// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package bidi

import "log"

// This implementation is a port based on the reference implementation found at:
// http://www.unicode.org/Public/PROGRAMS/BidiReferenceJava/
//
// described in Unicode Bidirectional Algorithm (UAX #9).
//
// Input:
// There are two levels of input to the algorithm, since clients may prefer to
// supply some information from out-of-band sources rather than relying on the
// default behavior.
//
// - Bidi class array
// - Bidi class array, with externally supplied base line direction
//
// Output:
// Output is separated into several stages:
//
//  - levels array over entire paragraph
//  - reordering array over entire paragraph
//  - levels array over line
//  - reordering array over line
//
// Note that for conformance to the Unicode Bidirectional Algorithm,
// implementations are only required to generate correct reordering and
// character directionality (odd or even levels) over a line. Generating
// identical level arrays over a line is not required. Bidi explicit format
// codes (LRE, RLE, LRO, RLO, PDF) and BN can be assigned arbitrary levels and
// positions as long as the rest of the input is properly reordered.
//
// As the algorithm is defined to operate on a single paragraph at a time, this
// implementation is written to handle single paragraphs. Thus rule P1 is
// presumed by this implementation-- the data provided to the implementation is
// assumed to be a single paragraph, and either contains no 'B' codes, or a
// single 'B' code at the end of the input. 'B' is allowed as input to
// illustrate how the algorithm assigns it a level.
//
// Also note that rules L3 and L4 depend on the rendering engine that uses the
// result of the bidi algorithm. This implementation assumes that the rendering
// engine expects combining marks in visual order (e.g. to the left of their
// base character in RTL runs) and that it adjusts the glyphs used to render
// mirrored characters that are in RTL runs so that they render appropriately.

// level is the embedding level of a character. Even embedding levels indicate
// left-to-right order and odd levels indicate right-to-left order. The special
// level of -1 is reserved for undefined order.
type level int8

const implicitLevel level = -1

// in returns if x is equal to any of the values in set.
func (c class) in(set ...class) bool {
	for _, s := range set {
		if c == s {
			return true
		}
	}
	return false
}

// A paragraph contains the state of a paragraph.
type paragraph struct {
	initialTypes []class

	// Arrays of properties needed for paired bracket evaluation in N0
	pairTypes  []bracketType // paired Bracket types for paragraph
	pairValues []rune        // rune for opening bracket or pbOpen and pbClose; 0 for pbNone

	embeddingLevel level // default: = implicitLevel;

	// at the paragraph levels
	resultTypes  []class
	resultLevels []level

	// Index of matching PDI for isolate initiator characters. For other
	// characters, the value of matchingPDI will be set to -1. For isolate
	// initiators with no matching PDI, matchingPDI will be set to the length of
	// the input string.
	matchingPDI []int

	// Index of matching isolate initiator for PDI characters. For other
	// characters, and for PDIs with no matching isolate initiator, the value of
	// matchingIsolateInitiator will be set to -1.
	matchingIsolateInitiator []int
}

// newParagraph initializes a paragraph. The user needs to supply a few arrays
// corresponding to the preprocessed text input. The types correspond to the
// Unicode BiDi classes for each rune. pairTypes indicates the bracket type for
// each rune. pairValues provides a unique bracket class identifier for each
// rune (suggested is the rune of the open bracket for opening and matching
// close brackets, after normalization). The embedding levels are optional, but
// may be supplied to encode embedding levels of styled text.
//
// TODO: return an error.
func newParagraph(types []class, pairTypes []bracketType, pairValues []rune, levels level) *paragraph {
	validateTypes(types)
	validatePbTypes(pairTypes)
	validatePbValues(pairValues, pairTypes)
	validateParagraphEmbeddingLevel(levels)

	p := &paragraph{
		initialTypes:   append([]class(nil), types...),
		embeddingLevel: levels,

		pairTypes:  pairTypes,
		pairValues: pairValues,

		resultTypes: append([]class(nil), types...),
	}
	p.run()
	return p
}

