package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	//"github.com/33cn/chain33/types"
	"io/ioutil"
	"net/http"
	"os"
	//"strconv"
	"strings"
	"strconv"
	//jsonrpc "github.com/33cn/chain33/rpc/jsonclient"
	//pty "github.com/33cn/plugin/plugin/dapp/guess/types"
)

var (

	/*
	测试步骤
	1.搭建Guess平行连测试环境。并创建地址addr1,addr2,addr3
	  addr1:
	  priv1:

	  addr2:
	  priv2:

	  addr3:
	  priv3:

	2.从创世地址中获得测试主链的bty，转给addr1,addr2,addr3,作为交易费用及投注费用
	3.addr1创建游戏id1，有Ａ，Ｂ两个选项，成功
	  addr2,addr3 bet游戏id1的不同选项Ａ，Ｂ,成功
	　addr2,addr3 bet游戏id1的不同选项Ｃ，1,失败
	  addr2,addr3尝试对游戏id1进行abort或者stopBet或者publish，失败。
	　addr1进行stopBet游戏id1,成功。
	  addr2,addr3尝试bet游戏id1。
	　addr1进行publish游戏id1,结果为Ａ，成功。
	　addr2中奖，Addr3未中奖。

	4.对历史数据进行查询
	　//待补充
	*/
	Jrpc_Url = "http://192.168.0.233:8901"
	//Jrpc_Url = "http://localhost:8801"
	//Jrpc_Url = "http://192.168.0.159:8901"
	//Jrpc_Url = "http://192.168.0.159:8901"

	//creatorAddr = "15nn4D2ppUj8tmyHfdm8g4EvtqpBYUS7DM"
	creatorAddr = "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
	//creatorAddr = "19MJmA7GcE1NfMwdGqgLJioBjVbzQnVYvR"
	closeAddr = "15nn4D2ppUj8tmyHfdm8g4EvtqpBYUS7DM"

	drawAddr = "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
	//creatorAddr = "15nn4D2ppUj8tmyHfdm8g4EvtqpBYUS7DM"

	zzhAddr = "1M3BKgh9hAzY5xcEmCCtAkainjCtrbqU3k"

	fee          int64 = 1e6
	purBlockNum        = 30 //600s
	drawBlockNum       = 40 //180s

	lotteryId string = "0xbbb31fa891c8b1e5d73ad928057573a812c8cf59bcae3e5da20f8951ad4e7e54"
	//lotteryId string = "0x1b5b038e27f265e4a583a2736517522316ea876259ee53c22af30a8fdb474bec"
	//lotteryId string = "0x4f50e96ac0baaf69e01689668eb3087b675c989cad08643e120ab0f163de7ad0"
	gameId string = "0x9fda83a900faa12aad6c6532fd53668df92b1d151707bc402e264ed25568d71e"

	execAddr = "1YJCAQKymbBW48KViUpo8tS66ee1n3hnD"
)

func init() {

}

