package dhellman

import (
	"errors"

	"git.ali33.ru/fcg-xvii/curve/v2"
	"git.ali33.ru/fcg-xvii/curve/v2/tools"
)

func randomCurveKeyPair(curve *tools.Curve) (*curveKeyPair, error) {
	pair := curveKeyPair{
		curve: curve,
	}
	var err error
	if pair.priv, err = randomCurveKeyPrivate(curve); err != nil {
		return nil, err
	}
	var pub *tools.Point
	if pub, err = curve.G().Mul(pair.priv.x); err != nil {
		return nil, err
	}
	pair.pub = &curveKeyPublic{
		p: pub,
	}
	return &pair, nil
}

type curveKeyPair struct {
	priv  *curveKeyPrivate
	pub   *curveKeyPublic
	curve *tools.Curve
}

func (s *curveKeyPair) KeyPrivate() curve.KeyPrivate {
	return s.priv
}

func (s *curveKeyPair) KeyPublic() curve.KeyPublic {
	return s.pub
}

func (s *curveKeyPair) MessageEncode(data []byte, args ...any) (curve.Message, error) {
	if len(args) == 0 {
		return nil, errors.New("Не найден публичный ключ принимающей стороны")
	}
	pub, check := args[0].(*curveKeyPublic)
	if !check {
		return nil, errors.New("Неверный тип аргумента - публичный ключ принимающей стороны")
	}
	encoded, err := s.messageEncode(data, pub)
	if err != nil {
		return nil, err
	}
	mes := &message{
		encoded: encoded,
	}
	return mes, err
}

func (s *curveKeyPair) MessageDecode(mes curve.Message, args ...any) ([]byte, error) {
	if len(args) == 0 {
		return nil, errors.New("Не найден публичный ключ отправляющей стороны")
	}
	pub, check := args[0].(*curveKeyPublic)
	if !check {
		return nil, errors.New("Неверный тип аргумента - публичный ключ отправляющей стороны")
	}
	return s.messageDecode(mes.Encoded(), pub)
}

func (s *curveKeyPair) messageEncode(data []byte, pub *curveKeyPublic) ([]byte, error) {
	sec, err := s.priv.secret(pub, s.curve)
	if err != nil {
		return nil, err
	}
	return aesEncode(data, sec)
}

func (s *curveKeyPair) messageDecode(encoded []byte, pub *curveKeyPublic) ([]byte, error) {
	sec, err := s.priv.secret(pub, s.curve)
	if err != nil {
		return nil, err
	}
	return aesEncode(encoded, sec)
}