func (p *paragraph) Len() int { return len(p.initialTypes) }

// The algorithm. Does not include line-based processing (Rules L1, L2).
// These are applied later in the line-based phase of the algorithm.
func (p *paragraph) run() {
	p.determineMatchingIsolates()

	// 1) determining the paragraph level
	// Rule P1 is the requirement for entering this algorithm.
	// Rules P2, P3.
	// If no externally supplied paragraph embedding level, use default.
	if p.embeddingLevel == implicitLevel {
		p.embeddingLevel = p.determineParagraphEmbeddingLevel(0, p.Len())
	}

	// Initialize result levels to paragraph embedding level.
	p.resultLevels = make([]level, p.Len())
	setLevels(p.resultLevels, p.embeddingLevel)

	// 2) Explicit levels and directions
	// Rules X1-X8.
	p.determineExplicitEmbeddingLevels()

	// Rule X9.
	// We do not remove the embeddings, the overrides, the PDFs, and the BNs
	// from the string explicitly. But they are not copied into isolating run
	// sequences when they are created, so they are removed for all
	// practical purposes.

	// Rule X10.
	// Run remainder of algorithm one isolating run sequence at a time
	for _, seq := range p.determineIsolatingRunSequences() {
		// 3) resolving weak types
		// Rules W1-W7.
		seq.resolveWeakTypes()

		// 4a) resolving paired brackets
		// Rule N0
		resolvePairedBrackets(seq)

		// 4b) resolving neutral types
		// Rules N1-N3.
		seq.resolveNeutralTypes()

		// 5) resolving implicit embedding levels
		// Rules I1, I2.
		seq.resolveImplicitLevels()

		// Apply the computed levels and types
		seq.applyLevelsAndTypes()
	}

	// Assign appropriate levels to 'hide' LREs, RLEs, LROs, RLOs, PDFs, and
	// BNs. This is for convenience, so the resulting level array will have
	// a value for every character.
	p.assignLevelsToCharactersRemovedByX9()
}

// determineMatchingIsolates determines the matching PDI for each isolate
// initiator and vice versa.
//
// Definition BD9.
//
// At the end of this function:
//
//  - The member variable matchingPDI is set to point to the index of the
//    matching PDI character for each isolate initiator character. If there is
//    no matching PDI, it is set to the length of the input text. For other
//    characters, it is set to -1.
//  - The member variable matchingIsolateInitiator is set to point to the
//    index of the matching isolate initiator character for each PDI character.
//    If there is no matching isolate initiator, or the character is not a PDI,
//    it is set to -1.
func (p *paragraph) determineMatchingIsolates() {
	p.matchingPDI = make([]int, p.Len())
	p.matchingIsolateInitiator = make([]int, p.Len())

	for i := range p.matchingIsolateInitiator {
		p.matchingIsolateInitiator[i] = -1
	}

	for i := range p.matchingPDI {
		p.matchingPDI[i] = -1

		if t := p.resultTypes[i]; t.in(_LRI, _RLI, _FSI) {
			depthCounter := 1
			for j := i + 1; j < p.Len(); j++ {
				if u := p.resultTypes[j]; u.in(_LRI, _RLI, _FSI) {
					depthCounter++
				} else if u == _PDI {
					if depthCounter--; depthCounter == 0 {
						p.matchingPDI[i] = j
						p.matchingIsolateInitiator[j] = i
						break
					}
				}
			}
			if p.matchingPDI[i] == -1 {
				p.matchingPDI[i] = p.Len()
			}
		}
	}
}

