package main

import (
	"bytes"
	"crypto/x509"
	"encoding/json"
	"math/big"
	"encoding/pem"
	"fmt"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	pb "github.com/hyperledger/fabric/protos/peer"
	"strconv"
	"strings"
)

type GXHCC struct {
}

type AuthGroup struct {
	Users map[string]int64 `json:"users"` //用户组权限，默认使用用户组。我们使用形如：“User1”:timestamp. key 表示用户或者角色，value 表示有效时间。我们使用格林威治时间时间戳
	Roles map[string]int64 `json:"roles"` //角色组权限，
}

type Auth struct {
	Read  AuthGroup `json:"read"`  // 字段的读权限,“”,不存在权限，
	Write AuthGroup `json:"write"` //字段的写权限
}

type LeadgerAuth struct { // 账本数据除了读权限外
	Read     AuthGroup `json:"read"`     // 字段的读权限,“”,不存在权限，
	Issue    AuthGroup `json:"issue"`    //账本数据的发行权限，
	Extract  AuthGroup `json:"extrate"`  //账本数据的提取权限，
	Transfer AuthGroup `json:"transfer"` // 账本数据的转账权限，
}

type SchemaParameters struct {
	Value  interface{} `json:"val"` //默认值  这里特别说明一下如果这里是backUp 字段，我们不进行更深一步的校验，包括格式
	PAuth  Auth        `json:"auth"`
	FCheck *Checks     `json:"fcheck"`
}

type SchemaLeadgerParameters struct {
	Value  interface{} `json:"val"` //默认值  这里特别说明一下如果这里是backUp 字段，我们不进行更深一步的校验，包括格式
	PAuth  LeadgerAuth `json:"auth"`
	FCheck *Checks     `json:"fcheck"`
}

type Checks struct {
	FType    string `json:"ftype"`    //字段类型
	Must     bool   `json:"must"`     //是否必填
	Fieldlen int    `json:"fieldlen"` //字段长度（如果字段类型是string,表示字段长度，如果是数值类型用0,1表示数据正负）
}

type Schema struct {
	LeadgerFields map[string]SchemaLeadgerParameters `json:"leadger_fields"` //账本字段
	StorageFields map[string]SchemaParameters        `json:"storage_fields"` //存证字段
	SchemaAuth    Auth                               `json:"schema_auth"`    //schema 的写权限，主要是用在 schema update 部分
	SAuth         Auth                               `json:"auth"`           //数据总的读权限
}

type Action struct {
	AccountType  string      `json:"account_type"`  //账户类型
	AccountId    string      `json:"account_id"`    //账户Id
	ActionAmount string      `json:"action_amount"` //这次的动作金额
	FundType     string      `json:"fund_type"`     //资金类型
	BackUp       interface{} `json:"back_up"`       //备注信息
}

type TransferAccount struct {
	AccountType string `json:"account_type"` //账户类型
	AccountId   string `json:"account_id"`   //账户Id
	FundType    string `json:"fund_type"`    //资金类型
}
type Node struct {
	Key   string
	Value *Schema
	pre   *Node
	next  *Node
}

type LRUCache struct {
	limit   int
	HashMap map[string]*Node
	head    *Node
	end     *Node
}

type Merchantsale struct {
	Mid         string  `json:"mid"`         //商户Id
	Bid         string  `json:"bid"`         // 分支机构id,也是一笔交易的接受者
	Tamount     string  `json:"tamount"`     //交易金额
	Treposit    string  `json:"treposit"`    //扣除预付金
	Bereposit   string  `json:"bereposit"`   //扣除前预付金
	Afreposit   string  `json:"afreposit"`   //扣除后预付金
	Feerate     float64 `json:"feerate"`     // 手续费扣率
	Free        string  `json:"free"`        // 手续费
	Oamount     string  `json:"oamount"`     // 原始交易金额
	Adiscounts  float64 `json:"adiscounts"`  //代理结算折扣
	Sdiscounts  float64 `json:"sdiscounts"`  //消费折扣
	Nodisamount string  `json:"nodisamount"` //不打折金额
	Disamount   string  `json:"disamount"`   //打折金额
	Perquisites string  `json:"perquisites"` //额外收益
}

