package bucash

import (
	"bucash/bucashRpc"
	"encoding/json"
	"errors"
	"fmt"
	"sync"
	"strconv"
	"time"

	simplejson "github.com/go-simplejson"
)

type BucashDataApi struct {
}

const BACKUPBLOCKHEIGHT = "backupblockcount"

//Multiple thread operations TxidCount
type TxidCountCache struct {
	TxidCount int
	Locker    sync.RWMutex
}

var txidCountcache TxidCountCache

func (n *TxidCountCache) initCache() {
	n.TxidCount = 0
}
func (n *TxidCountCache) Set() {
	defer n.Locker.Unlock()
	n.Locker.Lock()
	n.TxidCount++
}
func (n *TxidCountCache) Get() int {
	defer n.Locker.Unlock()
	n.Locker.Lock()
	return n.TxidCount
}

//TransRawinfos
var TransRawinfos map[string]interface{}

func init() {
	TransRawinfos = make(map[string]interface{})
}

func GetRawTransaction(txid string) error {
	//get raw transaction info by txid
	result, err := bucashRpc.RunCall("getrawtransaction", txid, 1)
	if err != nil {
		fmt.Println("Call getrawtransaction fail:", err.Error())
		return err
	}

	TransRawinfos[txid] = result
	return nil
}

func GetTransRawinfos(txid string) []byte {
	txinfo := TransRawinfos[txid]
	return []byte(txinfo.([]byte))
}

func DeletTransRawinfos(txid string) {
	delete(TransRawinfos, txid)
}



//get block hash by index
func (m BucashDataApi) WalletGetBlockHash(index uint64) (string, error) {

	var Blockhash RpcResult

	//get block hash by index
	result, err := bucashRpc.RunCall("getblockhash", index)
	if err != nil {
		fmt.Println("Call getblockhash fail:", err.Error())
		return "", err
	}

	if err := json.Unmarshal([]byte(result), &Blockhash); err != nil {
		fmt.Println("Unmarshal err :", err.Error())
		return "", err
	}

	// success
	if len(Blockhash.Error.Message) == 0 {
		return Blockhash.Result, nil
	}
	err = errors.New(Blockhash.Error.Message)
	return "", err
}
//get block Height by hash;
func (m BucashDataApi) WalletGetBlockHeight(blockhash string) (uint64, error) {

	var blockresult BlockResult

	if len(blockhash) == 0 {
		fmt.Println("input para err:")
		err := errors.New("input para err")
		return 0, err
	}
	//get block info by blockhash
	result, err := bucashRpc.RunCall("getblock", blockhash)
	if err != nil {
		fmt.Println("Call getblock fail:", err.Error())
		return 0, err
	}

	if err := json.Unmarshal([]byte(result), &blockresult); err != nil {
		fmt.Println("Unmarshal err :", err.Error())
		return 0, err
	}

	// success
	if len(blockresult.Error.Message) == 0 {

		return uint64(blockresult.Result.Height), nil
	}
	err = errors.New(blockresult.Error.Message)
	return 0, err
}



//get the number of blocks in the longest block chain
func (m BucashDataApi) WalleGetBlockCount() (uint64, error) {

	var blockcount Blockcountresult

	//
	result, err := bucashRpc.RunCall("getblockcount")

	if err != nil {
		fmt.Println("Call getblockcount fail:", err.Error())
		return 0, err
	}

	if err := json.Unmarshal([]byte(result), &blockcount); err != nil {
		fmt.Println("Unmarshal err :", err.Error())
		return 0, err
	}

	// success
	if len(blockcount.Error.Message) == 0 {
		return uint64(blockcount.Result), nil
	}
	err = errors.New(blockcount.Error.Message)
	return 0, err
}

func (m BucashDataApi) WalletInfo() ([]byte, error) {

	var walletinfoResult WalletinfoResult

	//
	result, err := bucashRpc.RunCall("getwalletinfo")

	if err != nil {
		fmt.Println("Call getwalletinfo fail:", err.Error())
		return nil, err
	}

	if err := json.Unmarshal([]byte(result), &walletinfoResult); err != nil {
		fmt.Println("Unmarshal err :", err.Error())
		return nil, err
	}

	// success
	if len(walletinfoResult.Error.Message) == 0 {
		var jbuf []byte
		if jbuf, err = json.Marshal(walletinfoResult.Result); err != nil {
			return nil, err
		}
		return jbuf, nil
	}

	err = errors.New(walletinfoResult.Error.Message)
	return nil, err
}

