package main

import (
	"encoding/json"
	"fmt"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	pb "github.com/hyperledger/fabric/protos/peer"
)


type TestCC struct {

}
// Init does nothing for this cc
func (t *TestCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
	return shim.Success([]byte("GXHCC init successful! "))
}

// Invoke for this chaincode exposes
func (t *TestCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
	// get arguments and transient
	functionName, args := stub.GetFunctionAndParameters()

	switch functionName {
	case "put":
		res,err := put(args,stub)
		if err!=nil{
			return shim.Error(fmt.Sprintf("put function err: %s", err))
		}
		return shim.Success([]byte(res))
	case "putNo":
		res,err := putNo(args,stub)
		if err!=nil{
			return shim.Error(fmt.Sprintf("put function err: %s", err))
		}
		return shim.Success([]byte(res))
	default:
		return shim.Error(fmt.Sprintf("Unsupported function %s", functionName))
	}
	return shim.Success([]byte("GXHCC invoke successful "))
}

/*
	put
	args 字段说明：
	1：args[0]代表我们具体操作的表，
    2：args[1:]后面的数据表示要记录到数据库的数据,每一个string 必须是json字符串，并且需要每一个json 字符串都必须包含id 字段

*/
func put(args []string, stub shim.ChaincodeStubInterface) (string, error) {
	//if len(args) < 2 {
	//	return "", fmt.Errorf("Expected  more than 2 parameters to function put!")
	//}

	var Result []map[string]interface{}

	if err := json.Unmarshal([]byte(args[0]), &Result); err != nil {
		return "", fmt.Errorf("parameters Unmarshal fail,args string not json array, err:%s", err)
	}
	for _, mapres := range Result{
		Id ,ok:= mapres["id"]
		if !ok{
			return "", fmt.Errorf("The id field must exist ")
		}
		tablename,ok := mapres["tablename"].(string)
		if !ok{
			return "", fmt.Errorf("tablename fields type not string! ")
		}
		putDate,_:=json.Marshal(mapres)
		if err := stub.PutState(tablename+Id.(string), putDate); err != nil {
			return "", fmt.Errorf("PutState fail, err :%s", err)
		}
		err := tableDifferentiate(tablename,mapres,stub)
		if err != nil{
			return "", err
		}
	}
	return fmt.Sprintf("%s put data success!", args[0]), nil
}

/*
	put
	args 字段说明：
	1：args[0]代表我们具体操作的表，
    2：args[1:]后面的数据表示要记录到数据库的数据,每一个string 必须是json字符串，并且需要每一个json 字符串都必须包含id 字段

*/
func putNo(args []string, stub shim.ChaincodeStubInterface) (string, error) {
	//if len(args) < 2 {
	//	return "", fmt.Errorf("Expected  more than 2 parameters to function put!")
	//}

	var Result []map[string]interface{}

	if err := json.Unmarshal([]byte(args[0]), &Result); err != nil {
		return "", fmt.Errorf("parameters Unmarshal fail,args string not json array, err:%s", err)
	}
	for _, mapres := range Result{
		Id ,ok:= mapres["id"]
		if !ok{
			return "", fmt.Errorf("The id field must exist ")
		}
		tablename,ok := mapres["tablename"].(string)
		if !ok{
			return "", fmt.Errorf("tablename fields type not string! ")
		}
		putDate,_:=json.Marshal(mapres)
		if err := stub.PutState(tablename+Id.(string), putDate); err != nil {
			return "", fmt.Errorf("PutState fail, err :%s", err)
		}
	}
	return fmt.Sprintf("%s put data success!", args[0]), nil
}
/*
	根据参数区分不同的表，并执行不同的操作
*/
func tableDifferentiate(tableName string,value map[string]interface{}, stub shim.ChaincodeStubInterface)(error){
	switch tableName {

	case "alibusi":
		return addCompositeKey(tableName,value, stub)
	case "alibusirecord":
		//return addAlibusirecord(tableName,value, stub)
	case "merchants":
		//return merchantsLeadger(tableName,value, stub)
	case "couincomingparts":
		//return addMerchantsale(args[1:],stub)
	case "merchantsale":
		//return addMerchantsale(tableName,value, stub)
	case "coutickets":
		//return couticketsLeadger(tableName,value, stub)
	case "coutcantm":
		//return coutcantmLeadger(tableName,value, stub)
	case "couticketcodes":
		//return coupartnersLeadger(args[1:],stub)
	case "coupartners":
		//return coupartnersLeadger(tableName,value, stub)
	case "couticketorders":
	//	return addCouticketorders(tableName,value,stub)
	default:
		return fmt.Errorf(fmt.Sprintf("Unsupported table name of %s", tableName))
	}
	return nil
}
func addCompositeKey(tableName string,value map[string]interface{}, stub shim.ChaincodeStubInterface)error{
	valBy,_ := json.Marshal(value)
	Id := value["id"].(string)
	aname,ok := value["aname"].(string)
	if !ok{
		return fmt.Errorf("aname fields type not string! ")
	}
	anamecomKey,err :=stub.CreateCompositeKey(tableName,[]string{aname,Id})
	if err!=nil{
		return err
	}
	if err := stub.PutState(anamecomKey, valBy); err != nil {
		return  fmt.Errorf("Put %s date fail, err :%s ",anamecomKey, err)
	}
	return  nil
}

func main() {
	err := shim.Start(&TestCC{})
	if err != nil {
		fmt.Printf("Error starting EncCC chaincode: %s", err)
	}
}