package ui

// RuneStylesheet maps runes to stylings.
type RuneStylesheet map[rune]Styling

// MarkLines provides a way to construct a styled text by separating the content
// and the styling.
//
// The arguments are groups of either
//
// * A single string, in which case it represents an unstyled line;
//
// * Three arguments that can be passed to MarkLine, in which case they are passed
//   to MarkLine and the return value is used as a styled line.
//
// Lines represented by all the groups are joined together.
//
// This function is mainly useful for constructing multi-line Text's with
// alignment across those lines. An example:
//
//   var stylesheet = map[rune]string{
//       '-': Reverse,
//       'x': Stylings(Blue, BgGreen),
//   }
//   var text = FromMarkedLines(
//       "foo      bar      foobar", stylesheet,
//       "---      xxx      ------"
//       "lorem    ipsum    dolar",
//   )
func ( ...interface{}) Text {
	var  Text
	for  := 0;  < len(); ++ {
		,  := [].(string)
		if ! {
			// TODO(xiaq): Surface the error.
			continue
		}
		if +2 < len() {
			if ,  := [+1].(RuneStylesheet);  {
				if ,  := [+2].(string);  {
					 = Concat(, MarkText(, , ))
					 += 2
					continue
				}
			}
		}
		 = Concat(, T())
	}
	return 
}

// MarkText applies styles to all the runes in the line, using the runes in
// the style string. The stylesheet argument specifies which style each rune
// represents.
func ( string,  RuneStylesheet,  string) Text {
	var  Text
	 := toRuns()
	for ,  := range  {
		 := bytesForFirstNRunes(, .n)
		 = Concat(, T([:], [.r]))
		 = [:]
	}
	if len() > 0 {
		 = Concat(, T())
	}
	return 
}

type run struct {
	r rune
	n int
}

func ( string) []run {
	var  []run
	 := run{}
	for ,  := range  {
		if  != .r {
			if .n > 0 {
				 = append(, )
			}
			 = run{, 1}
		} else {
			.n++
		}
	}
	if .n > 0 {
		 = append(, )
	}
	return 
}

func ( string,  int) int {
	 := 0
	for  := range  {
		if  ==  {
			return 
		}
		++
	}
	return len()
}