package gameapi

import (
	"../log"
	"../mod"
	"../nt"
	"bytes"
	"encoding/json"
	"go.uber.org/zap"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"
)

/*
	延时下分任务处理
 */
const (
	CQ9_TASK_TAG  = "Executor_CQ9"
	DBDZ_TASK_TAG = "Executor_DBDZ"
	FG_TASK_TAG   = "Executor_FG"
	IG_TASK_TAG   = "Executor_IG"
	VG_TASK_TAG   = "Executor_VG"
	ZZYL_TASK_TAG = "Executor_ZZYL"
)

type task struct {
	Id int64
	Conf *rpc_request
	Cmd int32
	Status int32
	LastActive int64
	LastReturn int32
	ExecutedTimes int64
	StartedAt int64
}

type rpc_request struct {
	Name string `json:"name"`
	Group string `json:"group"`
	Time []int `json:"time"`
	Interval int `json:"interval"`
	Condition int `json:"condition"`
	Delay int `json:"delay"`
	Times int `json:"times"`
	Fn string `json:"fn"`
	Params  rpc_params `json:"params"`
}

type rpc_params struct{
	Guid uint64 `json:"guid"`
	GameId int64 `json:"gameId"`
}

type rpc_response struct {
	Ec int `json:"ec"`
	Id int64 `json:"id"`
	Task task `json:"task"`
}

type rem_request struct {
	Ids []int64 `json:"ids"`
}

const (
	task_url        = "http://172.16.0.56:11000" //正式服
	//task_url        = "http://127.0.0.1:6900" //测试服
	add_task_uri 	= task_url+"/v1/pool/add"
	query_task_uri  = task_url+"/v1/pool/query?guid="
	remove_task_uri = task_url+"/v1/pool/remove"
	pause_task_uri  = task_url+"/v1/pool/pause"
	resume_task_uri = task_url+"/v1/pool/resume"
)

//马上执行 然后延迟interval后再次执行
func Add_withdraw_interval(guid uint64, gameId int64, name string, interval int, times int, fn string) {
	params := rpc_params{guid,gameId}
	req := rpc_request{name,"interval",nil,interval,0,0,times,fn,params}
	_, ok := rpc_client_post(add_task_uri, req)
	if ok {
		log.Debug("rpc_add_intervalTask 任务 SUCCESS",zap.Uint64("guid", guid),zap.Int64("gameId", gameId))
	}else{
		log.Debug("rpc_add_intervalTask 任务 failed",zap.Uint64("guid", guid),zap.Int64("gameId", gameId))
	}
}

//delay秒数后开始执行
func Add_withdraw_delay(guid uint64, gameId int64, name string, delay int, times int, fn string){
	params := rpc_params{guid,gameId}
	req := rpc_request{name,"interval",nil,delay,0,delay,times,fn,params}
	_, ok := rpc_client_post(add_task_uri, req)
	if ok {
		log.Debug("rpc_add_delayTask 任务 SUCCESS",zap.Uint64("guid", guid),zap.Int64("gameId", gameId))
	}else{
		log.Debug("rpc_add_delayTask 任务 failed",zap.Uint64("guid", guid),zap.Int64("gameId", gameId))
	}
}

func rem_withdraw_task(guid []int64){
	req := &rem_request{guid}
	_, ok := rpc_client_post( remove_task_uri, req)
	if ok {
		log.Debug("rpc_rem_task 任务 SUCCESS",zap.Any("guids", guid))
	}else{
		log.Debug("rpc_rem_task 任务 failed",zap.Any("guids", guid))
	}
}

//是否有未完成的任务
func Get_withdraw_task(guid string) bool{
	_, ok := rpc_client_get( query_task_uri + guid)
	if ok {
		log.Debug("还有下分任务",zap.String("guid", guid))
		return true
	}else{
		return false
	}
}

func rpc_client_get(url string) (r rpc_response,b bool){

	log.Debug("rpc_client_get 请求", zap.Any("data", url))
	var re rpc_response
	resp, err := http.Get(url)
	if err != nil {
		log.Debug("rpc_client_get Get err", zap.Error(err))
		return re,false
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Debug("rpc_client_get ReadAll err", zap.Error(err))
		return re,false
	}

	if err := json.Unmarshal(body[:len(body)], &re); err != nil {
		log.Debug("rpc_client_get json.Unmarshal", zap.Error(err))
		return re,false
	}

	log.Debug("rpc_client_get 响应", zap.Any("data", re))
	if re.Ec == 0 {
		return re,true
	} else {
		return re,false
	}
}

