package uniseg

import 

// The states of the sentence break parser.
const (
	sbAny = iota
	sbCR
	sbParaSep
	sbATerm
	sbUpper
	sbLower
	sbSB7
	sbSB8Close
	sbSB8Sp
	sbSTerm
	sbSB8aClose
	sbSB8aSp
)

// The sentence break parser's breaking instructions.
const (
	sbDontBreak = iota
	sbBreak
)

// The sentence break parser's state transitions. It's anologous to
// grTransitions, see comments there for details. Unicode version 14.0.0.
var sbTransitions = map[[2]int][3]int{
	// SB3.
	{sbAny, prCR}: {sbCR, sbDontBreak, 9990},
	{sbCR, prLF}:  {sbParaSep, sbDontBreak, 30},

	// SB4.
	{sbAny, prSep}:     {sbParaSep, sbDontBreak, 9990},
	{sbAny, prLF}:      {sbParaSep, sbDontBreak, 9990},
	{sbParaSep, prAny}: {sbAny, sbBreak, 40},
	{sbCR, prAny}:      {sbAny, sbBreak, 40},

	// SB6.
	{sbAny, prATerm}:     {sbATerm, sbDontBreak, 9990},
	{sbATerm, prNumeric}: {sbAny, sbDontBreak, 60},
	{sbSB7, prNumeric}:   {sbAny, sbDontBreak, 60}, // Because ATerm also appears in SB7.

	// SB7.
	{sbAny, prUpper}:   {sbUpper, sbDontBreak, 9990},
	{sbAny, prLower}:   {sbLower, sbDontBreak, 9990},
	{sbUpper, prATerm}: {sbSB7, sbDontBreak, 70},
	{sbLower, prATerm}: {sbSB7, sbDontBreak, 70},
	{sbSB7, prUpper}:   {sbUpper, sbDontBreak, 70},

	// SB8a.
	{sbAny, prSTerm}:           {sbSTerm, sbDontBreak, 9990},
	{sbATerm, prSContinue}:     {sbAny, sbDontBreak, 81},
	{sbATerm, prATerm}:         {sbATerm, sbDontBreak, 81},
	{sbATerm, prSTerm}:         {sbSTerm, sbDontBreak, 81},
	{sbSB7, prSContinue}:       {sbAny, sbDontBreak, 81},
	{sbSB7, prATerm}:           {sbATerm, sbDontBreak, 81},
	{sbSB7, prSTerm}:           {sbSTerm, sbDontBreak, 81},
	{sbSB8Close, prSContinue}:  {sbAny, sbDontBreak, 81},
	{sbSB8Close, prATerm}:      {sbATerm, sbDontBreak, 81},
	{sbSB8Close, prSTerm}:      {sbSTerm, sbDontBreak, 81},
	{sbSB8Sp, prSContinue}:     {sbAny, sbDontBreak, 81},
	{sbSB8Sp, prATerm}:         {sbATerm, sbDontBreak, 81},
	{sbSB8Sp, prSTerm}:         {sbSTerm, sbDontBreak, 81},
	{sbSTerm, prSContinue}:     {sbAny, sbDontBreak, 81},
	{sbSTerm, prATerm}:         {sbATerm, sbDontBreak, 81},
	{sbSTerm, prSTerm}:         {sbSTerm, sbDontBreak, 81},
	{sbSB8aClose, prSContinue}: {sbAny, sbDontBreak, 81},
	{sbSB8aClose, prATerm}:     {sbATerm, sbDontBreak, 81},
	{sbSB8aClose, prSTerm}:     {sbSTerm, sbDontBreak, 81},
	{sbSB8aSp, prSContinue}:    {sbAny, sbDontBreak, 81},
	{sbSB8aSp, prATerm}:        {sbATerm, sbDontBreak, 81},
	{sbSB8aSp, prSTerm}:        {sbSTerm, sbDontBreak, 81},

	// SB9.
	{sbATerm, prClose}:     {sbSB8Close, sbDontBreak, 90},
	{sbSB7, prClose}:       {sbSB8Close, sbDontBreak, 90},
	{sbSB8Close, prClose}:  {sbSB8Close, sbDontBreak, 90},
	{sbATerm, prSp}:        {sbSB8Sp, sbDontBreak, 90},
	{sbSB7, prSp}:          {sbSB8Sp, sbDontBreak, 90},
	{sbSB8Close, prSp}:     {sbSB8Sp, sbDontBreak, 90},
	{sbSTerm, prClose}:     {sbSB8aClose, sbDontBreak, 90},
	{sbSB8aClose, prClose}: {sbSB8aClose, sbDontBreak, 90},
	{sbSTerm, prSp}:        {sbSB8aSp, sbDontBreak, 90},
	{sbSB8aClose, prSp}:    {sbSB8aSp, sbDontBreak, 90},
	{sbATerm, prSep}:       {sbParaSep, sbDontBreak, 90},
	{sbATerm, prCR}:        {sbParaSep, sbDontBreak, 90},
	{sbATerm, prLF}:        {sbParaSep, sbDontBreak, 90},
	{sbSB7, prSep}:         {sbParaSep, sbDontBreak, 90},
	{sbSB7, prCR}:          {sbParaSep, sbDontBreak, 90},
	{sbSB7, prLF}:          {sbParaSep, sbDontBreak, 90},
	{sbSB8Close, prSep}:    {sbParaSep, sbDontBreak, 90},
	{sbSB8Close, prCR}:     {sbParaSep, sbDontBreak, 90},
	{sbSB8Close, prLF}:     {sbParaSep, sbDontBreak, 90},
	{sbSTerm, prSep}:       {sbParaSep, sbDontBreak, 90},
	{sbSTerm, prCR}:        {sbParaSep, sbDontBreak, 90},
	{sbSTerm, prLF}:        {sbParaSep, sbDontBreak, 90},
	{sbSB8aClose, prSep}:   {sbParaSep, sbDontBreak, 90},
	{sbSB8aClose, prCR}:    {sbParaSep, sbDontBreak, 90},
	{sbSB8aClose, prLF}:    {sbParaSep, sbDontBreak, 90},

	// SB10.
	{sbSB8Sp, prSp}:  {sbSB8Sp, sbDontBreak, 100},
	{sbSB8aSp, prSp}: {sbSB8aSp, sbDontBreak, 100},
	{sbSB8Sp, prSep}: {sbParaSep, sbDontBreak, 100},
	{sbSB8Sp, prCR}:  {sbParaSep, sbDontBreak, 100},
	{sbSB8Sp, prLF}:  {sbParaSep, sbDontBreak, 100},

	// SB11.
	{sbATerm, prAny}:     {sbAny, sbBreak, 110},
	{sbSB7, prAny}:       {sbAny, sbBreak, 110},
	{sbSB8Close, prAny}:  {sbAny, sbBreak, 110},
	{sbSB8Sp, prAny}:     {sbAny, sbBreak, 110},
	{sbSTerm, prAny}:     {sbAny, sbBreak, 110},
	{sbSB8aClose, prAny}: {sbAny, sbBreak, 110},
	{sbSB8aSp, prAny}:    {sbAny, sbBreak, 110},
	// We'll always break after ParaSep due to SB4.
}