// determineParagraphEmbeddingLevel reports the resolved paragraph direction of
// the substring limited by the given range [start, end).
//
// Determines the paragraph level based on rules P2, P3. This is also used
// in rule X5c to find if an FSI should resolve to LRI or RLI.
func (p *paragraph) determineParagraphEmbeddingLevel(start, end int) level {
	var strongType class = -1 // unknown

	// Rule P2.
	for i := start; i < end; i++ {
		if t := p.resultTypes[i]; t.in(_L, _AL, _R) {
			strongType = t
			break
		} else if t.in(_FSI, _LRI, _RLI) {
			i = p.matchingPDI[i] // skip over to the matching PDI
			if i > end {
				log.Panic("assert (i <= end)")
			}
		}
	}
	// Rule P3.
	switch strongType {
	case -1: // none found
		// default embedding level when no strong types found is 0.
		return 0
	case _L:
		return 0
	default: // AL, R
		return 1
	}
}

const maxDepth = 125

// This stack will store the embedding levels and override and isolated
// statuses
type directionalStatusStack struct {
	stackCounter        int
	embeddingLevelStack [maxDepth + 1]level
	overrideStatusStack [maxDepth + 1]class
	isolateStatusStack  [maxDepth + 1]bool
}

func (s *directionalStatusStack) empty()     { s.stackCounter = 0 }
func (s *directionalStatusStack) pop()       { s.stackCounter-- }
func (s *directionalStatusStack) depth() int { return s.stackCounter }

func (s *directionalStatusStack) push(level level, overrideStatus class, isolateStatus bool) {
	s.embeddingLevelStack[s.stackCounter] = level
	s.overrideStatusStack[s.stackCounter] = overrideStatus
	s.isolateStatusStack[s.stackCounter] = isolateStatus
	s.stackCounter++
}

func (s *directionalStatusStack) lastEmbeddingLevel() level {
	return s.embeddingLevelStack[s.stackCounter-1]
}

func (s *directionalStatusStack) lastDirectionalOverrideStatus() class {
	return s.overrideStatusStack[s.stackCounter-1]
}

func (s *directionalStatusStack) lastDirectionalIsolateStatus() bool {
	return s.isolateStatusStack[s.stackCounter-1]
}

// Determine explicit levels using rules X1 - X8
func (p *paragraph) determineExplicitEmbeddingLevels() {
	var stack directionalStatusStack
	var overflowIsolateCount, overflowEmbeddingCount, validIsolateCount int

	// Rule X1.
	stack.push(p.embeddingLevel, _ON, false)

	for i, t := range p.resultTypes {
		// Rules X2, X3, X4, X5, X5a, X5b, X5c
		switch t {
		case _RLE, _LRE, _RLO, _LRO, _RLI, _LRI, _FSI:
			isIsolate := t.in(_RLI, _LRI, _FSI)
			isRTL := t.in(_RLE, _RLO, _RLI)

			// override if this is an FSI that resolves to RLI
			if t == _FSI {
				isRTL = (p.determineParagraphEmbeddingLevel(i+1, p.matchingPDI[i]) == 1)
			}
			if isIsolate {
				p.resultLevels[i] = stack.lastEmbeddingLevel()
			}

			var newLevel level
			if isRTL {
				// least greater odd
				newLevel = (stack.lastEmbeddingLevel() + 1) | 1
			} else {
				// least greater even
				newLevel = (stack.lastEmbeddingLevel() + 2) &^ 1
			}

			if newLevel <= maxDepth && overflowIsolateCount == 0 && overflowEmbeddingCount == 0 {
				if isIsolate {
					validIsolateCount++
				}
				// Push new embedding level, override status, and isolated
				// status.
				// No check for valid stack counter, since the level check
				// suffices.
				switch t {
				case _LRO:
					stack.push(newLevel, _L, isIsolate)
				case _RLO:
					stack.push(newLevel, _R, isIsolate)
				default:
					stack.push(newLevel, _ON, isIsolate)
				}
				// Not really part of the spec
				if !isIsolate {
					p.resultLevels[i] = newLevel
				}
			} else {
				// This is an invalid explicit formatting character,
				// so apply the "Otherwise" part of rules X2-X5b.
				if isIsolate {
					overflowIsolateCount++
				} else { // !isIsolate
					if overflowIsolateCount == 0 {
						overflowEmbeddingCount++
					}
				}
			}

		// Rule X6a
		case _PDI:
			if overflowIsolateCount > 0 {
				overflowIsolateCount--
			} else if validIsolateCount == 0 {
				// do nothing
			} else {
				overflowEmbeddingCount = 0
				for !stack.lastDirectionalIsolateStatus() {
					stack.pop()
				}
				stack.pop()
				validIsolateCount--
			}
			p.resultLevels[i] = stack.lastEmbeddingLevel()

		// Rule X7
		case _PDF:
			// Not really part of the spec
			p.resultLevels[i] = stack.lastEmbeddingLevel()

			if overflowIsolateCount > 0 {
				// do nothing
			} else if overflowEmbeddingCount > 0 {
				overflowEmbeddingCount--
			} else if !stack.lastDirectionalIsolateStatus() && stack.depth() >= 2 {
				stack.pop()
			}

		case _B: // paragraph separator.
			// Rule X8.

			// These values are reset for clarity, in this implementation B
			// can only occur as the last code in the array.
			stack.empty()
			overflowIsolateCount = 0
			overflowEmbeddingCount = 0
			validIsolateCount = 0
			p.resultLevels[i] = p.embeddingLevel

		default:
			p.resultLevels[i] = stack.lastEmbeddingLevel()
			if stack.lastDirectionalOverrideStatus() != _ON {
				p.resultTypes[i] = stack.lastDirectionalOverrideStatus()
			}
		}
	}
}