func main() {
	fmt.Println(len(os.Args))

	if len(os.Args) < 2 {
		return
	}
	for _, arg := range os.Args {
		fmt.Println(arg)
	}

	if os.Args[1] == "testCreate" {
		testCreateGuess(os.Args[2])
	} else if os.Args[1] == "testBet" {
		testBetGuess(os.Args[2], os.Args[3], os.Args[4])
	} else if os.Args[1] == "testPublish" {
		testPublishGuess(os.Args[2], os.Args[3], os.Args[4])
	} else if os.Args[1] == "testStopBet" {
		testStopBetGuess(os.Args[2], os.Args[3])
	} else if os.Args[1] == "testAbort" {
		testAbortGuess(os.Args[2], os.Args[3])
	} else if os.Args[1] == "testQueryGameById" {
		testQueryGameById(os.Args[2])
	} else if os.Args[1] == "testQueryGamesByAddr" {
                index, _ := strconv.ParseInt(os.Args[3], 10, 64)
		testQueryGamesByAddr(os.Args[2], index)
	} else if os.Args[1] == "testQueryGamesByStatus" {
		status, _ := strconv.Atoi(os.Args[2])
		index, _ := strconv.ParseInt(os.Args[3], 10, 64)
		testQueryGamesByStatus(int32(status), index)
	} else if os.Args[1] == "testQueryGamesByAdminAddr" {
		index, _ := strconv.ParseInt(os.Args[3], 10, 64)
		testQueryGamesByAdminAddr(os.Args[2], index)
	} else if os.Args[1] == "testQueryGamesByAddrStatus" {
		status, _ := strconv.Atoi(os.Args[3])
		index, _ := strconv.ParseInt(os.Args[4], 10, 64)
		testQueryGamesByAddrStatus(os.Args[2], int32(status), index)
	} else if os.Args[1] == "testQueryGamesByAdminStatus" {
		status, _ := strconv.Atoi(os.Args[3])
		index, _ := strconv.ParseInt(os.Args[4], 10, 64)
		testQueryGamesByAdminStatus(os.Args[2], int32(status), index)
	} else if os.Args[1] == "testQueryGamesByCategoryStatus" {
		status, _ := strconv.Atoi(os.Args[3])
		index, _ := strconv.ParseInt(os.Args[4], 10, 64)
		testQueryGamesByCategoryStatus(os.Args[2], int32(status), index)
	}

}

func getJrpc() string {
	return Jrpc_Url
}

//create txs

func constructTx(poststr string) (string, error) {
	resp, err := http.Post(getJrpc(), "application/json", bytes.NewBufferString(poststr))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	var txdata = make(map[string]interface{})
	fmt.Println("resp:", string(data))

	err = json.Unmarshal(data, &txdata)
	fmt.Println("txdata:", txdata)
	if err != nil {
		fmt.Println("err:", err.Error())
		return "", err
	}
	if hextx, ok := txdata["result"]; ok {
		fmt.Println("hextx:", hextx)
		return hextx.(string), nil
	}
	return "", fmt.Errorf("not have result!")

}

func createGuessGameStartTx() (string, error) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":2,"method":"Chain33.CreateTransaction","params":[{"execer":"guess","actionName":"GuessStart", "payload":{"topic":"%v","options":"%v", "category":"%v","maxBets":%v,"maxBetsNumber":%v,"fee":%v}}]}`,"WorldCup Final", "A:France;B:Claodia", "football", int64(100e8), int64(1000e8),fee)
	fmt.Println(poststr)
	return constructTx(poststr)
}

func createGuessGameBetTx(id, option string) (string, error) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":2,"method":"Chain33.CreateTransaction",
                                   "params":[{"execer":"guess","actionName":"GuessBet", "payload":{"gameId":"%v","option":"%v", "betsNum":%v,"fee":%v}}]}`,
		id, option, int64(500000000),fee)
	fmt.Println(poststr)
	return constructTx(poststr)
}

func createGuessGamePublishTx(id, option string) (string, error) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":2,"method":"Chain33.CreateTransaction",
                                   "params":[{"execer":"guess","actionName":"GuessPublish", "payload":{"gameId":"%v","result":"%v", "fee":%v}}]}`,
		id, option, fee)
	fmt.Println(poststr)
	return constructTx(poststr)
}

func createGuessGameStopBetTx(id string) (string, error) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":2,"method":"Chain33.CreateTransaction",
                                  "params":[{"execer":"guess","actionName":"GuessStopBet", "payload":{"gameId":"%v", "fee":%v}}]}`,
		id, fee)
	fmt.Println(poststr)
	return constructTx(poststr)
}

func createGuessGameAbortTx(id string) (string, error) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":2,"method":"Chain33.CreateTransaction",
                                  "params":[{"execer":"guess","actionName":"GuessAbort", "payload":{"gameId":"%v", "fee":%v}}]}`,
		id, fee)
	fmt.Println(poststr)
	return constructTx(poststr)
}
//actions

