package vtclean

type char struct {
	char  byte
	vt100 []byte
}

func chars(p []byte) []char {
	tmp := make([]char, len(p))
	for i, v := range p {
		tmp[i].char = v
	}
	return tmp
}

type lineEdit struct {
	buf       []char
	pos, size int
	vt100     []byte
}

func newLineEdit(length int) *lineEdit {
	return &lineEdit{buf: make([]char, length)}
}

func (l *lineEdit) Vt100(p []byte) {
	l.vt100 = p
}

func (l *lineEdit) Move(x int) {
	if x < 0 && l.pos <= -x {
		l.pos = 0
	} else if x > 0 && l.pos+x > l.size {
		l.pos = l.size
	} else {
		l.pos += x
	}
}

func (l *lineEdit) MoveAbs(x int) {
	if x < l.size {
		l.pos = x
	}
}

func (l *lineEdit) Write(p []byte) {
	c := chars(p)
	if len(c) > 0 {
		c[0].vt100 = l.vt100
		l.vt100 = nil
	}
	if len(l.buf)-l.pos < len(c) {
		l.buf = append(l.buf[:l.pos], c...)
	} else {
		copy(l.buf[l.pos:], c)
	}
	l.pos += len(c)
	if l.pos > l.size {
		l.size = l.pos
	}
}

func (l *lineEdit) Insert(p []byte) {
	c := chars(p)
	if len(c) > 0 {
		c[0].vt100 = l.vt100
		l.vt100 = nil
	}
	l.size += len(c)
	c = append(c, l.buf[l.pos:]...)
	l.buf = append(l.buf[:l.pos], c...)
}

func (l *lineEdit) Delete(n int) {
	most := l.size - l.pos
	if n > most {
		n = most
	}
	copy(l.buf[l.pos:], l.buf[l.pos+n:])
	l.size -= n
}

func (l *lineEdit) Clear() {
	for i := 0; i < len(l.buf); i++ {
		l.buf[i].char = ' '
	}
}
func (l *lineEdit) ClearLeft() {
	for i := 0; i < l.pos+1; i++ {
		l.buf[i].char = ' '
	}
}
func (l *lineEdit) ClearRight() {
	l.size = l.pos
}

func (l *lineEdit) Bytes() []byte {
	length := 0
	buf := l.buf[:l.size]
	for _, v := range buf {
		length += 1 + len(v.vt100)
	}
	tmp := make([]byte, 0, length)
	for _, v := range buf {
		tmp = append(tmp, v.vt100...)
		tmp = append(tmp, v.char)
	}
	return tmp
}

func (l *lineEdit) String() string {
	return string(l.Bytes())
}