//get Raw Transaction Vout  by txid and voutindex
func (m BucashDataApi) WalletGetTransactionVout(voutindex uint64, txid string) ([]byte, error) {

	var rawtransactioninfo RawtransactionResult

	if len(txid) == 0 {
		fmt.Println("input para err:")
		err := errors.New("input para err")
		return nil, err
	}
	//get raw transaction info by txid
	result, err := bucashRpc.RunCall("getrawtransaction", txid, 1)
	if err != nil {
		fmt.Println("Call getrawtransaction fail:", err.Error())
		return nil, err
	}

	if err := json.Unmarshal([]byte(result), &rawtransactioninfo); err != nil {
		fmt.Println("Unmarshal err :", err.Error())
		return nil, err
	}

	//get output info:address asm value
	if len(rawtransactioninfo.Error.Message) == 0 {

		for _, vout := range rawtransactioninfo.Result.Vout {

			voutdata := make(map[string]interface{})
			if voutindex == vout.N {
				voutdata["address"] = vout.ScriptPubKey.Addresses
				voutdata["asm"] = vout.ScriptPubKey.Asm
				voutdata["value"] = vout.Value
				var jbuf []byte
				if jbuf, err = json.Marshal(voutdata); err != nil {
					fmt.Println("Marshal err :", err.Error())
					return nil, err
				}
				return jbuf, nil
			}
		}

		err = errors.New("Not find vout info in txid")
		return nil, err

	}
	err = errors.New(rawtransactioninfo.Error.Message)
	return nil, err
}

//get Transaction Vout From bucashdb  by txid and voutindex
func (m BucashDataApi) GetTransactionVoutFromBucashdb(voutindex uint64, txid string) ([]byte, error) {

	if len(txid) == 0 {
		fmt.Println("input para err:")
		err := errors.New("input para err")
		return nil, err
	}
	var txidbyte []byte
	txidbyte, err := json.Marshal(txid)
	if err != nil {
		fmt.Println("Marshal err :", err.Error())
		return nil, err
	}

	//get tx info from bucashdb
	txinfo, err := bucashdb.Get(txidbyte)
	if err != nil {
		fmt.Println("GettxInfo err txid :", txid)
		return nil, err
	}

	js, err := simplejson.NewJson(txinfo)
	if err != nil {
		fmt.Println("NewJson err :", err.Error())
		return nil, err
	}
	voutarry := js.Get("vout").MustArray()
	voutsize := len(voutarry)
	for i := 0; i < voutsize; i++ {
		voutJs := js.Get("vout").GetIndex(i)
		voutNo := voutJs.Get("n").MustUint64()
		voutdata := make(map[string]interface{})
		if voutNo == voutindex {
			addressarry := voutJs.Get("addresses").MustArray()
			addresssize := len(addressarry)
			outputsArr := make([]string, 0)
			for j := 0; j < addresssize; j++ {
				txid := (addressarry[j]).(string)
				outputsArr = append(outputsArr, txid)
			}
			voutdata["address"] = outputsArr
			voutdata["asm"] = voutJs.Get("asm").MustString()
			voutdata["value"] = voutJs.Get("value").MustFloat64()

			var jbuf []byte
			if jbuf, err = json.Marshal(voutdata); err != nil {
				fmt.Println("Marshal err :", err.Error())
				return nil, err
			}

			return jbuf, nil
		}
	}
	err = errors.New("txid voutindex is null")
	return nil, err
}

//get Transaction Vout From TransRawinfos  by txid and voutindex
func (m BucashDataApi) GetTransactionVoutFromTransRawinfos(voutindex uint64, txid string) ([]byte, error) {
	var rawtransactioninfo RawtransactionResult
	result := TransRawinfos[txid]
	if result == nil {
		err := errors.New("TransRawinfos is null")
		return nil, err
	}

	err := json.Unmarshal([]byte(result.([]byte)), &rawtransactioninfo)
	if err != nil {
		fmt.Println("Unmarshal111 err :", err.Error())
		return nil, err
	}
	// success
	if len(rawtransactioninfo.Error.Message) != 0 {
		err = errors.New(rawtransactioninfo.Error.Message)
		return nil, err
	}

	for _, vout := range rawtransactioninfo.Result.Vout {

		if voutindex == vout.N {
			voutdata := make(map[string]interface{})
			voutdata["address"] = vout.ScriptPubKey.Addresses
			voutdata["asm"] = vout.ScriptPubKey.Asm
			voutdata["value"] = vout.Value
			var jbuf []byte
			if jbuf, err = json.Marshal(voutdata); err != nil {
				fmt.Println("Marshal err :", err.Error())
				return nil, err
			}
			return jbuf, nil
		}
	}
	err = errors.New("not find in TransRawinfos")
	return nil, err
}

