package pin

import (
	"fmt"
	//"strconv"
	//"log"
	"surdeus.su/core/cli/mtool"
	"os"
)

var (
	Lflag bool
	lval int
	delim rune = '\n'
	nVal int
	chrs []rune
	Tool = mtool.T("pin").Func(Run).Desc(
		"print all the possible PIN combinations made of custom characters",
	).Usage(
		"",
	)
)

func Pow(x, p int) int {
	ret := 1 
	for i:=0 ; i<p ; i++ {
		ret *= x
	}
	return ret
}

func GetPin(s []rune, l int, i int) string {
	ret := ""
	slen := len(s)
	for j:=0 ; j<l ; j++ {
		ret = string(s[ ( i/Pow(slen, j) ) % slen] ) + ret
	}
	return ret
}

func printPins(s []rune, l int) {
	n := Pow(len(s), l)
	for i:=0 ; i<n ; i++ {
		pin := GetPin(s, l, i)
		if Fits([]rune(pin)) {
			fmt.Println(GetPin(s, l, i))
		}
	}
}

func Fits(s []rune) bool {
	a := make([]int, len(chrs))
	for i, v1 := range chrs {
		for _, v2 := range s {
			if v1 == v2 {
				a[i]++
				if a[i] > nVal {
					return false
				}
			}
		}
	}
	return true
}

func Run(flags *mtool.Flags) {
	var (
		length int
		rFlag bool
	)
	var (
		chrsString string 
		chrs []rune
	)

	flags.StringVar(
		&chrsString,
		"c",
		"0123456789",
		"character set for substitution",
		"COMBO_CHARS",
	)
	flags.IntVar(
		&lval, "min", 1,
		"min length of the output pins",
	)
	flags.BoolVar(
		&Lflag, "m", false,
		"set the '-min' flag value to 1 (overrides the '-min' it)",
	)
	flags.IntVar(
		&length, "max", 0,
		"max length of the output pins",
	)

	flags.IntVar(&nVal, "rep", 1, "max repeats of the rune." )
	flags.BoolVar(&rFlag, "R", false, "make the maximum repeat equal to the length of input chars" )

	_ = flags.Parse()

	/*if len(args) == 0 {
		flags.Usage()
		os.Exit(1)
	}*/

	chrs = []rune(chrsString)

	if length == 0 {
		length = 4
	}

	if Lflag {
		lval = 1
	}

	if rFlag {
		nVal = len(chrs)
	}

	if lval != 0 {
		if lval > length {
			flags.Usage()
			os.Exit(1)
		}
		for i := lval ; i<=length ; i++ {
			printPins(chrs, i)
		}
	} else {
		printPins(chrs, length)
	}

}