func testCreateGuess(addr string) {
	hexCreateTx, err := createGuessGameStartTx()
	fmt.Println("createx:", hexCreateTx)
	if err != nil {
		fmt.Println("testCreateGuess have a err:", err.Error())
		return
	}
	hexTx, err := SignRawTx(hexCreateTx, addr, "0x8d8523fbd09c27dabc853e99daf167533acaa1e2a2498dc2cb7449cff8137a37", "3600s", 0)
	if err != nil {
		fmt.Println("SignRawTx have a err:", err.Error())
		return
	}
	SendTx(hexTx)
}

func testBetGuess(id, option, addr string) {
	betTx, err := createGuessGameBetTx(id, option)
	if err != nil {
		fmt.Println("testBetGuess have a err:", err.Error())
		return
	}

	fmt.Println("resp:", (betTx))

	hexTx, err := SignRawTx(betTx, addr, "", "3600s", 0)
	if err != nil {
		fmt.Println("SignRawTx have a err:", err.Error())
		return
	}
	SendTx(hexTx)

}

func testStopBetGuess(id, addr string) {
	publishTx, err := createGuessGameStopBetTx(id)
	if err != nil {
		fmt.Println("testDrawLottery have a err:", err.Error())
		return
	}
	hexTx, err := SignRawTx(publishTx, addr, "", "3600s", 0)
	if err != nil {
		fmt.Println("SignRawTx have a err:", err.Error())
		return
	}
	SendTx(hexTx)
}

func testPublishGuess(id, option, addr string) {
	publishTx, err := createGuessGamePublishTx(id, option)
	if err != nil {
		fmt.Println("testDrawLottery have a err:", err.Error())
		return
	}
	hexTx, err := SignRawTx(publishTx, addr, "", "3600s", 0)
	if err != nil {
		fmt.Println("SignRawTx have a err:", err.Error())
		return
	}
	SendTx(hexTx)
}

func testAbortGuess(id, addr string) {
	publishTx, err := createGuessGameAbortTx(id)
	if err != nil {
		fmt.Println("testDrawLottery have a err:", err.Error())
		return
	}
	hexTx, err := SignRawTx(publishTx, addr, "", "3600s", 0)
	if err != nil {
		fmt.Println("SignRawTx have a err:", err.Error())
		return
	}
	SendTx(hexTx)
}

func SignRawTx(rawTx, addr, privKey, expire string, index int32) (string, error) {
	client := http.DefaultClient
	postdata := fmt.Sprintf(`{"jsonrpc":"2.0","id":1,"method":"Chain33.SignRawTx",
"params":[{"addr":"%v","privKey":"%v","txHex":"%v","expire":"%v","index":%v,"model":%v}]}`, addr, privKey, rawTx, expire, index, 0)
	req, err := http.NewRequest("post", getJrpc(), strings.NewReader(postdata))
	if err != nil {
		fmt.Println("err:", err.Error())
		return "", err
	}
	fmt.Printf("postdata:%v\n", postdata)
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("err:", err.Error())
		return "", err
	}
	defer resp.Body.Close()

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("err:", err.Error())
		return "", err
	}
	var txdata = make(map[string]interface{})
	fmt.Println("resp:", string(data))
	err = json.Unmarshal(data, &txdata)
	if err != nil {
		fmt.Println("err:", err.Error())
		return "", err
	}
	if hextx, ok := txdata["result"]; ok {
		return hextx.(string), nil
	}
	return "", fmt.Errorf("not have result!")
}

func SendTx(hexTx string) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":2,"method":"Chain33.SendTransaction","params":[{"data":"%v"}]}`,
		hexTx)

	resp, err := http.Post(getJrpc(), "application/json", bytes.NewBufferString(poststr))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	fmt.Printf("returned JSON: %s\n", string(b))
}

func testQueryGamesByIds(gameId string) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":0,"method":"Chain33.Query",
"params":[{"execer":"guess","funcName":"QueryGamesByIds","payload":{"gameIds":[{"%v"}]}}]}`, gameId)

	resp, err := http.Post(getJrpc(), "application/json", bytes.NewBufferString(poststr))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	var txdata = make(map[string]interface{})
	fmt.Println("resp:", string(data))
	err = json.Unmarshal(data, &txdata)
	if err != nil {
		fmt.Println("err:", err.Error())
		return
	}

	return
}

func testQueryGameById(gameId string) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":0,"method":"Chain33.Query",
"params":[{"execer":"guess","funcName":"QueryGameById","payload":{"gameId":"%v"}}]}`, gameId)

	resp, err := http.Post(getJrpc(), "application/json", bytes.NewBufferString(poststr))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	var txdata = make(map[string]interface{})
	fmt.Println("resp:", string(data))
	err = json.Unmarshal(data, &txdata)
	if err != nil {
		fmt.Println("err:", err.Error())
		return
	}

	return
}

