package main

import (
	"bytes"
	"crypto/x509"
	"encoding/json"
	"encoding/pem"
	"fmt"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	pb "github.com/hyperledger/fabric/protos/peer"
	"reflect"
	"sync"
	"time"
)

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 SchemaParameters struct {
	Value interface{}  `json:"val"`//默认值  这里特别说明一下如果这里是backUp 字段，我们不进行更深一步的校验，包括格式
	PAuth  Auth         `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 {
	Fields 		map[string]SchemaParameters `json:"fields"`
	SchemaAuth 	Auth `json:"schema_auth"`//schema 的写权限，主要是用在 schema update 部分
	SAuth 		Auth `json:"auth"`
}

type Node struct {
	Key string
	Value []byte
	pre *Node
	next *Node
}

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



var (
	defValue = "***" //查询用户权限不足的情况下默认返回值
	PREFIX = "GXH"
	IsUsers = false   //是否启用用户权限，false 表示启用Roles
	GxhSchema = "gxhSchema" //schema 存储前缀，为了实现复合主键使用。
	InitSchemaLength = 12 //初始化时schema 的长度
	schemaCache = Constructor(InitSchemaLength)
	once = sync.Once{}
)

func initSchema(stub shim.ChaincodeStubInterface)error{
	var errinfo error
	once.Do(func(){
		schemaIterator,err :=  stub.GetStateByPartialCompositeKey(GxhSchema,nil)
		if err != nil {
			errinfo = err
			return
		}
		defer schemaIterator.Close()
		index := 1
		for schemaIterator.HasNext(){
			querykv,err := schemaIterator.Next()
			if err != nil {
				errinfo = err
				return
			}
			fmt.Println("add cache key:",querykv.Key)
			_,compisiteKeys ,err := stub.SplitCompositeKey(querykv.Key)
			if err!=nil{
				errinfo = err
				return
			}
			schemaCache.Put(compisiteKeys[0],querykv.Value)
			fmt.Println("add cache key:",querykv.Key)
			index++
			if index > InitSchemaLength {
				fmt.Println("cache data length :",len(schemaCache.HashMap))
				return
			}
		}
		fmt.Println("cache data length :",len(schemaCache.HashMap))
		return
	})
	if errinfo != nil{
	return errinfo
	}
	return nil
}
// Init does nothing for this cc
func (t *GXHCC) Init(stub shim.ChaincodeStubInterface) pb.Response {
	return shim.Success([]byte("GXHCC init successful! "))
}

// Invoke for this chaincode exposes
func (t *GXHCC) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
	// get arguments and transient
	functionName, args := stub.GetFunctionAndParameters()
	err := initSchema(stub)
	if err !=nil{
		return shim.Error(err.Error())
	}
	switch functionName {
	case "schema":
		res, err := SchemaProcess(args, stub)
		if err != nil {
			return shim.Error(fmt.Sprintf("SchemaProcess function err: %s", err))
		}
		return shim.Success([]byte(res))
	case "put":
		res, err := put(args, stub)
		if err != nil {
			return shim.Error(fmt.Sprintf("put data function err: %s", err))
		}
		return shim.Success([]byte(res))
	case "get":
		res, err := get(args, stub)
		if err != nil {
			return shim.Error(fmt.Sprintf("get data function err: %s", err))
		}
		return shim.Success([]byte(res))
	case "update":
		res, err := update(args, stub)
		if err != nil {
			return shim.Error(fmt.Sprintf("update data function err: %s", err))
		}
		return shim.Success([]byte(res))
	case "getCertCommonName":
		name,err := getCertificateCommonName(stub)
		if err != nil{
			return shim.Error(fmt.Sprintf("get certificate CommonName fail,err: %s",err))
		}
		return shim.Success([]byte("current user certificate commonname :" +name))
	default:
		return shim.Error(fmt.Sprintf("Unsupported function %s", functionName))
	}
	return shim.Success([]byte("GXHCC invoke successful "))
}


func put(args []string, stub shim.ChaincodeStubInterface) (string, error) {
	if len(args) < 2 {
		return "", fmt.Errorf("put data operation expected more than 2 parameters! ")
	}
	var PutDatas []map[string]interface{}
	commonName, err := getCertificateCommonName(stub)
	if err != nil {
		return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
	}
	schema := &Schema{}
	result, err := schema.get(args[0], stub)
	if err != nil {
		return "", err
	}
	if err := json.Unmarshal([]byte(result), &schema); err != nil {
		return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail,err: %s ", err)
	}
	if ok,err := authorityCheck(schema.SAuth.Write, commonName);!ok {
		return "", fmt.Errorf("write %s table fail,err: %s ", args[0],err)
	}
	if err := json.Unmarshal([]byte(args[1]), &PutDatas); err != nil {
		return "", fmt.Errorf("%s table parameters Unmarshal fail,put string not json array, err:%s",args[0], err)
	}
	for k, mapres := range PutDatas {
		Id, ok := mapres["id"]
		if !ok {
			return "", fmt.Errorf("The id field must exist ")
		}
		if !SchemaCheck(schema.Fields, mapres) {
			return "", fmt.Errorf("SchemaCheck fail,args index %d string doesn't match %s format", k, args[0])
		}
		if err := FiledsCheck(schema.Fields,mapres);err !=nil{
			return "",err
		}
		putDate, _ := json.Marshal(mapres)
		if err := stub.PutState(PREFIX+"_"+args[0]+"_"+Id.(string), putDate); err != nil {
			return "", fmt.Errorf("PutState fail, err :%s", err)
		}
	}
	return fmt.Sprintf("%s put data success!", args[0]), nil
}

/*
	修改一个表的一条数据的一个或者多个字段值
*/
func update(args []string, stub shim.ChaincodeStubInterface) (string, error) {
	if len(args) != 2 {
		return "", fmt.Errorf("update data operation expected 2 parameters! ")
	}
	commonName, err := getCertificateCommonName(stub)
	if err != nil {
		return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
	}
	schema := &Schema{}
	schemaRes, err := schema.get(args[0], stub)
	if err != nil {
		return "", err
	}
	if err := json.Unmarshal([]byte(schemaRes), &schema); err != nil {
		return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail,err: %s ", err)
	}
	var Updata map[string]interface{}
	var allMap map[string]interface{}
	if err := json.Unmarshal([]byte(args[1]), &Updata); err != nil {
		return "", fmt.Errorf("%s table parameters Unmarshal fail,err: %s",args[0], err)
	}
	Id, ok := Updata["id"]
	if !ok {
		return "", fmt.Errorf("The id field must exist ")
	}
	if ok ,_ := authorityCheck(schema.SAuth.Write, commonName);!ok {
		if ok, err := parsauthorityCheck(schema.Fields, Updata, commonName); !ok {
			return "", fmt.Errorf("authority Check err: %s", err)
		}
	}
	if err := FiledsCheck(schema.Fields,Updata);err !=nil{
		return "",err
	}
	result, err := stub.GetState(PREFIX+"_"+args[0]+"_"+Id.(string))
	if err != nil || result == nil {
		return "", fmt.Errorf("GetState %s data fail,please check your parameters ",args[0]+"_"+Id.(string))
	}
	if err := json.Unmarshal(result, &allMap); err != nil {
		return "", fmt.Errorf("The original data Unmarshal fail err:%s ", err)
	}
	if err := Deassign(Updata, allMap); err != nil {
		return "", err
	}
	resultByte, _ := json.Marshal(allMap)
	if err := stub.PutState(PREFIX+"_"+args[0]+"_"+Id.(string), resultByte); err != nil {
		return "", fmt.Errorf("Put %s date fail, err :%s ",args[0]+"_"+Id.(string), err)
	}
	return fmt.Sprintf("%s update data success!", args[0]), nil
}

func get(args []string, stub shim.ChaincodeStubInterface) (string, error) {
	if len(args) != 2 {
		return "", fmt.Errorf("get data operation expected  2 parameters to function get!")
	}
	commonName, err := getCertificateCommonName(stub)
	if err != nil {
		return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
	}
	var parameters map[string]interface{}
	var mapResult map[string]interface{}

	if err := json.Unmarshal([]byte(args[1]), &parameters); err != nil {
		return "", fmt.Errorf("parameters Unmarshal fail,err: %s", err)
	}

	Id, ok := parameters["id"]
	if !ok {
		return "", fmt.Errorf("The id field must exist ")
	}
	result, err := stub.GetState(PREFIX+"_"+args[0]+"_"+Id.(string))
	if err != nil || result == nil {
		return "", fmt.Errorf("get %s data fail,please check your parameters ",args[0]+"_"+Id.(string))
	}
	schema := &Schema{}
	schemaRes, err := schema.get(args[0], stub)
	if err != nil {
		return "", err
	}
	if err := json.Unmarshal([]byte(schemaRes), &schema); err != nil {
		return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail,err: %s ", err)
	}
	if err := json.Unmarshal(result, &mapResult); err != nil {
		return "", fmt.Errorf("The original data Unmarshal fail err:%s ", err)
	}
	if ok,_:= authorityCheck(schema.SAuth.Read, commonName);!ok {
		if filteredData, err := dataFilter(schema.Fields, mapResult, commonName); err != nil {
			return "", fmt.Errorf("get data authority filter fail, err: %s", err)
		} else {
			result, _ := json.Marshal(filteredData)
			return string(result), nil
		}

	} else {
		return string(result), nil
	}
}

/*
	重新赋值，并检查相应的格式是否正确
*/
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 SchemaCheck(schema map[string]SchemaParameters, checkmap map[string]interface{}) bool {
	if len(schema) != len(checkmap) {
		return false
	}
	for k, v := range checkmap {
		if schemaV, ok := schema[k]; !ok {
			return false
		} else {
			if parameterS, ok := schemaV.Value.(map[string]interface{}); ok {
				if parameterC, ok := v.(map[string]interface{}); !ok {
					return false
				}else{
					if !BackUpCheck(parameterS,parameterC){
						return false
					}
				}
			}
		}
	}
	return true
}

func FiledsCheck(schema map[string]SchemaParameters, checkmap map[string]interface{}) error{
	for k, v := range checkmap {
		if k != "backup" && schema[k].FCheck!= nil&&schema[k].FCheck.FType != ""{
			if err := fieldCheckout(schema[k].FCheck,v);err!=nil{
				return fmt.Errorf("%s %s ",k,err)
			}
		}
	}
	return nil
}

func BackUpCheck(backUp map[string]interface{}, checkmap map[string]interface{}) bool {
	if len(backUp) != len(checkmap) {
		return false
	}
	for k, _ := range checkmap {
		if _, ok := backUp[k]; !ok {
			return false
		}
	}
	return true
}

func SchemaProcess(args []string, stub shim.ChaincodeStubInterface) (string, error) {
	if len(args) < 2 {
		return "", fmt.Errorf("Expect features with 2 or more parameters to play! ")
	}
	schema := &Schema{}
	switch args[0] {

	case "put":
		return schema.put(args[1:], stub)
	case "update":
		return schema.update(args[1:], stub)
	case "get":
		return schema.getSchema(args[1], stub)

	default:
		return "", fmt.Errorf(fmt.Sprintf("Unsupported schema function of %s", args[0]))

	}
}

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

我们可以发现json字符串都被我们解析成了map[string]interface{}类型的map,其中key代表表模板的字段，interface可以是一个结构，我们当前将他看做我们表模板字段的初始值。

*/
func (this *Schema) put(args []string, stub shim.ChaincodeStubInterface) (string, error) {
	if len(args) != 2 {
		return "", fmt.Errorf("Schema  put operation expected  2 parameters!")
	}
	var schema *Schema
	var err error
	if schema ,err = NewSchema(args[1]);err != nil{
		return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail,err: %s ", err)
	}else{
		if backupValue, ok := schema.Fields["backup"]; ok {
			if _,ok := backupValue.Value.(map[string]interface{}); !ok {
				return "", fmt.Errorf("backup parameters Unmarshal fail,it not json string,err: %s", err)
			}
		}
	}
	_, ok := schema.Fields["id"]
	if !ok {
		return "", fmt.Errorf("The id field must exist ")
	}
	CompositeKey,err := stub.CreateCompositeKey(GxhSchema,[]string{args[0]})
	if err != nil{
		return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args[0],err)
	}
	if schemaCache.Get(args[0]) != nil {
		fmt.Println("schemaCache.Get err")
		return "", fmt.Errorf("the schema %s already exists and cannot be added", args[0])
	}else if value, _ := stub.GetState(CompositeKey); value != nil {
		fmt.Println("GetState.Get err")
		return "", fmt.Errorf("the schema %s already exists and cannot be added", args[0])
	}
	putDate, _ := json.Marshal(schema) //处理重复字段
	if err := stub.PutState(CompositeKey, putDate); err != nil {
		return "", fmt.Errorf("Schema PutState fail,err: %s ", err)
	}
 	schemaCache.Put(args[0],putDate)
	return fmt.Sprintf("%s schema put success!", args[0]), nil
}

/*
	if update Schema 那么我们没有办法比较旧有的一个模板，
     Schema 的 update,不支持部分修改，因为存在增加和删除某些字段的情况。
	TODO,增加版本管理
*/
func (this *Schema) update(args []string, stub shim.ChaincodeStubInterface) (string, error) {
	if len(args) != 2 {
		return "", fmt.Errorf("Schema update operation expected 2 parameters! ")
	}
	var schema *Schema
	var err error
	if schema ,err = NewSchema(args[1]);err != nil{
		return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail,err: %s ", err)
	}else{
		if backupValue, ok := schema.Fields["backup"]; ok {
			if _,ok := backupValue.Value.(map[string]interface{}); !ok {
				return "", fmt.Errorf("backup parameters Unmarshal fail,it not json string,err: %s", err)
			}
		}
	}
	_, ok := schema.Fields["id"]
	if !ok {
		return "", fmt.Errorf("The id field must exist ")
	}
	CompositeKey,err := stub.CreateCompositeKey(GxhSchema,[]string{args[0]})
	if err != nil{
		return "", fmt.Errorf("the schema %s create comosite key fail,err : %s", args[0],err)
	}
	var result []byte
	if result = schemaCache.Get(args[0]);result == nil{
		fmt.Println("schemaCache.Get nil")
		result, err := stub.GetState(CompositeKey)
		if err != nil || result == nil {
			return "", fmt.Errorf("%s schema data doesn't exist,please check your parameters ",args[0])
		}
	}
	if err := json.Unmarshal(result, &schema); err != nil {
		return "", fmt.Errorf("The parameters Unmarshal to a Schema structural fail, err: %s ", err)
	}
	commonName, err := getCertificateCommonName(stub)
	if err != nil {
		return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
	}
	if ok,err := authorityCheck(schema.SchemaAuth.Write,commonName);!ok{
		return "", fmt.Errorf("update %s schema fail,err: %s ",args[0],err)
	}
	if err = stub.PutState(CompositeKey, []byte(args[1]));err != nil{
		return "", fmt.Errorf("%s schema data PutState fail,please try again ",args[0])
	}
	schemaCache.Put(args[0],[]byte(args[1]))
	return fmt.Sprintf("%s schema update success!", args[0]), err

}

func (this *Schema) get(args string, stub shim.ChaincodeStubInterface) (string, error) {
	var result []byte
	if result = schemaCache.Get(args);result == 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)
		}
		result, err = stub.GetState(CompositeKey)
		if err != nil || result == nil {
			return "", fmt.Errorf("%s schema data doesn't exist,please check your parameters ",args)
		}
		schemaCache.Put(args,result)
	}
	return string(result), nil
}

func (this *Schema) getSchema(args string, stub shim.ChaincodeStubInterface)(string, error) {
	var result []byte
	if result = schemaCache.Get(args);result == 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)
		}
		result, err = stub.GetState(CompositeKey)
		if err != nil || result == nil {
			return "", fmt.Errorf("%s schema data doesn't exist,please check your parameters ",args)
		}
		schemaCache.Put(args,result)
	}
	if err := json.Unmarshal(result, this); err != nil {
		return "", fmt.Errorf("SchemaData Unmarshal fail, err: %s", err)
	}
	commonName, err := getCertificateCommonName(stub)
	if err != nil {
		return "", fmt.Errorf("getCertificateCommonName happen err: %s ", err)
	}
	if ok,err := authorityCheck(this.SchemaAuth.Read,commonName);!ok{
		return "",fmt.Errorf("get %s schema fail,err: %s", args,err)
	}
	return string(result), 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 parsauthorityCheck(schema map[string]SchemaParameters, checkmap map[string]interface{}, commonName string) (bool, error) {
	for k, v := range checkmap {
		if schemaV, ok := schema[k]; !ok {
			return false, fmt.Errorf("Update data parameter mismatch with schema structure! ")
		} else {
			if _, ok := schemaV.Value.(map[string]interface{}); ok {
				if _, ok := v.(map[string]interface{}); !ok {
					return false, fmt.Errorf("Update data parameter mismatch with schema structure! ")
				}
			}
			if ok,err := authorityCheck(schemaV.PAuth.Write, commonName);!ok {
				return false, fmt.Errorf("%s field permission check does not match, err: %s ", k,err)
			}
		}
	}
	return true, nil
}

/*
	根据权限拼装数据,进行数据过滤
*/
func dataFilter(schema map[string]SchemaParameters, checkmap map[string]interface{}, commonName string) (map[string]interface{}, error) {
	for k, v := range checkmap {
		if schemaV, ok := schema[k]; !ok {
			return nil, fmt.Errorf("Update data parameter mismatch with schema structure! ")
		} else {
			if _, ok := schemaV.Value.(map[string]SchemaParameters); ok {
				if _, ok := v.(map[string]interface{}); !ok {
					return nil, fmt.Errorf("Update data parameter mismatch with schema structure! ")
				}
				if ok,_ := authorityCheck(schemaV.PAuth.Read, commonName);!ok {
					checkmap[k] = defValue
				}
			} else {
				if ok,_ := authorityCheck(schemaV.PAuth.Read, commonName);!ok {
					checkmap[k] = defValue
				}
			}
		}
	}
	return checkmap, nil
}

func authorityCheck(authority AuthGroup, commonName string) (bool,error) {
	var auths map[string]int64
	if IsUsers {
		auths = authority.Users
	}else{
		auths = authority.Roles
	}
	if len(auths) == 0 {
		return true,nil
	}
	for k, v := range auths {
		if k == commonName {
			if v == 0 || v > time.Now().Unix(){
				return true,nil
			}else{
				return false,fmt.Errorf("%s user permission period ",commonName)
			}
		}
	}
	return false,fmt.Errorf("%s user does not have permission",commonName)

}

func NewSchema(arg string)(*Schema,error){
	schema := &Schema{
		Fields:make(map[string]SchemaParameters),
	}
	var argMap map[string]interface{}
	if err := json.Unmarshal([]byte(arg),&argMap);err!=nil{
		return nil,err
	}
	if argMap["fields"] != nil && argMap["schema_auth"] != nil && argMap["auth"] != nil{
		if err := json.Unmarshal([]byte(arg),schema);err!=nil{
			return nil,err
		}
		return schema,nil
	}
	for k,v := range argMap{
		schema.Fields[k] = SchemaParameters{
			Value:v,
			PAuth:Auth{},
		}
	}
	return schema,nil
}

func fieldCheckout(check *Checks,val interface{})error{
	fType := reflect.TypeOf(val).String()

	switch check.FType {
	case "string":
		if fType != "string"{
			return fmt.Errorf("fields type does not match the defined string type! ")
		}
		if check.Must && (val == ""){
			return fmt.Errorf("fields can not be empty")
		}
		value := val.(string)
		if len([]rune(value))>check.Fieldlen{
			return fmt.Errorf("fields length cannot be greater than %d ",check.Fieldlen)
		}
	case "int","int16","int32","int64","float32","float64":
		if fType != "float64"{
			return fmt.Errorf("fields type does not match the defined %s type! ",check.FType )
		}
		value := val.(float64)
		if check.Must && (value == 0){
			return fmt.Errorf("fields can not be 0")
		}
		if check.Fieldlen !=0  && value < 0{
			return fmt.Errorf("fields cannot be negative")
		}
	case "time.Time":
		if fType != "string"{
			return fmt.Errorf("fields type does not match the defined time.Time type! ")
		}
		dateStr := reflect.ValueOf(val).String()
		if check.Must &&  dateStr == ""{
			return fmt.Errorf("fields cannot be empty")
		}
		if _ ,err := time.Parse("2006-1-02 15:04:05",dateStr);err != nil{
			return fmt.Errorf(err.Error())
		}

		//if check.Must && (dateStr == "0001-01-01 00:00:00 +0000 UTC"|| dateStr == "0001-01-01T00:00:00Z"){
		//	return fmt.Errorf("fields cannot be initial value")
		//}
	default:
		fmt.Errorf("fields type no match! ")
	}
	return nil
}

///*
//	根据参数区分不同的表，并执行不同的操作
//*/
//func tableDifferentiate(tableName string,value map[string]interface{}, stub shim.ChaincodeStubInterface)(error){
//	switch tableName {
//
//	case "alibusi":
//		return alibusiCompositeKey(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 alibusiCompositeKey(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
//	}
//	alinkman,ok := value["alinkman"].(string)
//	if !ok{
//		return fmt.Errorf("alinkman fields type not string! ")
//	}
//	alinkmancomKey,err :=stub.CreateCompositeKey(tableName,[]string{alinkman,Id})
//	if err!=nil{
//		return err
//	}
//	amob,ok := value["amob"].(string)
//	if !ok{
//		return fmt.Errorf("amob fields type not string! ")
//	}
//	amobcomKey,err :=stub.CreateCompositeKey(tableName,[]string{amob,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)
//	}
//	if err := stub.PutState(alinkmancomKey, valBy); err != nil {
//		return  fmt.Errorf("Put %s date fail, err :%s ",alinkmancomKey, err)
//	}
//	if err := stub.PutState(amobcomKey, valBy); err != nil {
//		return  fmt.Errorf("Put %s date fail, err :%s ",amobcomKey, err)
//	}
//	return nil
//}

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

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

func (l *LRUCache) Put(key string, value []byte) {
	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)
	}
}

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 main() {
	err := shim.Start(&GXHCC{})
	if err != nil {
		fmt.Printf("Error starting EncCC chaincode: %s", err)
	}
}