type OrderTx struct {
	Oamount      string         `json:"oamount"` // 原始交易金额
	Pamount      string         `json:"pamount"` // 支付金额
	Odesc        *OrderDescribe `json:"odesc"`   //订单描述
	Mid          string         `json:"mid"`     //商户Id
	Norate       float64        `json:"norate"`  //无预付金收益率
	Outfree      string         `json:"outfree"` //付款方手续费
	Infree       string         `json:"infree"`  //收款方手续费
	Partnersfree string         `json:"partnersfree"` //订单合作方手续费
	Free         string         `json:"free"` // 手续费
	Pid			 string			`json:"pid"`  //合作方Id
}

type OrderDescribe struct {
	Codes      []string `json:"codes"`       //码
	TicketType int      `json:"ticket_type"` //券类型，折扣券只能使用一次
	Tid        string   `json:"tid"`         //券Id
}

type CommonTx struct {
	SenderAccountType   string `json:"sender_account"`
	SenderId            string `json:"sender_id"`
	SenderFunt          string `json:"sender_funt"`
	ReceiverAccountType string `json:"receiver_account"`
	ReceiverId          string `json:"receiver_id"`
	ReceiverFunt        string `json:"receiver_funt"`
	Amount              string `json:"amount"`
}

type transferTypes func(args []string, stub shim.ChaincodeStubInterface) error                                                                       // 声明了一个函数类型
type putDataFilter func(putDatas []map[string]interface{}, name, tableName string, schema *Schema, stub shim.ChaincodeStubInterface) (string, error) // 声明了一个函数类型,这个函数类型主要是用于putdata 数据过滤使用

var (
	defValue         = "***" //查询用户权限不足的情况下默认返回值
	StoragePrefix    = "SGXH"
	LeadgerPrefix    = "LGXH"
	IsUsers          = true        //是否启用用户权限，false 表示启用Roles
	GxhSchema        = "gxhSchema" //schema 存储前缀，为了实现复合主键使用。
	InitSchemaLength = 12          //缓存的 schema 的长度
	schemaCache      = Constructor(InitSchemaLength)
	updateTime       = int64(60 * 60 * 12) //schema 更新时间间隔，默认是12小时
	lastTime         = int64(0)
	transferType     = initTransfer()
	PutDataFilter    = initPutData()
)

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

/*
	初始化我们要使用的交易执行方法
*/
func initTransfer() map[string]transferTypes {
	transferType := make(map[string]transferTypes)
	transferType["merchants"] = merchantsale
	transferType["tickerorders"] = tickerorders
	transferType["commontx"] = normalTransfer
	return transferType
}

func initPutData() map[string]putDataFilter {
	filter := make(map[string]putDataFilter)
	filter["couticketcodes"] = codeFilter
	filter["commonput"] = commanFilter
	filter["coutcantm"] = ticketMerFilter
	return filter
}

/*
	处理缓存内容的方法，
*/
func initSchema(stub shim.ChaincodeStubInterface) error {
	timeStamp, err := stub.GetTxTimestamp()
	if err != nil {
		return err
	} else if timeStamp.GetSeconds() < lastTime+updateTime {
		return nil
	}
	var values map[string]*Schema
	values = make(map[string]*Schema)

	schemaIterator, err := stub.GetStateByPartialCompositeKey(GxhSchema, nil)
	if err != nil {
		return err
	}
	defer schemaIterator.Close()
	index := 1
	for schemaIterator.HasNext() {
		querykv, err := schemaIterator.Next()
		if err != nil {
			return err
		}
		fmt.Println("add cache key:", querykv.Key)
		_, compisiteKeys, err := stub.SplitCompositeKey(querykv.Key)
		if err != nil {
			return err
		}
		scema := &Schema{}
		err = json.Unmarshal(querykv.Value, scema)
		if err != nil {
			fmt.Sprintf("json unmarshal %s schema fail,err: %s \n", querykv.Key, err)
		}
		if schemaCache.Get(compisiteKeys[0]) != nil {
			schemaCache.Put(compisiteKeys[0], scema)
			fmt.Println("add cache key:", querykv.Key)
			index++
			if index > InitSchemaLength {
				fmt.Println("cache data length :", len(schemaCache.HashMap))
				return nil
			}
		} else {
			values[compisiteKeys[0]] = scema
		}
	}
	for len(schemaCache.HashMap) < InitSchemaLength {
		for k, v := range values {
			schemaCache.Put(k, v)
		}
	}
	fmt.Println("cache data length :", len(schemaCache.HashMap))
	lastTime = timeStamp.GetSeconds() //设置最新修改时间
	return nil
}
// Invoke for this chaincode exposes
func (t *GXHCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
	// get arguments and transient

	functionName, args := stub.GetFunctionAndParameters()
	var err error
	err = initSchema(stub)
	if err != nil {
		return shim.Error(err.Error())
	}
	paths := splitPath(functionName)
	return Router(paths,args,stub)
}

