package gmath

import (
	stdbytes "bytes"
	"crypto/rand"
	"fmt"
	"math/big"
	"os/exec"
	"testing"

	"xdx.jelly/xgcl/grand"
)

func TestBig(t *testing.T) {
	b := grand.Int(0)
	fmt.Println(b.Bytes(), b.BitLen())
	a := BigInt2256.Neg(BigInt2256)
	BigInt2256.Neg(BigInt2256)
	b, _ = rand.Int(grand.Reader, a)
	fmt.Println(BigInt2256.Text(16))
	fmt.Println(b.Text(16))
	b, _ = rand.Int(grand.Reader, BigInt2)
	fmt.Println(b)
}

func TestFillBytes(t *testing.T) {
	a, _ := new(big.Int).SetString("123455", 16)
	buf := make([]byte, 1)
	// buf[2] = 1
	fmt.Printf("%02x\n", buf)
	err := FillBytes(a, buf)
	fmt.Printf("%02x %v\n", buf, err)
	fmt.Println("over")
}

func opensslIsPrime(n *big.Int) bool {
	cmd := exec.Command("openssl", "prime", "-hex", n.Text(16))
	buf, err := cmd.Output()
	if err != nil || stdbytes.Contains(buf, []byte("not prime")) {
		return false
	}
	return true
}

func TestIsPrimeMR(t *testing.T) {
	bits := 1024
	n := grand.Int(bits)
	count := 1
	for !IsPrimeMR(n) {
		count++
		n = grand.Int(bits)
	}
	fmt.Println("random times: ", count)
	fmt.Println(n.Text(16))
	if !opensslIsPrime(n) {
		t.Fail()
	}
}

func TestZp(t *testing.T) {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("panic:", err)
			fmt.Println("recover")
		}
	}()

	p, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
	a := NewZp(p)
	b := NewZp(p)
	c := NewZp(p)
	a.SetString("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16)
	b.SetString("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16)

	c.Add(a, b)
	fmt.Println("a+b=   ", c)

	c.Sub(b, a)
	fmt.Println("b-a=   ", c)

	c.Mul(b, a)
	fmt.Println("a*b=   ", c)

	c.Inv(b)
	fmt.Println("b^(-1)=", c)

	b.SetInt(0)
	c.Inv(b)
	fmt.Println("0^(-1)=", c)

}

func TestRandom(t *testing.T) {
	p, _ := new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
	a := NewZp(p)
	if err := a.Random(); err != nil {
		t.Failed()
	}
}