//Parse Raw Transaction  by txid and write to litecoindb
func (m BucashDataApi) WalletParseRawTransaction(blockheigt uint64, txid string) (bool, error) {
	defer txidCountcache.Set()
	var addrcount int = 0
	var rawtransactioninfo RawtransactionResult
	bucashbatch := bucashdb.NewBatch()

	if len(txid) == 0 {
		fmt.Println("input para err:")
		err := errors.New("input para err")
		return false, err
	}
	result := TransRawinfos[txid]
	if result == nil {
		fmt.Println("TransRawinfos is null txid:", txid)
		err := errors.New("TransRawinfos is null")
		return false, err
	}

	err := json.Unmarshal([]byte(result.([]byte)), &rawtransactioninfo)
	if err != nil {
		fmt.Println("Unmarshal111 err :", err.Error())
		return false, err
	}

	var txidbyte []byte
	if txidbyte, err = json.Marshal(txid); err != nil {
		fmt.Println("Marshal err :", err.Error())
		return false, err
	}

	// success
	if len(rawtransactioninfo.Error.Message) == 0 {

		//get input info:前一个交易的txid以及第几个vout 和asm
		vinAddressArr := make([]map[string]interface{}, 0)
		inputvalue := 0.00000000
		for _, vin := range rawtransactioninfo.Result.Vin {

			vindata := make(map[string]interface{})
			if len(vin.Txid) != 0 {

				vindata["asm"] = vin.ScriptSig.Asm

				vininfo, err := m.GetTransactionVoutFromTransRawinfos(vin.Vout, vin.Txid)
				if err != nil {
					vininfo, err = m.GetTransactionVoutFromBucashdb(vin.Vout, vin.Txid)
				}
				if err == nil {
					var vinaddressInfo AddressInfo
					if err := json.Unmarshal([]byte(vininfo), &vinaddressInfo); err != nil {
						fmt.Println("Unmarshal err :", err.Error())
						return false, err
					}
					vindata["addresses"] = vinaddressInfo.Address
					vindata["value"] = vinaddressInfo.Value
					inputvalue = inputvalue + vinaddressInfo.Value

					//write address to db
					for _, address := range vinaddressInfo.Address {
						vinaddrestxid := fmt.Sprintf("%s:%s", address, txid)
						addrcount++
						bucashbatch.Set([]byte(vinaddrestxid), txidbyte)
					}

				} else {
					fmt.Println("GetTransactionVoutFromlitecoindb fail txid : vin.Txid :", txid, vin.Txid)
					return false, err
				}

			} else {
				vindata["coinbase"] = vin.Coinbase
				inputvalue = 0
			}
			vinAddressArr = append(vinAddressArr, vindata)
		}

		//get output info:address asm value n
		voutAddressArr := make([]map[string]interface{}, 0)
		outputvalue := 0.00000000
		for _, vout := range rawtransactioninfo.Result.Vout {

			voutdata := make(map[string]interface{})
			voutdata["addresses"] = vout.ScriptPubKey.Addresses
			voutdata["asm"] = vout.ScriptPubKey.Asm
			voutdata["value"] = vout.Value
			voutdata["n"] = vout.N
			outputvalue = outputvalue + vout.Value
			voutAddressArr = append(voutAddressArr, voutdata)

			//write address to db
			for _, address := range vout.ScriptPubKey.Addresses {
				voutaddrestxid := fmt.Sprintf("%s:%s", address, txid)
				bucashbatch.Set([]byte(voutaddrestxid), txidbyte)
			}
		}

		resptmp := make(map[string]interface{})
		resptmp["txid"] = txid
		resptmp["blockheight"] = blockheigt
		resptmp["size"] = rawtransactioninfo.Result.Size
		resptmp["time"] = rawtransactioninfo.Result.Time
		resptmp["confirmations"] = rawtransactioninfo.Result.Confirmations
		resptmp["vin"] = vinAddressArr
		resptmp["vout"] = voutAddressArr

		// Accurate to 0.00000001
		inputvaluestr := fmt.Sprintf("%.8f", inputvalue)
		outputvaluestr := fmt.Sprintf("%.8f", outputvalue)

		inputvaluetmp, _ := strconv.ParseFloat(inputvaluestr, 64)
		outputvaluetmp, _ := strconv.ParseFloat(outputvaluestr, 64)

		resptmp["inputvalue"] = inputvaluetmp
		resptmp["outputvalue"] = outputvaluetmp

		if inputvaluetmp > outputvaluetmp {
			feevalue := inputvaluetmp - outputvaluetmp
			feevaluestr := fmt.Sprintf("%.8f", feevalue)
			feevaluetmp, _ := strconv.ParseFloat(feevaluestr, 64)
			resptmp["feevalue"] = feevaluetmp
		} else {
			resptmp["feevalue"] = 0
		}

		//write transinfo to db
		var traninfo []byte
		if traninfo, err = json.Marshal(resptmp); err != nil {
			fmt.Println("Marshal err :", err.Error())
			return false, err
		}
		var txidbyte []byte
		if txidbyte, err = json.Marshal(txid); err != nil {
			fmt.Println("Marshal err :", err.Error())
			return false, err
		}

		bucashbatch.Set(txidbyte, traninfo)
		err = bucashbatch.Write()
		if err != nil {
			return false, err
		}
		LOG("DEBUG", "WalletParseRawTransaction: end vinaddrcount: %v,txid:%v", addrcount, txid)
		return true, nil
	}
	err = errors.New(rawtransactioninfo.Error.Message)
	return false, err
}