func Router(paths,args []string ,stub shim.ChaincodeStubInterface) pb.Response {
	switch paths[0] {
	case "schema":
		return SchemaProcess(paths,args, stub)
	case "put":
		return putApi(args, stub)
	case "update":
		return updateApi(args, stub)
	case "get":
		return getApi(args, stub)
	case "createTx":
		return transactionProcess(paths,args, stub)
	case "getCertCommonName":
		return getCertNameApi(stub)
	default:
		return shim.Error(fmt.Sprintf("Unsupported function %s", paths[0]))
	}
}



func putApi(args []string, stub shim.ChaincodeStubInterface)pb.Response{
	if len(args) < 2 {
		return shim.Error("put data operation expected more than 2 parameters! ")
	}
	var PutDatas []map[string]interface{}
	err := json.Unmarshal([]byte(args[1]), &PutDatas)
	if  err != nil {
		return shim.Error(fmt.Sprintf("%s table parameters Unmarshal fail,put string not json array, err:%s", args[0], err))
	}
	res, err := put(args[0],PutDatas,stub)
	if err != nil {
		return shim.Error(fmt.Sprintf("put function err: %s", err))
	}
	return shim.Success([]byte("gxhcc invoke successful:" + res))
}

func updateApi(args []string, stub shim.ChaincodeStubInterface)pb.Response{
	if len(args) != 2 {
		return shim.Error("update data operation expected 2 parameters! ")
	}
	var datas map[string]interface{}
	if err := json.Unmarshal([]byte(args[1]), &datas); err != nil {
		return shim.Error(fmt.Sprintf("%s table parameters Unmarshal fail,put string not json array, err:%s", args[0], err))
	}
	res, err := updateStoreData(args[0],datas,stub)
	if err != nil {
		return shim.Error(fmt.Sprintf("put function err: %s", err))
	}
	return shim.Success([]byte("gxhcc invoke successful:" + res))
}

func getApi(args []string, stub shim.ChaincodeStubInterface)pb.Response{
	if len(args) != 2 {
		return shim.Error("get data operation expected  2 parameters to function get!")
	}
	var datas map[string]interface{}
	if err := json.Unmarshal([]byte(args[1]), &datas); err != nil {
		return shim.Error(fmt.Sprintf("%s table parameters Unmarshal fail,put string not json array, err:%s", args[0], err))
	}
	res, err := get(args[0],datas,stub)
	if err != nil {
		return shim.Error(fmt.Sprintf("put function err: %s", err))
	}
	return shim.Success([]byte(res))
}

func getCertNameApi(stub shim.ChaincodeStubInterface)pb.Response{
	res,err := getCertificateCommonName(stub)
	if err != nil {
		return shim.Error(fmt.Sprintf("get certificate common_name fail,err: %s", err))
	}
	return shim.Success([]byte("current user certificate common_name is:" + res))
}


