/* Create a group configuration file. This is really a convenience feature
   more than anything, making it easier to direct the client than supplying
   all the arguments on the command line. */
func runMultiSignatureGen(group []SchnorrMSHostSpec, outputFile string) error {

	var config SchnorrMGroupConfig
	var pkeys []crypto.SchnorrPublicKey

	suite := ed25519.NewAES128SHA256Ed25519(true)
	for _, mshp := range group {

		pkey, err := crypto.SchnorrLoadPubkey(mshp.KeyFilePath, suite)
		if err != nil {
			fmt.Println(err.Error())
			os.Exit(1)
		}

		pkeys = append(pkeys, pkey)

		member := SchnorrMMember{mshp.HostName, mshp.Port, pkey}
		config.Members = append(config.Members, member)
	}

	jointKey := crypto.SchnorrMComputeSharedPublicKey(suite, pkeys)
	config.JointKey = jointKey.GetSchnorrPK()

	data, _ := json.Marshal(config)

	f, err := os.OpenFile(outputFile, os.O_CREATE|os.O_RDWR, 0644)
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = f.Write(data)
	return err
}
func main() {
	var port int
	var hostname string
	var kfilepath string

	flag.StringVar(&kfilepath, "keyfile", "", "Use the keyfile specified")
	flag.StringVar(&hostname, "host", "localhost", "Connect to the specified host")
	flag.IntVar(&port, "port", 1111, "Use the specified port")
	flag.Parse()

	suite := ed25519.NewAES128SHA256Ed25519(true)
	pk, err := crypto.SchnorrLoadPubkey(kfilepath, suite)
	if err != nil {
		fmt.Println("Error " + err.Error())
		return
	}

	fmt.Println(pk.Y)

	var hostspec string
	hostspec = fmt.Sprintf("%s:%d", hostname, port)
	fmt.Println("Connecting to %s\n", hostspec)
	conn, err := net.Dial("tcp", hostspec)
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	randomdata := make([]byte, 1024)
	_, err = rand.Read(randomdata)
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	buffer := make([]byte, 64)

	conn.Write(randomdata)
	_, err = conn.Read(buffer)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	v, err := crypto.SchnorrVerify(suite, pk, randomdata, buffer)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	if v == true {
		fmt.Println("Signature verified OK")
	} else {
		fmt.Println("Signature verify FAILED")
	}

	return
}
/* Runs through the "user" side of the protocol i.e. the party
   requesting a partially blind signature */
func main() {

	kingpin.MustParse(app.Parse(os.Args[1:]))

	var kfilepath string = *appPrivatekeyfile
	var kinfopath string = *appInfo
	var hostspec string = *appHostspec

	suite := ed25519.NewAES128SHA256Ed25519(true)

	fmt.Println("CLIENT", "Connecting to", hostspec)

	pubKey, err := crypto.SchnorrLoadPubkey(kfilepath, suite)
	if err != nil {
		fmt.Println("CLIENT", "Error loading public key"+err.Error())
		return
	}

	info, err := LoadInfo(kinfopath)
	if err != nil {
		fmt.Println("CLIENT", "Error loading info"+err.Error())
		return
	}

	message := make([]byte, 1024)
	_, err = rand.Read(message)
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	conn, err := net.Dial("tcp", hostspec)
	if err != nil {
		fmt.Println("CLIENT", "Error connecting to server", err.Error())
		return
	}
	defer conn.Close()

	// first up, let's receive the signer's parameter set

	buffer := make([]byte, 1026)
	_, err = conn.Read(buffer)
	if err != nil {
		fmt.Println("CLIENT", "Error reading from server", err.Error())
		return
	}

	var userPublicParams crypto.WISchnorrPublicParams
	decodeBuffer := bytes.NewBuffer(buffer)
	err = abstract.Read(decodeBuffer, &userPublicParams, suite)

	// now we've got that, complete the challenge phase (i.e. let's generate E)
	challenge, userPrivateParams, err := crypto.ClientGenerateChallenge(suite, userPublicParams, pubKey, info, message)
	if err != nil {
		fmt.Println("CLIENT", "Error generating challenge", err.Error())
		return
	}

	// encode and send to server.
	challengebuffer := bytes.Buffer{}
	abstract.Write(&challengebuffer, &challenge, suite)
	conn.Write(challengebuffer.Bytes())

	// and now we wait for the server to respond to this:
	secondread := make([]byte, 1024)
	_, err = conn.Read(secondread)
	if err != nil {
		fmt.Println("CLIENT", "Error reading from server", err.Error())
		return
	}

	var responseMessage crypto.WISchnorrResponseMessage
	decodeBuffer = bytes.NewBuffer(secondread)
	err = abstract.Read(decodeBuffer, &responseMessage, suite)
	if err != nil {
		fmt.Println("CLIENT", "Error reading response", err.Error())
		return
	}

	// we've got the response message, time to sign and check.

	// finally, we can sign the message and check it verifies.
	sig, worked := crypto.ClientSignBlindly(suite, userPrivateParams, responseMessage, pubKey, message)

	//fmt.Println(blindSignature)

	if worked != true {
		fmt.Println("CLIENT", "Error preforming blind signature")
		return
	}

	// now verify this worked fine.
	result, err := crypto.VerifyBlindSignature(suite, pubKey, sig, info, message)

	if err != nil {
		fmt.Println("CLIENT", "Error handling signature verification", err.Error())
		return
	}
	if result != true {
		fmt.Println("CLIENT", "Signature did not correctly verify.")
		return
	}

	fmt.Println("CLIENT", "Signature OK -", sig)

	return
}