package door

import (
	"bytes"
	"strconv"
	"strings"

	"golang.org/x/text/width"
)

// https://siongui.github.io/2016/03/23/go-utf8-string-width/

// Return width of Unicode rune.
func UnicodeWidth(r rune) int {
	p := width.LookupRune(r)
	if p.Kind() == width.EastAsianWide {
		return 2
	}
	return 1
}

// Delete an item from an array, returning item and true on success.
func ArrayDelete[T any](stack *[]T, pos int) (T, bool) {
	// log.Printf("Array %d, %d\n", len(*stack), cap(*stack))
	var result T
	/*
	   https://stackoverflow.com/questions/33834742/remove-and-adding-elements-to-array-in-go-lang
	   https://github.com/golang/go/wiki/SliceTricks
	*/
	if pos < 0 || pos > len(*stack) {
		return result, false
	}
	result = (*stack)[pos]
	copy((*stack)[pos:], (*stack)[pos+1:])
	// var temp T
	// (*stack)[len(*stack)-1] = temp
	*stack = (*stack)[:len(*stack)-1]
	return result, true
}

// Pop items from head of array, return true on success.
func ArrayPop[T any](stack *[]T, count int) bool {
	/*
	   https://stackoverflow.com/questions/33834742/remove-and-adding-elements-to-array-in-go-lang
	   https://github.com/golang/go/wiki/SliceTricks
	*/
	if count < 0 || count > len(*stack) {
		return false
	}

	copy((*stack)[0:], (*stack)[count:])
	// var temp T
	// (*stack)[len(*stack)-1] = temp
	*stack = (*stack)[:len(*stack)-count]
	return true
}

// Split string on separator, returning []int
func SplitToInt(input string, sep string) []int {
	var result []int
	for _, number := range strings.Split(input, sep) {
		v, err := strconv.Atoi(number)
		if err == nil {
			result = append(result, v)
		}
	}
	return result
}

// In unicode, a single character isn't always 1 char wide.
// This finds the actual length.

// Calculate the length of the given line, dealing with unicode.
func StringLen(s []byte) int {
	if Unicode {
		var len int
		var ubuff *bytes.Buffer = bytes.NewBuffer(s)
		for {
			r, _, err := ubuff.ReadRune()
			if err != nil {
				break
			}
			len += UnicodeWidth(r)
		}
		return len
	} else {
		return len(s)
	}
}