func rpc_client_post( url string, p interface{}) ( back rpc_response,b bool){

	var re rpc_response
	msg, err := json.Marshal(p)
	if nil != err {
		nt.Log.Debug("Marshal", zap.Error(err), zap.Any("param", p))
		return re,false
	}
	log.Debug("rpc_client_post 请求参数",zap.String("json",string(msg)))
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(msg))
	if nil != err {
		nt.Log.Debug("request", zap.Error(err))
		return re,false
	}
	req.Header.Set("Content-Type", "application/json")
	client := new(http.Client)
	resp, err := client.Do(req)
	if nil != err {
		nt.Log.Debug("do", zap.Error(err))
		return re,false
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		nt.Log.Debug("ioutil.ReadAll", zap.Error(err))
		return re,false
	}

	err = json.Unmarshal(body, &re)
	if nil != err {
		nt.Log.Debug("decode", zap.Error(err),zap.Any("param", body))
		return re,false
	}
	log.Debug("rpc_client_post 响应",zap.Any("response", re))

	if re.Ec == SUCCESS {
		return re,true
	}else{
		return re,false
	}

}

func OnUserLogin_ClearTask(guid uint64) {

	regame, err := mod.GetUserAttr(guid, "regameinfo")
	if err != nil {
		log.Error("OnUserLogout mod.GetUserAttr err", zap.Uint64("guid", guid), zap.Error(err))
		return
	}

	if len(regame) > 0 { //如果是断线重连 删除延时任务
		var guid_arr = make([]int64,1)
		guid_arr[0] = int64(guid)
		rem_withdraw_task(guid_arr)
	}
}

func dispatch_taskByShutDown(guid uint64, gameId int64) {

	makerId := GetChannelByGameId(gameId)
	guid_str := strconv.FormatUint(guid, 10)
	switch makerId {

	//共享钱包
	case HONGBO, DBDZ:
		Ntf_Nats_LeaveGameInfo(guid, gameId)

	//上下分
	case ZZYL:
		Add_withdraw_interval(guid, gameId,
			guid_str, 15, 200, ZZYL_TASK_TAG)

	case IG_DZ,IG_LOTTERY,IG_LMG:
		Add_withdraw_interval(guid, gameId,
			guid_str, 5, 100, IG_TASK_TAG)

	case CQ9_DZ,CQ9_BY:
		Add_withdraw_delay(guid, gameId,
			guid_str, 5, 100, CQ9_TASK_TAG)

	case DBDZ_QP:
		Add_withdraw_interval(guid, gameId,
			guid_str, 8, 200, DBDZ_TASK_TAG)

	case VG: //共享钱包都用这种方式
		Add_withdraw_interval(guid, gameId,
			guid_str, 8, 200, VG_TASK_TAG)

	case FG:
		Add_withdraw_interval(guid, gameId,
			guid_str, 5, 100, FG_TASK_TAG)
	}
}

//强制关端 处理未完成的牌局结算
func OnUserLogout_AddTask(guid uint64){
	regame, err := mod.GetUserAttr(guid, "regameinfo")
	if err != nil {
		log.Error("OnUserLogout mod.GetUserAttr err", zap.Uint64("guid", guid), zap.Error(err))
		return
	}

	if len(regame) > 0 { //如果是断线重连 开启定时任务:15分钟后请求下分
		strArr := strings.Split(regame, "#") //存放 接入游戏大类id和接入游戏子id
		gameId, err := strconv.Atoi(strArr[0])
		if err != nil {
			log.Error("OnUserLogout strconv.Atoi err", zap.Error(err))
		}
		log.Debug("强制关端 放入下分任务",zap.Uint64("guid",guid),zap.Int("gameId",gameId))
		dispatch_taskByShutDown(guid, int64(gameId))
	}
}

//后台手动下分
func PHP_withdraw(guid string) (bool,int64){
	var detal int64 = 0
	var ok bool     = true
	detal, ok = CQ9_withdraw(guid)
	if ok && detal > 0 {
		log.Debug("后台手动下分SUCCESS-CQ9",zap.String("guid",guid),zap.Int64("detal",detal))
		return true,detal
	}
	detal, ok = DBDZ_QP_withdraw(guid)
	if ok && detal > 0 {
		log.Debug("后台手动下分SUCCESS-DBDZ_QP",zap.String("guid",guid),zap.Int64("detal",detal))
		return true,detal
	}
	detal, ok = FG_withdraw(guid)
	if ok && detal > 0 {
		log.Debug("后台手动下分SUCCESS-FG",zap.String("guid",guid),zap.Int64("detal",detal))
		return true,detal
	}
	detal, ok = IG_withdraw(guid)
	if ok && detal > 0 {
		log.Debug("后台手动下分SUCCESS-IG",zap.String("guid",guid),zap.Int64("detal",detal))
		return true,detal
	}
	detal, ok = VG_withdraw(guid)
	if ok && detal > 0 {
		log.Debug("后台手动下分SUCCESS-VG",zap.String("guid",guid),zap.Int64("detal",detal))
		return true,detal
	}
	detal, ok = ZZYL_withdraw(guid)
	if ok && detal > 0 {
		log.Debug("后台手动下分SUCCESS-ZZYL",zap.String("guid",guid),zap.Int64("detal",detal))
		return true,detal
	}
	log.Debug("后台手动下分FAILED,please check log",zap.String("guid",guid))
	return false,0
}