type isolatingRunSequence struct {
	p *paragraph

	indexes []int // indexes to the original string

	types          []class // type of each character using the index
	resolvedLevels []level // resolved levels after application of rules
	level          level
	sos, eos       class
}

func (i *isolatingRunSequence) Len() int { return len(i.indexes) }

func maxLevel(a, b level) level {
	if a > b {
		return a
	}
	return b
}

// Rule X10, second bullet: Determine the start-of-sequence (sos) and end-of-sequence (eos) types,
// 			 either L or R, for each isolating run sequence.
func (p *paragraph) isolatingRunSequence(indexes []int) *isolatingRunSequence {
	length := len(indexes)
	types := make([]class, length)
	for i, x := range indexes {
		types[i] = p.resultTypes[x]
	}

	// assign level, sos and eos
	prevChar := indexes[0] - 1
	for prevChar >= 0 && isRemovedByX9(p.initialTypes[prevChar]) {
		prevChar--
	}
	prevLevel := p.embeddingLevel
	if prevChar >= 0 {
		prevLevel = p.resultLevels[prevChar]
	}

	var succLevel level
	lastType := types[length-1]
	if lastType.in(_LRI, _RLI, _FSI) {
		succLevel = p.embeddingLevel
	} else {
		// the first character after the end of run sequence
		limit := indexes[length-1] + 1
		for ; limit < p.Len() && isRemovedByX9(p.initialTypes[limit]); limit++ {

		}
		succLevel = p.embeddingLevel
		if limit < p.Len() {
			succLevel = p.resultLevels[limit]
		}
	}
	level := p.resultLevels[indexes[0]]
	return &isolatingRunSequence{
		p:       p,
		indexes: indexes,
		types:   types,
		level:   level,
		sos:     typeForLevel(maxLevel(prevLevel, level)),
		eos:     typeForLevel(maxLevel(succLevel, level)),
	}
}

