package term

import (
	

	
	
)

// BufferBuilder supports building of Buffer.
type BufferBuilder struct {
	Width, Col, Indent int
	// EagerWrap controls whether to wrap line as soon as the cursor reaches the
	// right edge of the terminal. This is not often desirable as it creates
	// unneessary line breaks, but is is useful when echoing the user input.
	// will otherwise
	EagerWrap bool
	// Lines the content of the buffer.
	Lines Lines
	// Dot is what the user perceives as the cursor.
	Dot Pos
}

// NewBufferBuilder makes a new BufferBuilder, initially with one empty line.
func ( int) *BufferBuilder {
	return &BufferBuilder{Width: , Lines: [][]Cell{make([]Cell, 0, )}}
}

func ( *BufferBuilder) () Pos {
	return Pos{len(.Lines) - 1, .Col}
}

// Buffer returns a Buffer built by the BufferBuilder.
func ( *BufferBuilder) () *Buffer {
	return &Buffer{.Width, .Lines, .Dot}
}

func ( *BufferBuilder) ( int) *BufferBuilder {
	.Indent = 
	return 
}

func ( *BufferBuilder) ( bool) *BufferBuilder {
	.EagerWrap = 
	return 
}

func ( *BufferBuilder) ( Pos) *BufferBuilder {
	.Dot = 
	return 
}

func ( *BufferBuilder) () *BufferBuilder {
	return .setDot(.Cursor())
}

func ( *BufferBuilder) () {
	.Lines = append(.Lines, make([]Cell, 0, .Width))
	.Col = 0
}

func ( *BufferBuilder) ( Cell) {
	 := len(.Lines)
	.Lines[-1] = append(.Lines[-1], )
	.Col += wcwidth.Of(.Text)
}

// Newline starts a newline.
func ( *BufferBuilder) () *BufferBuilder {
	.appendLine()

	if .Indent > 0 {
		for  := 0;  < .Indent; ++ {
			.appendCell(Cell{Text: " "})
		}
	}

	return 
}

// WriteRuneSGR writes a single rune to a buffer with an SGR style, wrapping the
// line when needed. If the rune is a control character, it will be written
// using the caret notation (like ^X) and gets the additional style of
// styleForControlChar.
func ( *BufferBuilder) ( rune,  string) *BufferBuilder {
	if  == '\n' {
		.Newline()
		return 
	}
	 := Cell{string(), }
	if  < 0x20 ||  == 0x7f {
		// Always show control characters in reverse video.
		if  != "" {
			 =  + ";7"
		} else {
			 = "7"
		}
		 = Cell{"^" + string(^0x40), }
	}

	if .Col+wcwidth.Of(.Text) > .Width {
		.Newline()
		.appendCell()
	} else {
		.appendCell()
		if .Col == .Width && .EagerWrap {
			.Newline()
		}
	}
	return 
}

// Write is equivalent to calling WriteStyled with ui.T(text, style...).
func ( *BufferBuilder) ( string,  ...ui.Styling) *BufferBuilder {
	return .WriteStyled(ui.T(, ...))
}

// WriteSpaces writes w spaces with the given styles.
func ( *BufferBuilder) ( int,  ...ui.Styling) *BufferBuilder {
	return .Write(strings.Repeat(" ", ), ...)
}

// DotHere is a special argument to MarkLines to mark the position of the dot.
var DotHere = struct{ x struct{} }{}

// MarkLines is like calling WriteStyled with ui.MarkLines(args...), but accepts
// an additional special parameter DotHere to mark the position of the dot.
func ( *BufferBuilder) ( ...interface{}) *BufferBuilder {
	for ,  := range  {
		if  == DotHere {
			return .WriteStyled(ui.MarkLines([:]...)).
				SetDotHere().WriteStyled(ui.MarkLines([+1:]...))
		}
	}
	return .WriteStyled(ui.MarkLines(...))
}

// WriteStringSGR writes a string to a buffer with a SGR style.
func ( *BufferBuilder) (,  string) *BufferBuilder {
	for ,  := range  {
		.WriteRuneSGR(, )
	}
	return 
}

// WriteStyled writes a styled text.
func ( *BufferBuilder) ( ui.Text) *BufferBuilder {
	for ,  := range  {
		.WriteStringSGR(.Text, .Style.SGR())
	}
	return 
}

func ( int) []Cell {
	 := make([]Cell, )
	for  := 0;  < ; ++ {
		[].Text = " "
	}
	return 
}