package sm2a

import (
	"fmt"
	"io"
	"math/big"

	"xdx.jelly/xgcl/gmath"
	"xdx.jelly/xgcl/sm/sm2"
)

type ClientEncKeyGenContext struct {
	ClientKey *sm2.PrivateKey
	Pubkey    *sm2.PublicKey
}

func NewClientEncKeyGenContext() *ClientEncKeyGenContext {
	return &ClientEncKeyGenContext{
		ClientKey: sm2.NewPrivateKey(),
		Pubkey:    sm2.NewPublicKey(),
	}
}

// ClientKeyGen_one 客户端加密密钥生成第一步
func (c *ClientEncKeyGenContext) ClientKeyGen_one(rand io.Reader) ([]byte, error) {
	buf := make([]byte, sm2.ByteSize())
	if n, err := rand.Read(buf); n != len(buf) || err != nil {
		return nil, fmt.Errorf("Generate random number error")
	}
	c.ClientKey.SetBytes(buf)

	c.ClientKey.D.Mod(c.ClientKey.D, sm2.OrderN())
	c.Pubkey = sm2.GenPublicKey(c.ClientKey)
	out := make([]byte, 0, 2*sm2.ByteSize())
	out = append(out, gmath.BigIntToNByte(c.Pubkey.X, sm2.ByteSize())...)
	out = append(out, gmath.BigIntToNByte(c.Pubkey.Y, sm2.ByteSize())...)
	return out, nil
}

// ClientKeyGen_one 客户端加密密钥生成第二步
func (c *ClientEncKeyGenContext) ClientKeyGen_two(in []byte) error {
	x := new(big.Int)
	y := new(big.Int)
	x.SetBytes(in[:sm2.ByteSize()])
	y.SetBytes(in[sm2.ByteSize() : 2*sm2.ByteSize()])
	c.Pubkey.X, c.Pubkey.Y = sm2.Curve().Add(c.Pubkey.X, c.Pubkey.Y, x, y)
	return nil
}