// Resolving weak types Rules W1-W7.
//
// Note that some weak types (EN, AN) remain after this processing is
// complete.
func (s *isolatingRunSequence) resolveWeakTypes() {

	// on entry, only these types remain
	s.assertOnly(_L, _R, _AL, _EN, _ES, _ET, _AN, _CS, _B, _S, _WS, _ON, _NSM, _LRI, _RLI, _FSI, _PDI)

	// Rule W1.
	// Changes all NSMs.
	preceedingCharacterType := s.sos
	for i, t := range s.types {
		if t == _NSM {
			s.types[i] = preceedingCharacterType
		} else {
			if t.in(_LRI, _RLI, _FSI, _PDI) {
				preceedingCharacterType = _ON
			}
			preceedingCharacterType = t
		}
	}

	// Rule W2.
	// EN does not change at the start of the run, because sos != AL.
	for i, t := range s.types {
		if t == _EN {
			for j := i - 1; j >= 0; j-- {
				if t := s.types[j]; t.in(_L, _R, _AL) {
					if t == _AL {
						s.types[i] = _AN
					}
					break
				}
			}
		}
	}

	// Rule W3.
	for i, t := range s.types {
		if t == _AL {
			s.types[i] = _R
		}
	}

	// Rule W4.
	// Since there must be values on both sides for this rule to have an
	// effect, the scan skips the first and last value.
	//
	// Although the scan proceeds left to right, and changes the type
	// values in a way that would appear to affect the computations
	// later in the scan, there is actually no problem. A change in the
	// current value can only affect the value to its immediate right,
	// and only affect it if it is ES or CS. But the current value can
	// only change if the value to its right is not ES or CS. Thus
	// either the current value will not change, or its change will have
	// no effect on the remainder of the analysis.

	for i := 1; i < s.Len()-1; i++ {
		t := s.types[i]
		if t == _ES || t == _CS {
			prevSepType := s.types[i-1]
			succSepType := s.types[i+1]
			if prevSepType == _EN && succSepType == _EN {
				s.types[i] = _EN
			} else if s.types[i] == _CS && prevSepType == _AN && succSepType == _AN {
				s.types[i] = _AN
			}
		}
	}

	// Rule W5.
	for i, t := range s.types {
		if t == _ET {
			// locate end of sequence
			runStart := i
			runEnd := s.findRunLimit(runStart, _ET)

			// check values at ends of sequence
			t := s.sos
			if runStart > 0 {
				t = s.types[runStart-1]
			}
			if t != _EN {
				t = s.eos
				if runEnd < len(s.types) {
					t = s.types[runEnd]
				}
			}
			if t == _EN {
				setTypes(s.types[runStart:runEnd], _EN)
			}
			// continue at end of sequence
			i = runEnd
		}
	}

	// Rule W6.
	for i, t := range s.types {
		if t.in(_ES, _ET, _CS) {
			s.types[i] = _ON
		}
	}

	// Rule W7.
	for i, t := range s.types {
		if t == _EN {
			// set default if we reach start of run
			prevStrongType := s.sos
			for j := i - 1; j >= 0; j-- {
				t = s.types[j]
				if t == _L || t == _R { // AL's have been changed to R
					prevStrongType = t
					break
				}
			}
			if prevStrongType == _L {
				s.types[i] = _L
			}
		}
	}
}

// 6) resolving neutral types Rules N1-N2.
func (s *isolatingRunSequence) resolveNeutralTypes() {

	// on entry, only these types can be in resultTypes
	s.assertOnly(_L, _R, _EN, _AN, _B, _S, _WS, _ON, _RLI, _LRI, _FSI, _PDI)

	for i, t := range s.types {
		switch t {
		case _WS, _ON, _B, _S, _RLI, _LRI, _FSI, _PDI:
			// find bounds of run of neutrals
			runStart := i
			runEnd := s.findRunLimit(runStart, _B, _S, _WS, _ON, _RLI, _LRI, _FSI, _PDI)

			// determine effective types at ends of run
			var leadType, trailType class

			// Note that the character found can only be L, R, AN, or
			// EN.
			if runStart == 0 {
				leadType = s.sos
			} else {
				leadType = s.types[runStart-1]
				if leadType.in(_AN, _EN) {
					leadType = _R
				}
			}
			if runEnd == len(s.types) {
				trailType = s.eos
			} else {
				trailType = s.types[runEnd]
				if trailType.in(_AN, _EN) {
					trailType = _R
				}
			}

			var resolvedType class
			if leadType == trailType {
				// Rule N1.
				resolvedType = leadType
			} else {
				// Rule N2.
				// Notice the embedding level of the run is used, not
				// the paragraph embedding level.
				resolvedType = typeForLevel(s.level)
			}

			setTypes(s.types[runStart:runEnd], resolvedType)

			// skip over run of (former) neutrals
			i = runEnd
		}
	}
}

