package gameapi

import (
	"../log"
	"../mod"
	pb "../protos"
	"bytes"
	"encoding/xml"
	"github.com/shopspring/decimal"
	"go.uber.org/zap"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"
)

var Vg_addr = "https://ew68.cn/webapi/interface.aspx?"
var vg_agentName = "KG99"
var vg_privateKey = "Dw41e3#0fjj*bhz"

const (
	vg_create = "create"
	vg_loginWithChannel = "loginWithChannel"
	vg_deposit = "deposit"
	vg_withdraw = "withdraw"
	vg_balance = "balance"

	VG_SUCCESS = "0"
	VG_USER_EXISTED = "-99"
	VG_FAILED = "-1"
)

type vgResponse struct {
	Response 	xml.Name 	`xml:"response"`
	Errcode     string 		`xml:"errcode"`
	Errtext		string   	`xml:"errtext"`
	Result   	string   	`xml:"result"`
	Resultdouble float64 	`xml:"resultdouble"`
	Rate		string 		`xml:"rate"`
	Coins		int64 		`xml:"coins"`
	Gametype	string 		`xml:"gametype"`
	In_game		string 		`xml:"in_game"`
}

//平台金币换算
func vg_convertBalance(balance int64) float64 {
	return float64(balance) / 100
}

func VG_Enter_game(guid string, gameParam []string, cash int64, isReconnect bool, res *pb.S_EnterGame) {

	if len(gameParam) != 1 {
		res.Ec = SYS_GAME_PARAM_ERROR
		return
	}
	cash_ := vg_convertBalance(cash) //1:100
	//1.注册
	_,ok1 := vg_do_request(vgGetRegister(vg_create, guid, vg_agentName,""))
	if !ok1 {
		log.Debug("VG_Enter_game register failed ")
		res.Ec = SYS_REGIST_FAILED
		return
	}
	//2.登陆游戏
	gameType,_ := strconv.Atoi(gameParam[0])
	back, ok2 := vg_do_request(vgLogin(vg_loginWithChannel, guid, vg_agentName, gameType,2,1))
	if !ok2 {
		log.Debug("VG_Enter_game login failed ")
		res.Ec = SYS_LOGIN_FAILED
		return
	}

	//2.5重连就不上分了
	if isReconnect{
		res.Ec = SUCCESS
		res.Url = back.Result
		return
	}

	//3.上分
	ref := GetFormatDate()+guid
	_, ok3 := vg_do_request(vgDeposit(vg_deposit, guid, vg_agentName,cash_,ref))
	if !ok3 {
		log.Debug("VG_Enter_game deposit failed ")
		res.Ec = SYS_DEPOSIT_FAILED
		return
	}

	res.Ec = SUCCESS
	res.Url = back.Result
}

func VG_Leave_game(guid string, p_b *pb.S_Ntf_UserBalance, p_r *pb.S_LeaveGame) {

	wd_money , ok := VG_withdraw(guid)
	if ok {
		p_b.Balance = wd_money
		p_r.Ec = SUCCESS
	}else{
		p_r.Ec = SYS_WITHDRAW_FAILED
	}
}

func VG_query_balance(guid string) (bool, float64){
	back, ok := vg_do_request(vgBalance(vg_balance, vg_agentName, guid))
	if ok {
		return true, back.Resultdouble
	}else{
		return false, 0
	}
}


func VG_withdraw(guid string) (balance int64, b bool){
	//1.查询余额
	ok, balance_ := VG_query_balance(guid)
	if !ok{
		log.Debug("VG_withdraw 查询余额 failed")
		return 0 ,false
	}
	//2.下分
	ref2 := GetFormatDate() + guid
	_, ok2 := vg_do_request(vgDeposit(vg_withdraw, guid, vg_agentName, balance_, ref2))
	if !ok2{
		log.Debug("VG_withdraw 取款 failed")
		return 0 ,false
	}

	log.Debug("VG_withdraw 取款 success",zap.Float64("balance", balance_))
	return vg_convertBalanceTo(balance_) ,true
}

//金币换算 游戏->平台
func vg_convertBalanceTo(balance float64) int64 {
	return decimal.NewFromFloat(balance).Mul(decimal.NewFromFloat(100)).IntPart()
}

