package e2e

import (
	"fmt"
	"github.com/fabric-sdk-sample/fabric-sdk-go/pkg/client/channel"
	"github.com/fabric-sdk-sample/fabric-sdk-go/pkg/common/errors/retry"
	"github.com/fabric-sdk-sample/fabric-sdk-go/pkg/common/providers/core"
	"github.com/fabric-sdk-sample/fabric-sdk-go/pkg/core/config"
	"github.com/fabric-sdk-sample/fabric-sdk-go/pkg/fabsdk"
)

var (
	MychannelID          = "mychannel"
	MyorgName            = "org2"
	MyccID               = "mycc"
	MydefaultQueryArgs   = [][]byte{[]byte("b")}
	MydefaultexecuteArgs = [][]byte{[]byte("b"), []byte("a"), []byte("10")}
)

func getConfig() core.ConfigProvider {
	configPath := "../../fixtures/config/config_e2e.yaml"
	return config.FromFile(configPath)
}

/*
Parameters:
  ccId: is chaincode name(such mycc)
  functionName: is query chaincode functionName (such query)
  ccArgs: is query chaincode args
*/
func CcQuery(ccId ,functionName string,ccArgs [][]byte) []byte {
	configOpt := getConfig()
	sdk, err := fabsdk.New(configOpt)
	if err != nil {
		fmt.Printf("Failed to create new SDK: %s \n", err)
	}
	defer sdk.Close()
	//prepare channel client context using client context
	clientChannelContext := sdk.ChannelContext(MychannelID, fabsdk.WithUser("Admin"), fabsdk.WithOrg(MyorgName))
	// Channel client is used to query and execute transactions (Org1 is default org)
	client, err := channel.New(clientChannelContext)
	if err != nil {
		fmt.Printf("Failed to create new channel client: %s \n", err)
	}
	return querycc(client,ccId,functionName,ccArgs)
}
/*
Parameters:
  ccId: is chaincode name(such mycc)
  functionName: is invoke chaincode functionName (such query)
  ccArgs: is invoke chaincode args
*/
func CcInvoke(ccId ,functionName string,ccArgs [][]byte) []byte {

	configOpt := getConfig()
	sdk, err := fabsdk.New(configOpt)
	if err != nil {
		fmt.Printf("Failed to create new SDK: %s \n", err)
	}
	defer sdk.Close()
	//prepare channel client context using client context
	clientChannelContext := sdk.ChannelContext(MychannelID, fabsdk.WithUser("Admin"), fabsdk.WithOrg(MyorgName))
	// Channel client is used to query and execute transactions (Org1 is default org)
	client, err := channel.New(clientChannelContext)
	if err != nil {
		fmt.Printf("Failed to create new channel client: %s \n", err)
	}
	return executeCc(client,ccId,functionName,ccArgs)
}

func querycc(client *channel.Client, ccId ,functionName string,ccArgs [][]byte,targetEndpoints ...string) []byte {
	response, err := client.Query(channel.Request{ChaincodeID: ccId, Fcn: functionName, Args: ccArgs},
		channel.WithRetry(retry.DefaultChannelOpts),
		channel.WithTargetEndpoints(targetEndpoints...),
	)
	if err != nil {
		fmt.Printf("Failed to query funds: %s \n", err)
	}
	return response.Payload
}

func executeCc(client *channel.Client,ccId ,functionName string,ccArgs [][]byte) []byte {
	response, err := client.Execute(channel.Request{ChaincodeID: ccId, Fcn: functionName, Args: ccArgs},
		channel.WithRetry(retry.DefaultChannelOpts))
	if err != nil {
		fmt.Printf("Failed to move funds: %s", err)
	}
	return response.Payload
}


