package tests

import (
  {{- if .IsScalar}}
  "github.com/ingonyama-zk/icicle/v2/wrappers/golang/core"{{end}}
	{{if ne .FieldPrefix "G2"}}{{.Field}}{{end}} "github.com/ingonyama-zk/icicle/v2/wrappers/golang/{{.BaseImportPath}}{{if eq .FieldPrefix "G2"}}/g2{{end}}"
  "github.com/ingonyama-zk/icicle/v2/wrappers/golang/test_helpers"
	"github.com/stretchr/testify/assert"
	"testing"
)

 const (
	{{toConst .FieldPrefix}}LIMBS = {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{toConst .FieldPrefix}}LIMBS
)

func Test{{.FieldPrefix}}FieldFromLimbs(t *testing.T) {
	emptyField := {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field{}
	randLimbs := test_helpers.GenerateRandomLimb(int({{toConst .FieldPrefix}}LIMBS))
	emptyField.FromLimbs(randLimbs[:])
	assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the {{.FieldPrefix}}Field's limbs")
	randLimbs[0] = 100
	assert.NotEqual(t, randLimbs, emptyField.GetLimbs())
}

func Test{{.FieldPrefix}}FieldGetLimbs(t *testing.T) {
	emptyField := {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field{}
	randLimbs := test_helpers.GenerateRandomLimb(int({{toConst .FieldPrefix}}LIMBS))
	emptyField.FromLimbs(randLimbs[:])

	assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the {{.FieldPrefix}}Field's limbs")
}

func Test{{.FieldPrefix}}FieldOne(t *testing.T) {
	var emptyField {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field
	emptyField.One()
	limbOne := test_helpers.GenerateLimbOne(int({{toConst .FieldPrefix}}LIMBS))
	assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work")

	randLimbs := test_helpers.GenerateRandomLimb(int({{toConst .FieldPrefix}}LIMBS))
	emptyField.FromLimbs(randLimbs[:])

	emptyField.One()
	assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "{{.FieldPrefix}}Field with limbs to field one did not work")
}

func Test{{.FieldPrefix}}FieldZero(t *testing.T) {
	var emptyField {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field
	emptyField.Zero()
	limbsZero := make([]uint32, {{toConst .FieldPrefix}}LIMBS)
	assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed")

	randLimbs := test_helpers.GenerateRandomLimb(int({{toConst .FieldPrefix}}LIMBS))
	emptyField.FromLimbs(randLimbs[:])

	emptyField.Zero()
	assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "{{.FieldPrefix}}Field with limbs to field zero failed")
}

func Test{{.FieldPrefix}}FieldSize(t *testing.T) {
	var emptyField {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field
	randLimbs := test_helpers.GenerateRandomLimb(int({{toConst .FieldPrefix}}LIMBS))
	emptyField.FromLimbs(randLimbs[:])

	assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes")
}

func Test{{.FieldPrefix}}FieldAsPointer(t *testing.T) {
	var emptyField {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field
	randLimbs := test_helpers.GenerateRandomLimb(int({{toConst .FieldPrefix}}LIMBS))
	emptyField.FromLimbs(randLimbs[:])

	assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value")
}

func Test{{.FieldPrefix}}FieldFromBytes(t *testing.T) {
	var emptyField {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field
	bytes, expected := test_helpers.GenerateBytesArray(int({{toConst .FieldPrefix}}LIMBS))

	emptyField.FromBytesLittleEndian(bytes)

	assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values")
}

func Test{{.FieldPrefix}}FieldToBytes(t *testing.T) {
	var emptyField {{if eq .FieldPrefix "G2"}}g2{{else}}{{.Field}}{{end}}.{{.FieldPrefix}}Field
	expected, limbs := test_helpers.GenerateBytesArray(int({{toConst .FieldPrefix}}LIMBS))
	emptyField.FromLimbs(limbs)

	assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values")
}
{{if .IsScalar}}
func Test{{capitalize .Field}}GenerateScalars(t *testing.T) {
	const numScalars = 8
	scalars := {{.Field}}.GenerateScalars(numScalars)

	assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars)

	assert.Equal(t, numScalars, scalars.Len())
	zeroScalar := {{.Field}}.{{.FieldPrefix}}Field{}
	assert.NotContains(t, scalars, zeroScalar)
}

func Test{{capitalize .Field}}MongtomeryConversion(t *testing.T) {
	size := 1 << 15
	scalars := {{.Field}}.GenerateScalars(size)

	var deviceScalars core.DeviceSlice
	scalars.CopyToDevice(&deviceScalars, true)

	{{.Field}}.ToMontgomery(&deviceScalars)

	scalarsMontHost := {{.Field}}.GenerateScalars(size)

	scalarsMontHost.CopyFromDevice(&deviceScalars)
	assert.NotEqual(t, scalars, scalarsMontHost)

	{{.Field}}.FromMontgomery(&deviceScalars)

	scalarsMontHost.CopyFromDevice(&deviceScalars)
	assert.Equal(t, scalars, scalarsMontHost)
}{{end}}
