package sm2

import (
	"crypto/elliptic"
	"math/big"

	"xdx.jelly/xgcl/gmath"
	"xdx.jelly/xgcl/internal/kdf"
	"xdx.jelly/xgcl/sm/sm2/ec256"
)

const (
	// ECCRefMaxBits c.f. GMT 0018
	ECCRefMaxBits = 512
	// ECCRefMaxLen c.f. GMT 0018
	ECCRefMaxLen = (ECCRefMaxBits + 7) >> 3

	// ECCStrict UnmarshalBinary的时候是否要求数据严格遵循GMT0018格式, 也就是要求
	// bits按大端存储，并且等于密钥长度即256
	ECCStrict = false
)

var one = new(big.Int).SetInt64(1)

var (
	sm2Curve elliptic.Curve

	// byteSize is the Bytes of prime, module...
	byteSize int

	// orderN the order of Group of points on the curve
	orderN *big.Int

	// byteOfN is the ByteSize - long of N of byte slice
	byteOfN []byte

	// nMinusOne N-1
	nMinusOne *big.Int

	// Curve256 export the curve param.
	Curve256 = ec256.Curve256
)

func init() {
	// Choose the curve
	// if the curve changed to a 384-bits curve,
	// just sm2Curve = ec.EC384()
	sm2Curve = ec256.CurveSM2()
	byteSize = (sm2Curve.Params().BitSize + 7) / 8
	orderN = new(big.Int).Set(sm2Curve.Params().N)
	byteOfN = gmath.BigIntToNByte(orderN, byteSize)
	nMinusOne = new(big.Int).Sub(orderN, gmath.BigInt1)
	// must after sm2Curve and byteSize
	initPrecompute()
	// for key exchange constants
	initKeyExchange()

}

// ByteSize 返回SM2的密钥大小
func ByteSize() int {
	return byteSize
}

// OrderN return the order of point group
func OrderN() *big.Int {
	return orderN
}

// Curve return the sm2 curve (interface)
func Curve() elliptic.Curve {
	return sm2Curve
}

// Prime return the p of field charactor
func Prime() *big.Int {
	return sm2Curve.Params().P
}

// BaseX return the x of base point
func BaseX() *big.Int {
	return sm2Curve.Params().Gx
}

// BaseY return the y of base point
func BaseY() *big.Int {
	return sm2Curve.Params().Gy
}

var Kdf = kdf.SMKDF.Kdf