//Parse block  by hash;write to db
func (m BucashDataApi) WalletParseBlockInfo(blockhash string) (bool, error) {

	var blockresult BlockResult
	txidcount := 0

	if len(blockhash) == 0 {
		fmt.Println("input para err:")
		err := errors.New("input para err")
		return false, err
	}
	//get block info by blockhash
	result, err := bucashRpc.RunCall("getblock", blockhash)
	if err != nil {
		fmt.Println("Call getblock fail:", err.Error())
		return false, err
	}

	if err := json.Unmarshal([]byte(result), &blockresult); err != nil {
		fmt.Println("Unmarshal err :", err.Error())
		return false, err
	}

	// success
	if len(blockresult.Error.Message) == 0 {

		for _, tx := range blockresult.Result.Tx {

			// get raw transactions in this block
			if len(tx) != 0 {
				result := GetRawTransaction(tx)
				if result != nil {
					return false, result
				}
			}
		}
		LOG("DEBUG", "GetRawTransaction ok")
		txidCountcache.initCache()
		for _, tx := range blockresult.Result.Tx {
			// get transactions count in this block
			if len(tx) != 0 {
				txidcount++
				go m.WalletParseRawTransaction(blockresult.Result.Height, tx)
			}
		}

		for {
			TmpTxidCount := txidCountcache.Get()
			if txidcount <= TmpTxidCount {
				LOG("DEBUG", "TxidCount:%v txidcount:%v", TmpTxidCount, txidcount)
				break
			}
			time.Sleep(time.Microsecond * 1)
		}

		for _, tx := range blockresult.Result.Tx {
			DeletTransRawinfos(tx)
		}

		//encode block info
		resptmp := make(map[string]interface{})
		resptmp["height"] = blockresult.Result.Height
		resptmp["hash"] = blockresult.Result.Hash
		resptmp["size"] = blockresult.Result.Size
		resptmp["time"] = blockresult.Result.Time
		resptmp["difficulty"] = blockresult.Result.Difficulty
		resptmp["version"] = blockresult.Result.Version
		resptmp["nonce"] = blockresult.Result.Nonce
		resptmp["previousblockhash"] = blockresult.Result.Previousblockhash
		resptmp["nextblockhash"] = blockresult.Result.Nextblockhash
		resptmp["merkleroot"] = blockresult.Result.Merkleroot
		resptmp["txcount"] = txidcount
		resptmp["txids"] = blockresult.Result.Tx

		//write blockinf to db
		var blockinfo []byte
		if blockinfo, err = json.Marshal(resptmp); err != nil {
			fmt.Println("Marshal err :", err.Error())
			return false, err
		}

		var blockheight []byte
		if blockheight, err = json.Marshal(blockresult.Result.Height); err != nil {
			fmt.Println("Marshal err :", err.Error())
			return false, err
		}
		bucashbatch := bucashdb.NewBatch()
		bucashbatch.Set(blockheight, blockinfo)
		bucashbatch.Set([]byte(BACKUPBLOCKHEIGHT), blockheight)
		err = bucashbatch.Write()
		if err == nil {
			return true, nil
		} else {
			return false, err
		}

	}
	err = errors.New(blockresult.Error.Message)
	return false, err
}