func SchemaProcess(paths,args []string, stub shim.ChaincodeStubInterface) pb.Response {
	switch paths[0] {
	case "put":
		return schemaPutApi(args, stub)
	case "update":
		return schemaUpdateApi(args, stub)
	case "get":
		return schemaGetApi(args, stub)
	default:
		return shim.Error(fmt.Sprintf("Unsupported schema function of %s", paths[0]))
	}
}
/*
	put
	args 字段说明：
	1：args[0]代表我们具体操作的表，
    2：args[1:]后面的数据表示要记录到数据库的数据,每一个string 必须是json字符串，并且需要每一个json 字符串都必须包含id 字段

我们可以发现json字符串都被我们解析成了map[string]interface{}类型的map,其中key代表表模板的字段，interface可以是一个结构，我们当前将他看做我们表模板字段的初始值。
伪代码：
1：在创建schema data 时，我们必须检查金额字段的类型必须是float64,并且不能为负数。
*/
func schemaPutApi(args []string, stub shim.ChaincodeStubInterface)pb.Response{
	if len(args) != 2 {
		return shim.Error("Schema  put operation expected 2 parameters!")
	}
	schema, err := NewSchema(args[1])
	if err != nil {
		return  shim.Error("The parameters Unmarshal to a Schema structural fail,err: "+ err.Error())
	}
	result,err := schemaPut(args[0],schema,stub)
	if err != nil{
		return shim.Error(err.Error())
	}
	return shim.Success([]byte(result))
}


func schemaUpdateApi(args []string, stub shim.ChaincodeStubInterface)pb.Response{
	if len(args) != 2 {
		return shim.Error("Schema  update operation expected 2 parameters!")
	}
	schema, err := NewSchema(args[1])
	if err != nil {
		return  shim.Error("The parameters Unmarshal to a Schema structural fail,err: "+ err.Error())
	}
	result,err := schemaUpdate(args[0],schema,stub)
	if err != nil{
		return shim.Error(err.Error())
	}
	return shim.Success([]byte(result))
}

func schemaGetApi(args []string, stub shim.ChaincodeStubInterface)pb.Response{
	if len(args) != 1 {
		return shim.Error("Schema get operation expected 1 parameters!")
	}
	result,err := schemaGet(args[0],stub)
	if err != nil{
		return shim.Error(err.Error())
	}
	return shim.Success([]byte(result))
}


func schemaPut(schemaName string, schema *Schema,stub shim.ChaincodeStubInterface) (string, error) {
	_, ok := schema.StorageFields["id"]
	if !ok {
		return "", fmt.Errorf("The id field must exist ")
	}
	_, ok = schema.StorageFields["common_name"]
	if !ok {
		return "", fmt.Errorf("The common_name field must exist ")
	}

	CompositeKey, err := stub.CreateCompositeKey(GxhSchema, []string{schemaName})
	if err != nil {
		return "", fmt.Errorf("the schema %s create comosite key fail,err : %s",schemaName, err)
	}
	if schemaCache.Get(schemaName) != nil {
		return "", fmt.Errorf("the schema %s already exists and cannot be added", schemaName)
	} else if value, _ := getBytes(CompositeKey,stub); value != nil {
		return "", fmt.Errorf("the schema %s already exists and cannot be added", schemaName)
	}
	err = putState(CompositeKey, schema,stub)
	if err != nil {
		return "", fmt.Errorf("Schema PutState fail,err: %s ", err)
	}
	//schemaCache.Put(args[0], schema)
	return fmt.Sprintf("%s schema put success!", schemaName), nil
}

/*
	if update Schema 那么我们没有办法比较旧有的一个模板，
     Schema 的 update,不支持部分修改，因为存在增加和删除某些字段的情况。
     初版暂时只允许修改存储数据,金额字段暂时不允许修改
*/
func schemaUpdate(schemaName string, schema *Schema,stub shim.ChaincodeStubInterface) (string, error) {
	schemaOld := &Schema{}
	var err error
	_, ok := schema.StorageFields["id"]
	if !ok {
		return "", fmt.Errorf("The id field must exist ")
	}
	_, ok = schema.StorageFields["common_name"]
	if !ok {
		return "", fmt.Errorf("The common_name field must exist ")
	}
	CompositeKey, err := stub.CreateCompositeKey(GxhSchema, []string{schemaName})
	if err != nil {
		return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", schemaName, err)
	}
	schemaOld,err = getSchema(schemaName, stub)
	if err != nil {
		return "", err
	}
	commonName, err := getCertificateCommonName(stub)
	if err != nil {
		return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
	}
	if err := schema.WriteCheck(commonName, ""); err != nil {
		return "", fmt.Errorf("update %s schema fail,err: %s ", schemaName, err)
	}
	schema.LeadgerFields = schemaOld.LeadgerFields
	err = putState(CompositeKey,schema,stub)
	if err != nil {
		return "", fmt.Errorf("%s schema data PutState fail,please try again ",schemaName)
	}
	return fmt.Sprintf("%s schema update success!", schemaName), err

}