func testQueryGamesByAddr(addr string,index int64) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":0,"method":"Chain33.Query",
"params":[{"execer":"guess","funcName":"QueryGamesByAddr","payload":{"addr":"%v","index":"%v"}}]}`, addr, index)

	resp, err := http.Post(getJrpc(), "application/json", bytes.NewBufferString(poststr))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	var txdata = make(map[string]interface{})
	fmt.Println("resp:", string(data))
	err = json.Unmarshal(data, &txdata)
	if err != nil {
		fmt.Println("err:", err.Error())
		return
	}

	return
}

func testQueryGamesByStatus(status int32, index int64) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":0,"method":"Chain33.Query",
"params":[{"execer":"guess","funcName":"QueryGamesByStatus","payload":{"status":"%v","index":"%v"}}]}`, status, index)

	resp, err := http.Post(getJrpc(), "application/json", bytes.NewBufferString(poststr))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	var txdata = make(map[string]interface{})
	fmt.Println("resp:", string(data))
	err = json.Unmarshal(data, &txdata)
	if err != nil {
		fmt.Println("err:", err.Error())
		return
	}

	return
}

func testQueryGamesByAdminAddr(addr string,index int64) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":0,"method":"Chain33.Query",
"params":[{"execer":"guess","funcName":"QueryGamesByAdminAddr","payload":{"adminAddr":"%v","index":"%v"}}]}`, addr, index)

	resp, err := http.Post(getJrpc(), "application/json", bytes.NewBufferString(poststr))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	var txdata = make(map[string]interface{})
	fmt.Println("resp:", string(data))
	err = json.Unmarshal(data, &txdata)
	if err != nil {
		fmt.Println("err:", err.Error())
		return
	}

	return
}


func testQueryGamesByAddrStatus(addr string,status int32, index int64) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":0,"method":"Chain33.Query",
"params":[{"execer":"guess","funcName":"QueryGamesByAddrStatus","payload":{"addr":"%v","status":"%v","index":"%v"}}]}`, addr, status, index)

	resp, err := http.Post(getJrpc(), "application/json", bytes.NewBufferString(poststr))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	var txdata = make(map[string]interface{})
	fmt.Println("resp:", string(data))
	err = json.Unmarshal(data, &txdata)
	if err != nil {
		fmt.Println("err:", err.Error())
		return
	}

	return
}

func testQueryGamesByAdminStatus(addr string,status int32, index int64) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":0,"method":"Chain33.Query",
"params":[{"execer":"guess","funcName":"QueryGamesByAdminStatus","payload":{"adminAddr":"%v","status":"%v","index":"%v"}}]}`, addr, status, index)

	resp, err := http.Post(getJrpc(), "application/json", bytes.NewBufferString(poststr))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	var txdata = make(map[string]interface{})
	fmt.Println("resp:", string(data))
	err = json.Unmarshal(data, &txdata)
	if err != nil {
		fmt.Println("err:", err.Error())
		return
	}

	return
}

func testQueryGamesByCategoryStatus(category string,status int32, index int64) {
	poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":0,"method":"Chain33.Query",
"params":[{"execer":"guess","funcName":"QueryGamesByCategoryStatus","payload":{"category":"%v","status":"%v","index":"%v"}}]}`, category, status, index)

	resp, err := http.Post(getJrpc(), "application/json", bytes.NewBufferString(poststr))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	var txdata = make(map[string]interface{})
	fmt.Println("resp:", string(data))
	err = json.Unmarshal(data, &txdata)
	if err != nil {
		fmt.Println("err:", err.Error())
		return
	}

	return
}
