package syntax

import (
	"strings"

	"github.com/rivo/uniseg"
)

type graphemeInfo struct {
	column int
	line   int
	start  int
	end    int
}

func (g *graphemeInfo) Column() int {
	return g.column
}

func (g *graphemeInfo) Line() int {
	return g.line
}

func (g *graphemeInfo) Start() int {
	return g.start
}

func (g *graphemeInfo) End() int {
	return g.end
}

type index struct {
	Graphemes []graphemeInfo
	Lines     []string
}

func NewIndex(input string) index {
	graphemeIndex := make([]graphemeInfo, len(input))
	graphemes := uniseg.NewGraphemes(input)
	column := 0
	line := 0
	lines := []string{}
	lineStartPos := 0
	currentPos := 0

	for graphemes.Next() {
		start, end := graphemes.Positions()
		info := graphemeInfo{column, line, start, end}

		if column == 0 {
			lineStartPos = start
		}
		currentPos = end

		for i := start; i < end; i++ {
			graphemeIndex[i] = info
		}

		column++
		if graphemes.Str() == "\n" || graphemes.Str() == "\r\n" {
			line++
			column = 0
			lines = append(lines, strings.TrimRight(input[lineStartPos:currentPos], "\r\n"))
		}
	}

	lines = append(lines, strings.TrimRight(input[lineStartPos:], "\r\n"))

	return index{Graphemes: graphemeIndex, Lines: lines}
}