func getSchema(name string, stub shim.ChaincodeStubInterface) (*Schema,error) {
	schema := &Schema{}
	if schema = schemaCache.Get(name); schema == nil {
		CompositeKey, err := stub.CreateCompositeKey(GxhSchema, []string{name})
		if err != nil {
			return nil,fmt.Errorf("the schema %s create comosite key fail,err : %s", name, err)
		}
		ok, err := getObject(CompositeKey,schema,stub)
		if !ok {
			return nil,fmt.Errorf("%s schema data doesn't exist,please check your parameters ", name)
		}
		schemaCache.Put(name, schema)
	}
	return schema,nil
}

func schemaGet(args string, stub shim.ChaincodeStubInterface) (string, error) {
	schema := &Schema{}
	var result []byte
	if schema = schemaCache.Get(args); schema == nil {
		CompositeKey, err := stub.CreateCompositeKey(GxhSchema, []string{args})
		if err != nil {
			return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args, err)
		}
		bool, err := getObject(CompositeKey,schema,stub)
		if err != nil {
			return "",err
		}
		if !bool {
			return "", fmt.Errorf("%s schema data doesn't exist,please check your parameters ", args)
		}

		schemaCache.Put(args, schema)
	}
	commonName, err := getCertificateCommonName(stub)
	if err != nil {
		return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
	}
	err = schema.WriteCheck( commonName, "")
	if err != nil {
		return "", err
	}
	result, _ = json.Marshal(schema)
	return string(result), nil
}

/*
	将字段根据账本数据，与存储数据分开
	leadgers:参数表示我们需要在账本数据包含的字段，这些字段不属于账本数据。
*/
func separateFields(schema *Schema, checkmap map[string]interface{}, leadgers []string) (storagemap, leadgermap map[string]interface{}) {
	storagemap = make(map[string]interface{})
	leadgermap = make(map[string]interface{})
	for k, _ := range schema.LeadgerFields {
		leadgermap[k] = checkmap[k]
	}
	for _, v := range leadgers {
		leadgermap[v] = checkmap[v]
	}
	for k, _ := range schema.StorageFields {
		storagemap[k] = checkmap[k]
	}
	return
}

/*
	重新赋值，并检查相应的格式是否正确
*/
func Deassign(upMap, result map[string]interface{}) error {
	if len(upMap) > len(result) {
		return fmt.Errorf("Deassign fail,reassigned data length greater than the original data length! ")
	}
	for k, v := range upMap {
		if resultV, ok := result[k]; ok {
			if resultMap, resultok := resultV.(map[string]interface{}); resultok {
				if vMap, ok := v.(map[string]interface{}); !ok {
					return fmt.Errorf("Deassign fail, format doesn't match! ")
				} else {
					Deassign(vMap, resultMap)
				}
			} else {
				result[k] = v
			}
		} else {
			return fmt.Errorf("Deassign fail %s key nonentity ", k)
		}
	}
	return nil
}



func getMap(key string, stub shim.ChaincodeStubInterface) (map[string]interface{}, error) {
	var resultmap map[string]interface{}
	result, err := stub.GetState(key)
	if err != nil {
		return nil, fmt.Errorf("GetState %s data fail,err %s ", key, err)
	}
	if result == nil {
		return nil, nil
	}
	err = json.Unmarshal(result, &resultmap)
	if err != nil {
		return nil, fmt.Errorf("json unmarshal leadger map fail,err: %s", err)
	}
	return resultmap, nil
}

func getState(key string, stub shim.ChaincodeStubInterface) (map[string]interface{}, error) {
	var resultmap map[string]interface{}
	result, err := stub.GetState(key)
	if err != nil {
		return nil, fmt.Errorf("GetState %s data fail,err %s ", key, err)
	}
	if result == nil {
		return nil, nil
	}
	err = json.Unmarshal(result, &resultmap)
	if err != nil {
		return nil, fmt.Errorf("json unmarshal leadger map fail,err: %s", err)
	}
	return resultmap, nil
}

