package ui

import (
	
	
	

	
)

// Segment is a string that has some style applied to it.
type Segment struct {
	Style
	Text string
}

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

// Repr returns the representation of this Segment. The string can be used to
// construct an identical Segment. Unset or default attributes are skipped. If
// the Segment represents an unstyled string only this string is returned.
func ( *Segment) (int) string {
	 := new(bytes.Buffer)
	 := func( string, ,  interface{}) {
		if  !=  {
			var  string
			if ,  := .(Color);  {
				 = .String()
			} else {
				 = vals.Repr(, 0)
			}
			fmt.Fprintf(, "&%s=%s ", , )
		}
	}

	("fg-color", .Foreground, nil)
	("bg-color", .Background, nil)
	("bold", .Bold, false)
	("dim", .Dim, false)
	("italic", .Italic, false)
	("underlined", .Underlined, false)
	("blink", .Blink, false)
	("inverse", .Inverse, false)

	if .Len() == 0 {
		return .Text
	}

	return fmt.Sprintf("(ui:text-segment %s %s)", .Text, strings.TrimSpace(.String()))
}

// IterateKeys feeds the function with all valid attributes of styled-segment.
func (*Segment) ( func( interface{}) bool) {
	vals.Feed(, "text", "fg-color", "bg-color", "bold", "dim", "italic", "underlined", "blink", "inverse")
}

// Index provides access to the attributes of a styled-segment.
func ( *Segment) ( interface{}) ( interface{},  bool) {
	switch  {
	case "text":
		 = .Text
	case "fg-color":
		if .Foreground == nil {
			return "default", true
		}
		return .Foreground.String(), true
	case "bg-color":
		if .Background == nil {
			return "default", true
		}
		return .Background.String(), true
	case "bold":
		 = .Bold
	case "dim":
		 = .Dim
	case "italic":
		 = .Italic
	case "underlined":
		 = .Underlined
	case "blink":
		 = .Blink
	case "inverse":
		 = .Inverse
	}

	return ,  != nil
}

// Concat implements Segment+string, Segment+float64, Segment+Segment and
// Segment+Text.
func ( *Segment) ( interface{}) (interface{}, error) {
	switch rhs := .(type) {
	case string:
		return Text{
			,
			&Segment{Text: },
		}, nil
	case float64:
		return Text{
			,
			&Segment{Text: vals.ToString()},
		}, nil
	case *Segment:
		return Text{, }, nil
	case Text:
		return Text(append([]*Segment{}, ...)), nil
	}

	return nil, vals.ErrConcatNotImplemented
}

// RConcat implements string+Segment and float64+Segment.
func ( *Segment) ( interface{}) (interface{}, error) {
	switch lhs := .(type) {
	case string:
		return Text{
			&Segment{Text: },
			,
		}, nil
	case float64:
		return Text{
			&Segment{Text: vals.ToString()},
			,
		}, nil
	}
	return nil, vals.ErrConcatNotImplemented
}

// Clone returns a copy of the Segment.
func ( *Segment) () *Segment {
	 := *
	return &
}

// CountRune counts the number of times a rune occurs in a Segment.
func ( *Segment) ( rune) int {
	return strings.Count(.Text, string())
}

// SplitByRune splits a Segment by the given rune.
func ( *Segment) ( rune) []*Segment {
	 := strings.Split(.Text, string())
	 := make([]*Segment, len())
	for ,  := range  {
		[] = &Segment{.Style, }
	}
	return 
}

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

// VTString renders the styled segment using VT-style escape sequences.
func ( *Segment) () string {
	 := .SGR()
	if  == "" {
		return .Text
	}
	return fmt.Sprintf("\033[%sm%s\033[m", , .Text)
}