package langext

import (
	"fmt"
	"strings"
)

func StrLimit(val string, maxlen int, suffix string) string {
	if len(val) > maxlen {
		return val[0:maxlen-len(suffix)] + suffix
	}
	return val
}

func StrSplit(val string, sep string, allowEmpty bool) []string {
	var arr []string
	for _, k := range strings.Split(val, sep) {
		if allowEmpty || k != "" {
			arr = append(arr, k)
		}
	}
	return arr
}

func StrPadRight(str string, pad string, padlen int) string {
	if pad == "" {
		pad = " "
	}

	if len(str) >= padlen {
		return str
	}

	return str + strings.Repeat(pad, padlen-len(str))[0:(padlen-len(str))]
}

func StrPadLeft(str string, pad string, padlen int) string {
	if pad == "" {
		pad = " "
	}

	if len(str) >= padlen {
		return str
	}

	return strings.Repeat(pad, padlen-len(str))[0:(padlen-len(str))] + str
}

func DeRefStringer(v fmt.Stringer) *string {
	if v == nil {
		return nil
	} else {
		return Ptr(v.String())
	}
}

func ConvertStringerArray[T fmt.Stringer](inarr []T) []string {
	result := make([]string, 0, len(inarr))
	for _, v := range inarr {
		result = append(result, v.String())
	}
	return result
}

func StrRunePadLeft(str string, pad string, padlen int) string {
	if pad == "" {
		pad = " "
	}

	if len([]rune(str)) >= padlen {
		return str
	}

	return strings.Repeat(pad, padlen-len([]rune(str)))[0:(padlen-len([]rune(str)))] + str
}

func StrRunePadRight(str string, pad string, padlen int) string {
	if pad == "" {
		pad = " "
	}

	if len([]rune(str)) >= padlen {
		return str
	}

	return str + strings.Repeat(pad, padlen-len([]rune(str)))[0:(padlen-len([]rune(str)))]
}

func Indent(str string, pad string) string {
	eonl := strings.HasSuffix(str, "\n")
	if eonl {
		str = str[0 : len(str)-1]
	}
	r := ""
	for _, v := range strings.Split(str, "\n") {
		r += pad + v + "\n"
	}

	if !eonl {
		r = r[0 : len(r)-1]
	}

	return r
}

func NumToStringOpt[V IntConstraint](v *V, fallback string) string {
	if v == nil {
		return fallback
	} else {
		return fmt.Sprintf("%d", v)
	}
}

func StrRepeat(val string, count int) string {
	r := ""
	for i := 0; i < count; i++ {
		r += val
	}
	return r
}

func StrWrap(val string, linelen int, seperator string) string {
	res := ""

	for iPos := 0; ; {
		next := min(iPos+linelen, len(val))
		res += val[iPos:next]

		iPos = next
		if iPos >= len(val) {
			break
		}

		res += seperator
	}

	return res
}