func setLevels(levels []level, newLevel level) {
	for i := range levels {
		levels[i] = newLevel
	}
}

func setTypes(types []class, newType class) {
	for i := range types {
		types[i] = newType
	}
}

// 7) resolving implicit embedding levels Rules I1, I2.
func (s *isolatingRunSequence) resolveImplicitLevels() {

	// on entry, only these types can be in resultTypes
	s.assertOnly(_L, _R, _EN, _AN)

	s.resolvedLevels = make([]level, len(s.types))
	setLevels(s.resolvedLevels, s.level)

	if (s.level & 1) == 0 { // even level
		for i, t := range s.types {
			// Rule I1.
			if t == _L {
				// no change
			} else if t == _R {
				s.resolvedLevels[i] += 1
			} else { // t == _AN || t == _EN
				s.resolvedLevels[i] += 2
			}
		}
	} else { // odd level
		for i, t := range s.types {
			// Rule I2.
			if t == _R {
				// no change
			} else { // t == _L || t == _AN || t == _EN
				s.resolvedLevels[i] += 1
			}
		}
	}
}

// Applies the levels and types resolved in rules W1-I2 to the
// resultLevels array.
func (s *isolatingRunSequence) applyLevelsAndTypes() {
	for i, x := range s.indexes {
		s.p.resultTypes[x] = s.types[i]
		s.p.resultLevels[x] = s.resolvedLevels[i]
	}
}

// Return the limit of the run consisting only of the types in validSet
// starting at index. This checks the value at index, and will return
// index if that value is not in validSet.
func (s *isolatingRunSequence) findRunLimit(index int, validSet ...class) int {
loop:
	for ; index < len(s.types); index++ {
		t := s.types[index]
		for _, valid := range validSet {
			if t == valid {
				continue loop
			}
		}
		return index // didn't find a match in validSet
	}
	return len(s.types)
}

// Algorithm validation. Assert that all values in types are in the
// provided set.
func (s *isolatingRunSequence) assertOnly(codes ...class) {
loop:
	for i, t := range s.types {
		for _, c := range codes {
			if t == c {
				continue loop
			}
		}
		log.Panicf("invalid bidi code %s present in assertOnly at position %d", t, s.indexes[i])
	}
}

// determineLevelRuns returns an array of level runs. Each level run is
// described as an array of indexes into the input string.
//
// Determines the level runs. Rule X9 will be applied in determining the
// runs, in the way that makes sure the characters that are supposed to be
// removed are not included in the runs.
func (p *paragraph) determineLevelRuns() [][]int {
	run := []int{}
	allRuns := [][]int{}
	currentLevel := implicitLevel

	for i := range p.initialTypes {
		if !isRemovedByX9(p.initialTypes[i]) {
			if p.resultLevels[i] != currentLevel {
				// we just encountered a new run; wrap up last run
				if currentLevel >= 0 { // only wrap it up if there was a run
					allRuns = append(allRuns, run)
					run = nil
				}
				// Start new run
				currentLevel = p.resultLevels[i]
			}
			run = append(run, i)
		}
	}
	// Wrap up the final run, if any
	if len(run) > 0 {
		allRuns = append(allRuns, run)
	}
	return allRuns
}

// Definition BD13. Determine isolating run sequences.
func (p *paragraph) determineIsolatingRunSequences() []*isolatingRunSequence {
	levelRuns := p.determineLevelRuns()

	// Compute the run that each character belongs to
	runForCharacter := make([]int, p.Len())
	for i, run := range levelRuns {
		for _, index := range run {
			runForCharacter[index] = i
		}
	}

	sequences := []*isolatingRunSequence{}

	var currentRunSequence []int

	for _, run := range levelRuns {
		first := run[0]
		if p.initialTypes[first] != _PDI || p.matchingIsolateInitiator[first] == -1 {
			currentRunSequence = nil
			// int run = i;
			for {
				// Copy this level run into currentRunSequence
				currentRunSequence = append(currentRunSequence, run...)

				last := currentRunSequence[len(currentRunSequence)-1]
				lastT := p.initialTypes[last]
				if lastT.in(_LRI, _RLI, _FSI) && p.matchingPDI[last] != p.Len() {
					run = levelRuns[runForCharacter[p.matchingPDI[last]]]
				} else {
					break
				}
			}
			sequences = append(sequences, p.isolatingRunSequence(currentRunSequence))
		}
	}
	return sequences
}