//强制关端  下分、发送离开游戏事件
func VG_Cronjob(guid uint64, gameId int64) bool {

	s_guid := strconv.FormatUint(guid,10)

	//1.查询余额
	back, ok := vg_do_request(vgBalance(vg_balance, vg_agentName, s_guid))
	if !ok{
		log.Debug("VG_Leave_game query balance failed")
		return false
	}

	//2.下分
	ref2 := GetFormatDate() + s_guid
	vg_do_request(vgDeposit(vg_withdraw, s_guid, vg_agentName, back.Resultdouble, ref2))
	if !ok{
		log.Debug("VG_Leave_game withdraw failed")
		return false
	}

	balance := back.Coins
	//3.给用户加金币
	log.Debug("CQ9_Cronjob redis update balance", zap.Int64("balance", balance))
	new_balance, err := mod.AddUserBalance(guid, balance)
	log.Debug("CQ9_Cronjob new balance", zap.Int64("new_balance", new_balance))
	if err != nil {
		log.Error("CQ9_Cronjob falild", zap.Error(err), zap.Uint64("guid", guid), zap.Int64("balance", balance))
	}
	if new_balance >= 0 {
		//4, 断开游戏连接3分钟以后就不走断线重连,下分成功直接进大厅
		if err := mod.UpdateUserAttr(guid, "regameinfo", ""); err != nil {
			log.Error("CQ9_Cronjob clean regameinfo err,please check", zap.Uint64("guid", guid))
		}
	}
	//5.通知后台更新玩家金币变更
	Nats_Ntf_Balance(guid, gameId, strconv.FormatInt(new_balance, 10), false)
	log.Debug("CQ9_Cronjob withdraw success", zap.Uint64("guid", guid))
	return true
}

func vg_do_request(content string) (vr vgResponse,b bool){

	var back vgResponse
	log.Debug("VG请求: "+ Vg_addr + content)
	resp, err := http.Get(Vg_addr + content)
	if err != nil{
		log.Debug("vg_do_request http.Get",zap.Error(err))
		return back,false
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Debug("vg_do_request ioutil.ReadAll",zap.Error(err))
		return back,false
	}

	if err := xml.Unmarshal(body[:len(body)],&back);err != nil{
		log.Debug("vg_do_request xml.Unmarshal",zap.Error(err))
		return back,false
	}
	log.Debug("VG响应",zap.Any("data", back))
	if back.Errcode == VG_SUCCESS || back.Errcode == VG_USER_EXISTED{
		return back,true
	}else{
		return back,false
	}

}

func vgBalance(action string, channel string, username string) string{
	var buffer bytes.Buffer
	buffer.WriteString("action=")
	buffer.WriteString(action)
	buffer.WriteString("&")
	buffer.WriteString("channel=")
	buffer.WriteString(channel)
	buffer.WriteString("&")
	buffer.WriteString("username=")
	buffer.WriteString(username)
	buffer.WriteString("&")
	buffer.WriteString("verifyCode=")
	buffer.WriteString(strings.ToUpper(Md5Encrypt(action+channel+username+vg_privateKey)))
	return buffer.String()
}

func vgGetRegister(action string, username string, channel string, agent string) string{
	var buffer bytes.Buffer
	buffer.WriteString("action=")
	buffer.WriteString(action)
	buffer.WriteString("&")
	buffer.WriteString("username=")
	buffer.WriteString(username)
	buffer.WriteString("&")
	buffer.WriteString("channel=")
	buffer.WriteString(channel)
	buffer.WriteString("&")
	buffer.WriteString("agent=")
	buffer.WriteString(agent)
	buffer.WriteString("&")
	buffer.WriteString("verifyCode=")
	buffer.WriteString(strings.ToUpper(Md5Encrypt(action+username+channel+agent+vg_privateKey)))
	return buffer.String()
}

func vgLogin(action string, username string, channel string, gametype int,gameversion int,orientation int) string{
	gametype_ := strconv.Itoa(gametype)
	gameversion_ := strconv.Itoa(gameversion)
	orientation_ := strconv.Itoa(orientation)
	var buffer bytes.Buffer
	buffer.WriteString("action=")
	buffer.WriteString(action)
	buffer.WriteString("&")
	buffer.WriteString("username=")
	buffer.WriteString(username)
	buffer.WriteString("&")
	buffer.WriteString("channel=")
	buffer.WriteString(channel)
	buffer.WriteString("&")
	buffer.WriteString("gametype=")
	buffer.WriteString(gametype_)
	buffer.WriteString("&")
	buffer.WriteString("gameversion=")
	buffer.WriteString(gameversion_)
	buffer.WriteString("&")
	buffer.WriteString("orientation=")
	buffer.WriteString(orientation_)
	buffer.WriteString("&")
	buffer.WriteString("verifyCode=")
	buffer.WriteString(strings.ToUpper(Md5Encrypt(action+username+channel+gametype_+gameversion_+orientation_+vg_privateKey)))
	return buffer.String()
}

//上下分都用
func vgDeposit(action string, username string, channel string, amount float64,serial string) string{
	amount_ := strconv.FormatFloat(amount,'f',-1,64)
	var buffer bytes.Buffer
	buffer.WriteString("action=")
	buffer.WriteString(action)
	buffer.WriteString("&")
	buffer.WriteString("username=")
	buffer.WriteString(username)
	buffer.WriteString("&")
	buffer.WriteString("channel=")
	buffer.WriteString(channel)
	buffer.WriteString("&")
	buffer.WriteString("amount=")
	buffer.WriteString(amount_)
	buffer.WriteString("&")
	buffer.WriteString("serial=")
	buffer.WriteString(serial)
	buffer.WriteString("&")
	buffer.WriteString("verifyCode=")
	buffer.WriteString(strings.ToUpper(Md5Encrypt(action+username+channel+amount_+serial+vg_privateKey)))
	return buffer.String()
}
