package ask

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func raw[T any](query string, to byte, validate func(string) (v T, msg string)) T {
	fmt.Println(query)
	reader := bufio.NewReader(os.Stdin)
	for {
		text, _ := reader.ReadString(to)
		v, msg := validate(strings.TrimSpace(text[:len(text)-1]))

		if msg == "" {
			return v
		}
		fmt.Println(msg)
	}
}

func String(query string, min, max int) string {
	return raw(query, '\n', func(s string) (v string, msg string) {
		v = s

		if min >= 0 && len(v) < min {
			msg = fmt.Sprintf("your input is to short. Minimum length is %d", min)
			return v, msg
		}
		if max >= 0 && len(v) > max {
			msg = fmt.Sprintf("your input is to long. Maximum length is %d", min)
			return v, msg
		}
		return v, msg
	})
}

func StringSlice(query string, min, max, smin, smax int) []string {
	return raw(query, ';', func(s string) (v []string, msg string) {
		splits := strings.Split(s, ",")
		v = make([]string, 0, len(splits))
		for _, split := range splits {
			v = append(v, strings.TrimSpace(split))
		}

		if min >= 0 && len(v) < min {
			msg = fmt.Sprintf("your input is to short. Minimum length is %d", min)
		}
		if max >= 0 && len(v) > max {
			msg = fmt.Sprintf("your input is to long. Maximum length is %d", max)
		}
		for i, s := range v {
			if smin >= 0 && len(s) < smin {
				msg = fmt.Sprintf("your is value at index %d is to short. Minimum length is %d", i, smin)
			}
			if smax >= 0 && len(s) > smax {
				msg = fmt.Sprintf("your is value at index %d is to long. Maximum length is %d", i, smax)
			}
		}

		return v, msg
	})
}

func Boolean(query string, def bool) bool {
	if def {
		query += " (Y/n)"
	} else {
		query += " (y/N)"
	}
	return raw(query, '\n', func(s string) (v bool, msg string) {
		s = strings.ToLower(s)

		if s == "" {
			v = def
			return v, msg
		}

		if s == "y" {
			v = true
			return v, msg
		}
		if s == "n" {
			v = false
			return v, msg
		}

		msg = `your answer must be "y" "n" or enter for default`
		return v, msg
	})
}