// Assign level information to characters removed by rule X9. This is for
// ease of relating the level information to the original input data. Note
// that the levels assigned to these codes are arbitrary, they're chosen so
// as to avoid breaking level runs.
func (p *paragraph) assignLevelsToCharactersRemovedByX9() {
	for i, t := range p.initialTypes {
		if t.in(_LRE, _RLE, _LRO, _RLO, _PDF, _BN) {
			p.resultTypes[i] = t
			p.resultLevels[i] = -1
		}
	}
	// now propagate forward the levels information (could have
	// propagated backward, the main thing is not to introduce a level
	// break where one doesn't already exist).

	if p.resultLevels[0] == -1 {
		p.resultLevels[0] = p.embeddingLevel
	}
	for i := 1; i < len(p.initialTypes); i++ {
		if p.resultLevels[i] == -1 {
			p.resultLevels[i] = p.resultLevels[i-1]
		}
	}
	// Embedding information is for informational purposes only so need not be
	// adjusted.
}

//
// Output
//

// getLevels computes levels array breaking lines at offsets in linebreaks.
// Rule L1.
//
// The linebreaks array must include at least one value. The values must be
// in strictly increasing order (no duplicates) between 1 and the length of
// the text, inclusive. The last value must be the length of the text.
func (p *paragraph) getLevels(linebreaks []int) []level {
	// Note that since the previous processing has removed all
	// P, S, and WS values from resultTypes, the values referred to
	// in these rules are the initial types, before any processing
	// has been applied (including processing of overrides).
	//
	// This example implementation has reinserted explicit format codes
	// and BN, in order that the levels array correspond to the
	// initial text. Their final placement is not normative.
	// These codes are treated like WS in this implementation,
	// so they don't interrupt sequences of WS.

	validateLineBreaks(linebreaks, p.Len())

	result := append([]level(nil), p.resultLevels...)

	// don't worry about linebreaks since if there is a break within
	// a series of WS values preceding S, the linebreak itself
	// causes the reset.
	for i, t := range p.initialTypes {
		if t.in(_B, _S) {
			// Rule L1, clauses one and two.
			result[i] = p.embeddingLevel

			// Rule L1, clause three.
			for j := i - 1; j >= 0; j-- {
				if isWhitespace(p.initialTypes[j]) { // including format codes
					result[j] = p.embeddingLevel
				} else {
					break
				}
			}
		}
	}

	// Rule L1, clause four.
	start := 0
	for _, limit := range linebreaks {
		for j := limit - 1; j >= start; j-- {
			if isWhitespace(p.initialTypes[j]) { // including format codes
				result[j] = p.embeddingLevel
			} else {
				break
			}
		}
		start = limit
	}

	return result
}

// getReordering returns the reordering of lines from a visual index to a
// logical index for line breaks at the given offsets.
//
// Lines are concatenated from left to right. So for example, the fifth
// character from the left on the third line is
//
// 		getReordering(linebreaks)[linebreaks[1] + 4]
//
// (linebreaks[1] is the position after the last character of the second
// line, which is also the index of the first character on the third line,
// and adding four gets the fifth character from the left).
//
// The linebreaks array must include at least one value. The values must be
// in strictly increasing order (no duplicates) between 1 and the length of
// the text, inclusive. The last value must be the length of the text.
func (p *paragraph) getReordering(linebreaks []int) []int {
	validateLineBreaks(linebreaks, p.Len())

	return computeMultilineReordering(p.getLevels(linebreaks), linebreaks)
}

