package ui

import (
	
	
	
	

	
	
)

// Text contains of a list of styled Segments.
type Text []*Segment

// T constructs a new Text with the given content and the given Styling's
// applied.
func ( string,  ...Styling) Text {
	return StyleText(Text{&Segment{Text: }}, ...)
}

// Concat concatenates multiple Text's into one.
func ( ...Text) Text {
	var  Text
	for ,  := range  {
		 = append(, ...)
	}
	return 
}

// Kind returns "styled-text".
func (Text) () string { return "ui:text" }

// Repr returns the representation of the current Text. It is just a wrapper
// around the containing Segments.
func ( Text) ( int) string {
	 := new(bytes.Buffer)
	for ,  := range  {
		.WriteString(.Repr( + 1))
	}
	return fmt.Sprintf("(ui:text %s)", .String())
}

// IterateKeys feeds the function with all valid indices of the styled-text.
func ( Text) ( func(interface{}) bool) {
	for  := 0;  < len(); ++ {
		if !(strconv.Itoa()) {
			break
		}
	}
}

// Index provides access to the underlying styled-segment.
func ( Text) ( interface{}) (interface{}, error) {
	,  := vals.ConvertListIndex(, len())
	if  != nil {
		return nil, 
	} else if .Slice {
		return [.Lower:.Upper], nil
	} else {
		return [.Lower], nil
	}
}

// Concat implements Text+string, Text+number, Text+Segment and Text+Text.
func ( Text) ( interface{}) (interface{}, error) {
	switch rhs := .(type) {
	case string:
		return Concat(, T()), nil
	case int, *big.Int, *big.Rat, float64:
		return Concat(, T(vals.ToString())), nil
	case *Segment:
		return Concat(, Text{}), nil
	case Text:
		return Concat(, ), nil
	}

	return nil, vals.ErrConcatNotImplemented
}

// RConcat implements string+Text and number+Text.
func ( Text) ( interface{}) (interface{}, error) {
	switch lhs := .(type) {
	case string:
		return Concat(T(), ), nil
	case int, *big.Int, *big.Rat, float64:
		return Concat(T(vals.ToString()), ), nil
	}

	return nil, vals.ErrConcatNotImplemented
}

// Partition partitions the Text at n indices into n+1 Text values.
func ( Text) ( ...int) []Text {
	 := make([]Text, len()+1)
	 := .Clone()
	for ,  := range  {
		 := 
		if  > 0 {
			 -= [-1]
		}
		for len() > 0 &&  > 0 {
			if len([0].Text) <=  {
				[] = append([], [0])
				 -= len([0].Text)
				 = [1:]
			} else {
				[] = append([], &Segment{[0].Style, [0].Text[:]})
				[0] = &Segment{[0].Style, [0].Text[:]}
				 = 0
			}
		}
	}
	if len() > 0 {
		// Don't use segs directly to avoid memory leak
		[len()] = append(Text(nil), ...)
	}
	return 
}

// Clone returns a deep copy of Text.
func ( Text) () Text {
	 := make(Text, len())
	for ,  := range  {
		[] = .Clone()
	}
	return 
}

// CountRune counts the number of times a rune occurs in a Text.
func ( Text) ( rune) int {
	 := 0
	for ,  := range  {
		 += .CountRune()
	}
	return 
}

// CountLines counts the number of lines in a Text. It is equal to
// t.CountRune('\n') + 1.
func ( Text) () int {
	return .CountRune('\n') + 1
}

// SplitByRune splits a Text by the given rune.
func ( Text) ( rune) []Text {
	// Call SplitByRune for each constituent Segment, and "paste" the pairs of
	// subsegments across the segment border. For instance, if Text has 3
	// Segments a, b, c that results in a1, a2, a3, b1, b2, c1, then a3 and b1
	// as well as b2 and c1 are pasted together, and the return value is [a1],
	// [a2], [a3, b1], [b2, c1]. Pasting can happen coalesce: for instance, if
	// Text has 3 Segments a, b, c that results in a1, a2, b1, c1, the return
	// value will be [a1], [a2, b1, c1].
	var  []Text
	var  Text
	for ,  := range  {
		 := .SplitByRune()
		if len() == 1 {
			// Only one subsegment. Just paste.
			 = append(, [0])
			continue
		}
		// Paste the previous trailing segments with the first subsegment, and
		// add it as a Text.
		 = append(, append(, [0]))
		// For the subsegments in the middle, just add then as is.
		for  := 1;  < len()-1; ++ {
			 = append(, Text{[]})
		}
		// The last segment becomes the new paste.
		 = Text{[len()-1]}
	}
	if len() > 0 {
		 = append(, )
	}
	return 
}

// TrimWcwidth returns the largest prefix of t that does not exceed the given
// visual width.
func ( Text) ( int) Text {
	var  Text
	for ,  := range  {
		 := wcwidth.Of(.Text)
		if  >=  {
			 = append(,
				&Segment{.Style, wcwidth.Trim(.Text, )})
			break
		}
		 -= 
		 = append(, )
	}
	return 
}

// String returns a string representation of the styled text. This now always
// assumes VT-style terminal output.
//
// TODO: Make string conversion sensible to environment, e.g. use HTML when
// output is web.
func ( Text) () string {
	return .VTString()
}

// VTString renders the styled text using VT-style escape sequences.
func ( Text) () string {
	var  bytes.Buffer
	for ,  := range  {
		.WriteString(.VTString())
	}
	return .String()
}