// back up block info to litecoin db
func (m BucashDataApi) backupblockinfo() (bool, error) {

	var backupblockcount uint64

	//get backupblockcount from litecoindb
	backupblockheight, err := bucashdb.Get([]byte(BACKUPBLOCKHEIGHT))
	if err != nil {
		fmt.Println("bucashdb.Get :", err.Error())
		return false, err
	}
	if len(string(backupblockheight)) == 0 {
		backupblockcount = 0
	} else {
		fmt.Println(".Get BACKUPBLOCKHEIGHT:", string(backupblockheight))

		if err := json.Unmarshal([]byte(backupblockheight), &backupblockcount); err != nil {
			fmt.Println("Unmarshal err :", err.Error())
			return false, err
		}
	}
	fmt.Println("record backup block count:", backupblockcount)

	blockcount, err := m.WalleGetBlockCount()

	if err == nil {
		fmt.Println("current  block count:", blockcount)

		if backupblockcount < blockcount {
			for i := backupblockcount + 1; i < blockcount; i++ {

				filedir, err := m.WalletGetBlockHash(uint64(i))
				if err == nil {
					LOG("DEBUG", "Blockheigt:%v Hash:%v", i, filedir)
					_, err := m.WalletParseBlockInfo(filedir)
					if err == nil {
						LOG("DEBUG", "Parse Blockheight:%v Info success,write in db!", i)
					} else {
						fmt.Println("WalletParseBlockInfo err:", err.Error())
						return false, err
					}
				}
				if err != nil {
					fmt.Println("WalletGetBlockHash err:", err.Error())
					return false, err
				}
			}
		}
		return true, nil
	}
	return false, err
}

//get Trans info from bucashdb by Block Height
func (m BucashDataApi) GetTransByBlockHeight(blockhight uint64) ([]byte, error) {
	var height []byte
	var blockinfoindb Blockinfoindb

	height, err := json.Marshal(blockhight)
	if err != nil {
		fmt.Println("Marshal err :", err.Error())
		return nil, err
	}

	blockinfo, err := bucashdb.Get(height)
	if err != nil {
		fmt.Println("GetBlockInfo blockhight :", blockhight)
		return nil, err
	}

	if err := json.Unmarshal([]byte(blockinfo), &blockinfoindb); err != nil {
		fmt.Println("Unmarshal err :", err.Error())
		return nil, err
	}

	txsArr := make([]map[string]interface{}, 0)
	allinputvalue := 0.00000000
	alloutputvalue := 0.00000000
	allfeevalue := 0.00000000
	//get tx info
	for _, tx := range blockinfoindb.Txids {

		var txbyte []byte
		txbyte, err := json.Marshal(tx)
		if err != nil {
			fmt.Println("Marshal err :", err.Error())
			return nil, err
		}

		txinfo, err := bucashdb.Get(txbyte)
		if err != nil {
			fmt.Println("GettxInfo err txid :", tx)
			return nil, err
		}

		js, err := simplejson.NewJson(txinfo)
		if err != nil {
			fmt.Println("NewJson err txid :", tx)
			return nil, err
		}

		inputvalue := js.Get("inputvalue").MustFloat64()
		outputvalue := js.Get("outputvalue").MustFloat64()
		feevalue := js.Get("feevalue").MustFloat64()
		allinputvalue = allinputvalue + inputvalue
		alloutputvalue = alloutputvalue + outputvalue
		allfeevalue = allfeevalue + feevalue

		var litetransinfoindb map[string]interface{}
		if err := json.Unmarshal([]byte(txinfo), &litetransinfoindb); err != nil {
			fmt.Println("Unmarshal err :", err.Error())
			return nil, err
		}

		txsArr = append(txsArr, litetransinfoindb)
	}

	resptmp := make(map[string]interface{})
	resptmp["errcode"] = 0
	resptmp["cointype"] = "BCC"
	resptmp["height"] = blockhight
	resptmp["hash"] = blockinfoindb.Hash
	resptmp["size"] = blockinfoindb.Size
	resptmp["time"] = blockinfoindb.Time
	resptmp["difficulty"] = blockinfoindb.Difficulty
	resptmp["version"] = blockinfoindb.Version
	resptmp["nonce"] = blockinfoindb.Nonce
	resptmp["previousblockhash"] = blockinfoindb.Previousblockhash
	resptmp["nextblockhash"] = blockinfoindb.Nextblockhash
	resptmp["merkleroot"] = blockinfoindb.Merkleroot
	resptmp["txcount"] = blockinfoindb.Txcount
	resptmp["alloutputvalue"] = alloutputvalue
	resptmp["allfeevalue"] = allfeevalue

	resptmp["trans"] = txsArr
	jbuf, err := json.Marshal(resptmp)
	if err != nil {
		fmt.Println("Marshal err ")
		return nil, err
	}
	return jbuf, err
}