// Return multiline reordering array for a given level array. Reordering
// does not occur across a line break.
func computeMultilineReordering(levels []level, linebreaks []int) []int {
	result := make([]int, len(levels))

	start := 0
	for _, limit := range linebreaks {
		tempLevels := make([]level, limit-start)
		copy(tempLevels, levels[start:])

		for j, order := range computeReordering(tempLevels) {
			result[start+j] = order + start
		}
		start = limit
	}
	return result
}

// Return reordering array for a given level array. This reorders a single
// line. The reordering is a visual to logical map. For example, the
// leftmost char is string.charAt(order[0]). Rule L2.
func computeReordering(levels []level) []int {
	result := make([]int, len(levels))
	// initialize order
	for i := range result {
		result[i] = i
	}

	// locate highest level found on line.
	// Note the rules say text, but no reordering across line bounds is
	// performed, so this is sufficient.
	highestLevel := level(0)
	lowestOddLevel := level(maxDepth + 2)
	for _, level := range levels {
		if level > highestLevel {
			highestLevel = level
		}
		if level&1 != 0 && level < lowestOddLevel {
			lowestOddLevel = level
		}
	}

	for level := highestLevel; level >= lowestOddLevel; level-- {
		for i := 0; i < len(levels); i++ {
			if levels[i] >= level {
				// find range of text at or above this level
				start := i
				limit := i + 1
				for limit < len(levels) && levels[limit] >= level {
					limit++
				}

				for j, k := start, limit-1; j < k; j, k = j+1, k-1 {
					result[j], result[k] = result[k], result[j]
				}
				// skip to end of level run
				i = limit
			}
		}
	}

	return result
}

// isWhitespace reports whether the type is considered a whitespace type for the
// line break rules.
func isWhitespace(c class) bool {
	switch c {
	case _LRE, _RLE, _LRO, _RLO, _PDF, _LRI, _RLI, _FSI, _PDI, _BN, _WS:
		return true
	}
	return false
}

// isRemovedByX9 reports whether the type is one of the types removed in X9.
func isRemovedByX9(c class) bool {
	switch c {
	case _LRE, _RLE, _LRO, _RLO, _PDF, _BN:
		return true
	}
	return false
}

// typeForLevel reports the strong type (L or R) corresponding to the level.
func typeForLevel(level level) class {
	if (level & 0x1) == 0 {
		return _L
	}
	return _R
}

// TODO: change validation to not panic

func validateTypes(types []class) {
	if len(types) == 0 {
		log.Panic("types is null")
	}
	for i, t := range types[:len(types)-1] {
		if t == _B {
			log.Panicf("B type before end of paragraph at index: %d", i)
		}
	}
}

func validateParagraphEmbeddingLevel(embeddingLevel level) {
	if embeddingLevel != implicitLevel &&
		embeddingLevel != 0 &&
		embeddingLevel != 1 {
		log.Panicf("illegal paragraph embedding level: %d", embeddingLevel)
	}
}

func validateLineBreaks(linebreaks []int, textLength int) {
	prev := 0
	for i, next := range linebreaks {
		if next <= prev {
			log.Panicf("bad linebreak: %d at index: %d", next, i)
		}
		prev = next
	}
	if prev != textLength {
		log.Panicf("last linebreak was %d, want %d", prev, textLength)
	}
}

func validatePbTypes(pairTypes []bracketType) {
	if len(pairTypes) == 0 {
		log.Panic("pairTypes is null")
	}
	for i, pt := range pairTypes {
		switch pt {
		case bpNone, bpOpen, bpClose:
		default:
			log.Panicf("illegal pairType value at %d: %v", i, pairTypes[i])
		}
	}
}

func validatePbValues(pairValues []rune, pairTypes []bracketType) {
	if pairValues == nil {
		log.Panic("pairValues is null")
	}
	if len(pairTypes) != len(pairValues) {
		log.Panic("pairTypes is different length from pairValues")
	}
}
