package entities

import (
	"go-nkode/internal/security"
	"log"
)

type CustomerAttributes struct {
	AttrVals []uint64
	SetVals  []uint64
}

func NewCustomerAttributes() (*CustomerAttributes, error) {
	attrVals, err := security.GenerateRandomNonRepeatingUint64(KeypadMax.TotalAttrs())
	if err != nil {
		log.Print("unable to generate attribute vals: ", err)
		return nil, err
	}
	setVals, err := security.GenerateRandomNonRepeatingUint64(KeypadMax.AttrsPerKey)
	if err != nil {
		log.Print("unable to generate set vals: ", err)
		return nil, err
	}

	customerAttrs := CustomerAttributes{
		AttrVals: attrVals,
		SetVals:  setVals,
	}
	return &customerAttrs, nil
}

func NewCustomerAttributesFromBytes(attrBytes []byte, setBytes []byte) CustomerAttributes {
	return CustomerAttributes{
		AttrVals: security.ByteArrToUint64Arr(attrBytes),
		SetVals:  security.ByteArrToUint64Arr(setBytes),
	}
}

func (c *CustomerAttributes) Renew() error {
	attrVals, err := security.GenerateRandomNonRepeatingUint64(KeypadMax.TotalAttrs())
	if err != nil {
		return err
	}
	setVals, err := security.GenerateRandomNonRepeatingUint64(KeypadMax.AttrsPerKey)
	if err != nil {
		return err
	}
	c.AttrVals = attrVals
	c.SetVals = setVals
	return nil
}

func (c *CustomerAttributes) IndexOfAttr(attrVal uint64) (int, error) {
	// TODO: should this be mapped instead?
	return security.IndexOf[uint64](c.AttrVals, attrVal)
}

func (c *CustomerAttributes) IndexOfSet(setVal uint64) (int, error) {
	// TODO: should this be mapped instead?
	return security.IndexOf[uint64](c.SetVals, setVal)
}

func (c *CustomerAttributes) GetAttrSetVal(attrVal uint64, userKeypad KeypadDimension) (uint64, error) {
	indexOfAttr, err := c.IndexOfAttr(attrVal)
	if err != nil {
		return 0, err
	}
	setIdx := indexOfAttr % userKeypad.AttrsPerKey
	return c.SetVals[setIdx], nil
}

func (c *CustomerAttributes) AttrValsForKp(userKp KeypadDimension) ([]uint64, error) {
	err := userKp.IsValidKeypadDimension()
	if err != nil {
		return nil, err
	}
	return c.AttrVals[:userKp.TotalAttrs()], nil
}

func (c *CustomerAttributes) SetValsForKp(userKp KeypadDimension) ([]uint64, error) {
	err := userKp.IsValidKeypadDimension()
	if err != nil {
		return nil, err
	}
	return c.SetVals[:userKp.AttrsPerKey], nil
}

func (c *CustomerAttributes) AttrBytes() []byte {
	return security.Uint64ArrToByteArr(c.AttrVals)
}

func (c *CustomerAttributes) SetBytes() []byte {
	return security.Uint64ArrToByteArr(c.SetVals)
}