//get trans info from litecoindb by txid
func (m BucashDataApi) GetTransBytxid(txid string) ([]byte, error) {
	var txidbyte []byte
	txidbyte, err := json.Marshal(txid)
	if err != nil {
		fmt.Println("Marshal err :", err.Error())
		return nil, err
	}

	//get tx info
	txinfo, err := bucashdb.Get(txidbyte)
	if err != nil {
		fmt.Println("GettxInfo err txid :", txid)
		return nil, err
	}

	var transinfoindb map[string]interface{}
	if err := json.Unmarshal([]byte(txinfo), &transinfoindb); err != nil {
		fmt.Println("Unmarshal err :", err.Error())
		return nil, err
	}

	resptmp := make(map[string]interface{})
	resptmp["errcode"] = 0
	resptmp["cointype"] = "BCC"
	resptmp["trans"] = transinfoindb
	jbuf, err := json.Marshal(resptmp)
	if err != nil {
		fmt.Println("Marshal err ")
		return nil, err
	}
	return jbuf, err
}

//get trans info from coindb by address
func (m BucashDataApi) GetTransByAddres(address string) ([]byte, error) {

	//get txid info
	txidinfo, err := bucashdb.PrefixScan([]byte(address))
	if err != nil {
		fmt.Println("Get txid by address err address :", address)
		return nil, err
	}

	if txidinfo == nil {
		fmt.Println("Get txidinfo is null  by address :", address)
		return nil, err
	}
	var txids []string
	if err := json.Unmarshal([]byte(txidinfo), &txids); err != nil {
		fmt.Println("Unmarshal err :", err.Error())
		return nil, err
	}
	txcount := 0
	outputsArr := make([]map[string]interface{}, 0)
	//get tx info
	for _, tx := range txids {

		txbyte, err := json.Marshal(tx)
		if err != nil {
			fmt.Println("Marshal err :", err.Error())
			return nil, err
		}

		txinfo, err := bucashdb.Get(txbyte)
		if err != nil {
			fmt.Println("GettxInfo err txid :", tx)
			return nil, err
		}
		var transinfoindb map[string]interface{}
		if err := json.Unmarshal([]byte(txinfo), &transinfoindb); err != nil {
			fmt.Println("Unmarshal err :", err.Error())
			return nil, err
		}

		txcount++
		outputsArr = append(outputsArr, transinfoindb)
	}
	resptmp := make(map[string]interface{})
	resptmp["errcode"] = 0
	resptmp["cointype"] = "BCC"
	resptmp["txcount"] = txcount
	resptmp["trans"] = outputsArr

	jbuf, err := json.Marshal(resptmp)
	if err != nil {
		fmt.Println("Marshal err ")
		return nil, err
	}
	return jbuf, err
}