// transitionSentenceBreakState determines the new state of the sentence break
// parser given the current state and the next code point. It also returns
// whether a sentence boundary was detected. If more than one code point is
// needed to determine the new state, the byte slice or the string starting
// after rune "r" can be used (whichever is not nil or empty) for further
// lookups.
func transitionSentenceBreakState( int,  rune,  []byte,  string) ( int,  bool) {
	// Determine the property of the next character.
	 := property(sentenceBreakCodePoints, )

	// SB5 (Replacing Ignore Rules).
	if  == prExtend ||  == prFormat {
		if  == sbParaSep ||  == sbCR {
			return sbAny, true // Make sure we don't apply SB5 to SB3 or SB4.
		}
		if  < 0 {
			return sbAny, true // SB1.
		}
		return , false
	}

	// Find the applicable transition in the table.
	var  int
	,  := sbTransitions[[2]int{, }]
	if  {
		// We have a specific transition. We'll use it.
		, ,  = [0], [1] == sbBreak, [2]
	} else {
		// No specific transition found. Try the less specific ones.
		,  := sbTransitions[[2]int{, prAny}]
		,  := sbTransitions[[2]int{sbAny, }]
		if  &&  {
			// Both apply. We'll use a mix (see comments for grTransitions).
			, ,  = [0], [1] == sbBreak, [2]
			if [2] < [2] {
				,  = [1] == sbBreak, [2]
			}
		} else if  {
			// We only have a specific state.
			, ,  = [0], [1] == sbBreak, [2]
			// This branch will probably never be reached because okAnyState will
			// always be true given the current transition map. But we keep it here
			// for future modifications to the transition map where this may not be
			// true anymore.
		} else if  {
			// We only have a specific property.
			, ,  = [0], [1] == sbBreak, [2]
		} else {
			// No known transition. SB999: Any × Any.
			, ,  = sbAny, false, 9990
		}
	}

	// SB8.
	if  > 80 && ( == sbATerm ||  == sbSB8Close ||  == sbSB8Sp ||  == sbSB7) {
		// Check the right side of the rule.
		var  int
		for  != prOLetter &&
			 != prUpper &&
			 != prLower &&
			 != prSep &&
			 != prCR &&
			 != prLF &&
			 != prATerm &&
			 != prSTerm {
			// Move on to the next rune.
			if  != nil { // Byte slice version.
				,  = utf8.DecodeRune()
				 = [:]
			} else { // String version.
				,  = utf8.DecodeRuneInString()
				 = [:]
			}
			if  == utf8.RuneError {
				break
			}
			 = property(sentenceBreakCodePoints, )
		}
		if  == prLower {
			return sbLower, false
		}
	}

	return
}