func getObject(key string, value interface{}, stub shim.ChaincodeStubInterface)( bool,error){
	result, err := stub.GetState(key)
	if err != nil {
		return  false,fmt.Errorf("GetState %s data fail,err %s ", key, err)
	}
	if result == nil {
		return  false,nil
	}
	err = json.Unmarshal(result, value)
	if err != nil {
		return  false,fmt.Errorf("json unmarshal leadger map fail,err: %s", err)
	}
	return  true,nil
}

func getBytes(key string,  stub shim.ChaincodeStubInterface) ([]byte, error) {
	result, err := stub.GetState(key)
	if err != nil {
		return nil, fmt.Errorf("GetState %s data fail,err %s ", key, err)
	}

	return result, nil
}
/*
	不要进行[]byte 的marshal,
*/
func putState(key string, value interface{}, stub shim.ChaincodeStubInterface) error {
	valueByte, err := json.Marshal(value)
	if err != nil {
		return fmt.Errorf(" %s json marshal data fail,err: %s", key, err)
	}
	err = stub.PutState(key, valueByte)
	if err != nil {
		return fmt.Errorf("putState %s data fail,err: %s", key, err)
	}
	return nil
}

/*
	不要进行[]byte 的marshal,
*/
func putStateByte(key string, value []byte, stub shim.ChaincodeStubInterface) error {
	err := stub.PutState(key, value)
	if err != nil {
		return fmt.Errorf("putState %s data fail,err: %s", key, err)
	}
	return nil
}


func getCertificateCommonName(stub shim.ChaincodeStubInterface) (string, error) {
	return "Admin@org2.example.com", nil
	creatorByte, _ := stub.GetCreator()
	certStart := bytes.IndexAny(creatorByte, "-----BEGIN")
	if certStart == -1 {
		return "", fmt.Errorf("No certificate found ")
	}
	certText := creatorByte[certStart:]
	bl, _ := pem.Decode(certText)
	if bl == nil {
		return "", fmt.Errorf("Could not decode the PEM structure ")
	}
	cert, err := x509.ParseCertificate(bl.Bytes)
	if err != nil {
		return "", fmt.Errorf("ParseCertificate failed")
	}
	return cert.Subject.CommonName, nil
}

func Decimal(value float64) float64 {
	value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
	return value
}


func Constructor(capacity int) LRUCache {
	lruCache := LRUCache{limit: capacity}
	lruCache.HashMap = make(map[string]*Node, capacity)
	return lruCache
}

func (l *LRUCache) Get(key string) *Schema {
	if v, ok := l.HashMap[key]; ok {
		l.refreshNode(v)
		return v.Value
	} else {
		return nil
	}
}

func (l *LRUCache) Put(key string, value *Schema) error {
	if v, ok := l.HashMap[key]; !ok {
		if len(l.HashMap) >= l.limit {
			oldKey := l.removeNode(l.head)
			delete(l.HashMap, oldKey)
		}
		node := Node{Key: key, Value: value}
		l.addNode(&node)
		l.HashMap[key] = &node
	} else {
		v.Value = value
		l.refreshNode(v)
	}
	return nil
}

func (l *LRUCache) refreshNode(node *Node) {
	if node == l.end {
		return
	}
	l.removeNode(node)
	l.addNode(node)
}

func (l *LRUCache) removeNode(node *Node) string {
	if node == l.end {
		l.end = l.end.pre
		l.end.next = nil
	} else if node == l.head {
		l.head = l.head.next
		l.head.pre = nil
	} else {
		node.pre.next = node.next
		node.next.pre = node.pre
	}
	return node.Key
}

func (l *LRUCache) addNode(node *Node) {
	if l.end != nil {
		l.end.next = node
		node.pre = l.end
		node.next = nil
	}
	l.end = node
	if l.head == nil {
		l.head = node
	}
}

func dividecalc(bint *big.Int, divide float64) (*big.Int, error) {
	divide *= 1000000
	value := new(big.Int).Mul(bint, big.NewInt(int64(divide)))
	value.Div(value, big.NewInt(1000000))
	return value, nil
}


// "/" -> []
// "/admin" -> ["admin"]
// "/admin/" -> ["admin"]
// "/admin/users" -> ["admin", "users"]
func splitPath(key string) []string {
	key = strings.Trim(key, "/ ")
	if key == "" {
		return []string{}
	}
	return strings.Split(key, "/")
}

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