//get Txids info from coindb by Block Height
func (m BucashDataApi) GetTxidsByBlockHeight(blockhight uint64) ([]byte, error) {
	var height []byte
	var blockinfoindb Blockinfoindb

	height, err := json.Marshal(blockhight)
	if err != nil {
		fmt.Println("Marshal err :", err.Error())
		return nil, err
	}

	blockinfo, err := bucashdb.Get(height)
	if err != nil {
		fmt.Println("GetBlockInfo blockhight :", blockhight)
		return nil, err
	}

	if err := json.Unmarshal([]byte(blockinfo), &blockinfoindb); err != nil {
		fmt.Println("Unmarshal err :", err.Error())
		return nil, err
	}

	allinputvalue := 0.00000000
	alloutputvalue := 0.00000000
	allfeevalue := 0.00000000
	//get tx info
	for _, tx := range blockinfoindb.Txids {

		var txbyte []byte
		txbyte, err := json.Marshal(tx)
		if err != nil {
			fmt.Println("Marshal err :", err.Error())
			return nil, err
		}

		txinfo, err := bucashdb.Get(txbyte)
		if err != nil {
			fmt.Println("GettxInfo err txid :", tx)
			return nil, err
		}

		js, err := simplejson.NewJson(txinfo)
		if err != nil {
			fmt.Println("NewJson err txid :", tx)
			return nil, err
		}

		inputvalue := js.Get("inputvalue").MustFloat64()
		outputvalue := js.Get("outputvalue").MustFloat64()
		feevalue := js.Get("feevalue").MustFloat64()
		allinputvalue = allinputvalue + inputvalue
		alloutputvalue = alloutputvalue + outputvalue
		allfeevalue = allfeevalue + feevalue

	}

	resptmp := make(map[string]interface{})
	resptmp["errcode"] = 0
	resptmp["cointype"] = "BCC"
	resptmp["height"] = blockhight
	resptmp["hash"] = blockinfoindb.Hash
	resptmp["size"] = blockinfoindb.Size
	resptmp["time"] = blockinfoindb.Time
	resptmp["difficulty"] = blockinfoindb.Difficulty
	resptmp["version"] = blockinfoindb.Version
	resptmp["nonce"] = blockinfoindb.Nonce
	resptmp["previousblockhash"] = blockinfoindb.Previousblockhash
	resptmp["nextblockhash"] = blockinfoindb.Nextblockhash
	resptmp["merkleroot"] = blockinfoindb.Merkleroot
	resptmp["txcount"] = blockinfoindb.Txcount
	resptmp["alloutputvalue"] = alloutputvalue
	resptmp["allfeevalue"] = allfeevalue

	resptmp["txids"] = blockinfoindb.Txids
	jbuf, err := json.Marshal(resptmp)
	if err != nil {
		fmt.Println("Marshal err ")
		return nil, err
	}
	return jbuf, err
}

//get Txids info from coindb by address
func (m BucashDataApi) GetTxidsByAddres(address string) ([]byte, error) {

	//get txid info
	txidinfo, err := bucashdb.PrefixScan([]byte(address))
	if err != nil {
		fmt.Println("Get txid by address err address :", address)
		return nil, err
	}

	if txidinfo == nil {
		fmt.Println("Get txidinfo is null  by address :", address)
		return nil, err
	}
	var txids []string
	if err := json.Unmarshal([]byte(txidinfo), &txids); err != nil {
		fmt.Println("Unmarshal err :", err.Error())
		return nil, err
	}
	txcount := 0
	//get tx info
	for _, tx := range txids {
		txcount++
		if len(tx) == 0 {
			fmt.Println("tx is null err :")
		}
	}
	resptmp := make(map[string]interface{})
	resptmp["errcode"] = 0
	resptmp["cointype"] = "BCC"
	resptmp["txcount"] = txcount
	resptmp["txids"] = txids

	jbuf, err := json.Marshal(resptmp)
	if err != nil {
		fmt.Println("Marshal err ")
		return nil, err
	}
	return jbuf, err
}
func (m BucashDataApi) GetCoinDbBlockHeight() (uint64, error) {

	var backupblockcount uint64

	//get backupblockcount from litecoindb
	backupblockheight, err := bucashdb.Get([]byte(BACKUPBLOCKHEIGHT))
	if err != nil {
		fmt.Println("bucashdb.Get :", err.Error())
		return 0, err
	}
	if len(string(backupblockheight)) == 0 {
		backupblockcount = 0
	} else {
		fmt.Println("db.Get BACKUPBLOCKHEIGHT:", string(backupblockheight))

		if err := json.Unmarshal([]byte(backupblockheight), &backupblockcount); err != nil {
			fmt.Println("Unmarshal err :", err.Error())
			return 0, err
		}
	}
	fmt.Println("record backup block count:", backupblockcount)
	return backupblockcount, nil
}

func (m BucashDataApi) InitRpcConf(rpcuser string, rpcpassword string, rpchost string, rpcport int) bool {

	bucashRpc.InitRpcConfig(rpcuser, rpcpassword, rpchost, rpcport)
	return true
}
