package grammalecte

import (
	"bytes"
	"fmt"
	"strings"
	"unicode/utf8"
)

const LOG_PREFIX_LEN = 20

type SpellingError struct {
	Prefix      string
	Source      string
	NSource     int
	Start       int
	End         int
	Type        string
	Value       string
	Suggestions []string
}

func (e SpellingError) Error() string {
	suggestions := ""
	if len(e.Suggestions) > 0 {
		suggestions = "\nSuggestions : " + strings.Join(e.Suggestions, ", ")
	}

	return fmt.Sprintf(
		"%sspelling error %s %q (:spelling:%s)\n%q\n%s%s",
		e.Prefix,
		e.Type,
		e.Value,
		e.Value,
		e.Source,
		underline(1, e.Start, e.End),
		suggestions,
	)
}

type GrammarError struct {
	Prefix      string
	Source      string
	NSource     int
	Start       int
	End         int
	RuleId      string
	Type        string
	Message     string
	Suggestions []string
	URL         string
}

func (e GrammarError) Error() string {
	sornot := ""
	if len(e.Suggestions) > 1 {
		sornot = "s"
	}

	suggestions := ""
	if len(e.Suggestions) > 0 {
		suggestions = "\nSuggestion" + sornot + " : " + strings.Join(e.Suggestions, ", ")
	}

	return fmt.Sprintf(
		"%s%s (%d:%s)\n%q\n%s%s",
		e.Prefix,
		e.Message,
		e.NSource, e.RuleId,
		e.Source,
		underline(1, e.Start, e.End),
		suggestions,
	)
}

func (e GrammarError) GetPassage() string {
	nb := 0
	var ret []byte
	for _, r := range e.Source {
		if nb >= e.End {
			break
		}
		if nb >= e.Start {
			ret = utf8.AppendRune(ret, r)
		}
		nb += 1
	}

	return string(ret)
}

func underline(prefix, start, end int) string {
	var b bytes.Buffer

	for i := 0; i < prefix+start; i++ {
		b.Write([]byte{' '})
	}

	for i := 0; i < end-start; i++ {
		b.Write([]byte{'^'})
	}

	return b.String()
}
