const elliptic = require('elliptic')
import { KEYUTIL } from 'jsrsasign'

const EC = elliptic.ec
const ecdsaCurve = elliptic.curves['p256']

type Curves = 'secp256r1' | 'secp384r1'

const ordersForCurve = {
	secp256r1: {
		halfOrder: elliptic.curves.p256.n.shrn(1),
		order: elliptic.curves.p256.n,
	},
	secp384r1: {
		halfOrder: elliptic.curves.p384.n.shrn(1),
		order: elliptic.curves.p384.n,
	},
}

// this function comes from CryptoSuite_ECDSA_AES.js and will be part of the
// stand alone fabric-sig package in future.
function preventMalleability(sig: any, curveParams: { name: Curves }) {
	const halfOrder = ordersForCurve['secp256r1'].halfOrder

	// in order to guarantee 's' falls in the lower range of the order, as explained in the above link,
	// first see if 's' is larger than half of the order, if so, it needs to be specially treated
	if (sig.s.cmp(halfOrder) === 1) {
		// module 'bn.js', file lib/bn.js, method cmp()
		// convert from BigInteger used by jsrsasign Key objects and bn.js used by elliptic Signature objects
		const bigNum = ordersForCurve[curveParams.name].order
		sig.s = bigNum.sub(sig.s)
	}

	return sig
}

export function signDigest(privateKey: string, digest: string) {
	const ecdsa = new EC(ecdsaCurve)
	const key:any = KEYUTIL.getKey(privateKey)
	const signKey = ecdsa.keyFromPrivate(key.prvKeyHex, 'hex')
	const signature = preventMalleability(
		ecdsa.sign(Buffer.from(digest, 'hex'), signKey),
		key.ecparams
	)

	return Buffer.from(signature.toDER()).toString('base64')
}
