package logic

import (
	"World/clubmgr"
	"World/common"
	"World/conf"
	"World/db"
	"World/pb"
	pmgr "World/playermgr"
	"World/utils"
	"common/logger"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

var ch chan *ClubGrantFundData

func StartHttpServe() {
	startServerHttpServe()
}

func CheckErr(err error) {
	if err != nil {
		panic(err)
	}
}

func startServerHttpServe() {
	http.HandleFunc("/reviewalliance", ReviewAllianceHandler)
	http.HandleFunc("/clubgrantfund", ClubGrantFundHandler)
	http.HandleFunc("/clubincometransfer", ClubIncomeTransferHandler)
	http.HandleFunc("/allianceincometransfer", AllianceIncomeTransferHandler)
	http.HandleFunc("/rechagregold", RechargeGoldHandler)
	err := http.ListenAndServe(conf.GetServerHttpAddrConf(), nil)
	CheckErr(err)
}

func ClubGrantFundHandler(w http.ResponseWriter, r *http.Request) {
	defer utils.PrintPanicStack()

	result, _ := ioutil.ReadAll(r.Body)
	r.Body.Close()

	s := string(result)
	logger.Info("ClubGrantFundHandler handler, body:%v", s)

	HandleClubGrantFund(s)
	fmt.Fprint(w, "Success!")
}

type ClubGrantFundData struct {
	OpPlayerId uint32 `json:"op_player_id"`
	ClubId     uint32 `json:"club_id"`
	TargetId   uint32 `json:"target_id"`
	Amount     int64  `json:"amount"`
}

func HandleClubGrantFund(data string) {
	var cdata ClubGrantFundData
	err := json.Unmarshal([]byte(data), &cdata)

	if err != nil {
		logger.Info("json decode ClubGrantFundData data failed:%v", err, " for:%v", data)
		return
	}

	logger.Info("###HandleClubGrantFund###cdata:", cdata)

	var player *common.GamePlayer = nil
	var err_num common.ErrorType = common.Error_OK
	for {
		var er error = nil
		player, er = pmgr.GetPlayerFromMap(cdata.OpPlayerId)
		if er != nil {
			err_num = common.Error_Player_Not_Found
			logger.Notic("get player uid:%v failed for%v", cdata.OpPlayerId, err_num)
			break
		}

		//请求者不是管理员也不是创建者则退出
		if !clubmgr.HasPrivilege(cdata.ClubId, cdata.OpPlayerId) {
			err_num = common.Error_Club_Privilege_Not_Enough
			logger.Notic("HasPrivilege uid:%v for %v", cdata.OpPlayerId, err_num)
			break
		}

		if cdata.Amount < 0 {
			err_num = common.Error_Club_Other
			logger.Notic("Amount invalid uid:%v failed:%v Amount:%v", cdata.OpPlayerId, err_num, cdata.Amount)
			break
		}

		//转账者金币是否足够
		curGoldNum, err := db.GetUserGoldNum(cdata.OpPlayerId)
		if err != nil {
			err_num = common.Error_Club_Other
			logger.Notic("db.GetUserGoldNum failed err:%v", err)
			break
		}

		if curGoldNum < cdata.Amount {
			err_num = common.Error_Club_Fund_Not_Enough
			logger.Notic("curGoldNum is not enough uid:%v failed:%v ClubId:%v Amount:%v", cdata.OpPlayerId, err_num, cdata.ClubId, cdata.Amount)
			break
		}

		//做修改操作
		err_num = clubmgr.DoGrantClubFundNew(cdata.ClubId, cdata.TargetId, cdata.Amount, cdata.OpPlayerId)
		if err_num != common.Error_OK {
			logger.Notic("DoGrantClubFund uid:%v failed:%v ClubId:%v TargetId:%v Amount:%v", cdata.OpPlayerId, err_num, cdata.ClubId, cdata.TargetId, cdata.Amount)
			break
		}

		break

	}

	logger.Info("HandleClubGrantFund result uid:%v err_num:%v", cdata.OpPlayerId, err_num)

	//通知客户的转账成功
	var noti pb.ClubGrantFundNotice
	noti.Error = int32(err_num)
	noti.OpPlayerId = uint32(cdata.OpPlayerId)
	noti.Clubid = uint32(cdata.ClubId)
	noti.Targetid = uint32(cdata.TargetId)
	noti.Amount = cdata.Amount
	common.SendNoti(player, uint32(0), uint32(cdata.OpPlayerId), pb.MSGID_MsgID_ClubGrantFund_Notice, &noti)

}

func ReviewAllianceHandler(w http.ResponseWriter, r *http.Request) {
	defer utils.PrintPanicStack()

	result, _ := ioutil.ReadAll(r.Body)
	r.Body.Close()

	s := string(result)
	logger.Info("ReviewAllianceHandler , body:%v", s)

	go HandleReviewedAlliance(s)
	fmt.Fprint(w, "Success!")
}

type ReviewAllianceData struct {
	AllianceId    uint32 `json:"alliance_id"`
	CreaterClubId uint32 `json:"creater_club_id"`
	Reviewed      int    `json:"reviewed"`
	Reason        string `json:"reason"`
}

func HandleReviewedAlliance(data string) {
	var rdata ReviewAllianceData
	err := json.Unmarshal([]byte(data), &rdata)
	if err != nil {
		logger.Info("json decode ReviewAlliance data failed:%v", err, " for:%v", data)
		return
	}

	logger.Info("###HandleGameData###rdata:", rdata)
	if rdata.Reviewed == 1 {
		db.ModifyAllianceStatus(rdata.AllianceId, rdata.Reviewed, rdata.Reason)
	} else {
		db.RemoveAllianceMember(rdata.CreaterClubId, rdata.AllianceId)
		db.DeleteFromAlliance(rdata.AllianceId)
	}
}

func ClubIncomeTransferHandler(w http.ResponseWriter, r *http.Request) {
	defer utils.PrintPanicStack()

	result, _ := ioutil.ReadAll(r.Body)
	r.Body.Close()

	s := string(result)
	logger.Info("ClubIncomeTransferHandler, body:%v", s)

	//go HandleClubIncomeTransfer(s)
	err := HandleClubIncomeTransfer(s)
	if err == nil {
		fmt.Fprint(w, "Success!")
	} else {
		fmt.Fprint(w, "failed!")
	}
}

type ClubIncomeTransferData struct {
	UID uint32 `json:"uid"`
}

func HandleClubIncomeTransfer(data string) error {
	var goldAfter int64 = 0
	var rdata ClubIncomeTransferData
	err := json.Unmarshal([]byte(data), &rdata)
	if err != nil {
		logger.Info("json decode ClubIncomeTransfer data failed:%v", err, " for:%v", data)
		return err
	}

	logger.Info("###HandleClubIncomeTransfer###rdata:", rdata)
	//取出来
	db.ClubIncome_locker.Lock()
	for {
		if err = db.CheckAndLoadClubIncome(uint32(rdata.UID)); err != nil {
			break
		}
		ccuidIncome, _ := db.GetClubIncome(int(rdata.UID))
		if ccuidIncome == nil {
			ccuidIncome = new(common.ClubCreaterIncomeInfo)
		}
		amount := int64(ccuidIncome.Total)
		_, goldAfter, err = db.OperateRequesterGold(rdata.UID, amount, db.Add)
		if err == nil {
			ccuidIncome.Fee = 0
			ccuidIncome.Insurance = 0
			ccuidIncome.Jackpot = 0
			ccuidIncome.Total -= amount

			db.UpdateClubIncome(int(rdata.UID), ccuidIncome)
			if err = db.SyncClubIncomeToDB(int(rdata.UID)); err != nil {
				break
			}

			if err = db.RecordClubIncomeTransfer(rdata.UID, amount); err != nil {
				logger.Notic("RecordClubIncomeTransfer failed uid:%v amount", rdata.UID, amount)
				break
			}

			player, err := pmgr.GetPlayerFromMap(rdata.UID)
			if err == nil {
				common.SendGoldNumNotify(player, 0, uint32(rdata.UID), int64(goldAfter), int64(amount))
			} else {
				logger.Notic("Player not found uid:%v", rdata.UID)
			}

		} else {
			logger.Warn("HandleClubIncomeTransfer Add gold failed uid:%v,err:%v", rdata.UID, err)
			break
		}

		break
	}
	db.ClubIncome_locker.Unlock()
	return err
}

func AllianceIncomeTransferHandler(w http.ResponseWriter, r *http.Request) {
	log.Println("AllianceIncomeTransferHandler")
	defer utils.PrintPanicStack()

	result, _ := ioutil.ReadAll(r.Body)
	r.Body.Close()

	s := string(result)
	logger.Info("AllianceIncomeTransferHandler, body:%v", s)

	//go HandleAllianceIncomeTransfer(s)
	HandleAllianceIncomeTransfer(s)
	fmt.Fprint(w, "Success!")
}

type NotifyRechargeData struct {
	PlayerId uint32 `json:"player_id"`
	Amount   int64  `json:"amount"`
}

func RechargeGoldHandler(w http.ResponseWriter, r *http.Request) {
	logger.Info("RechargeGoldHandler!")
	defer utils.PrintPanicStack()

	result, _ := ioutil.ReadAll(r.Body)
	r.Body.Close()

	s := string(result)

	err := HandleRechargeGold(s)
	if err != nil {
		fmt.Fprint(w, "Failed!")
	} else {
		fmt.Fprint(w, "Success!")
	}

}

func HandleRechargeGold(data string) error {
	var rdata NotifyRechargeData
	err := json.Unmarshal([]byte(data), &rdata)
	if err != nil {
		logger.Info("json decode HandleRechargeGold data failed:%v", err, " for:%v", data)
		return err
	}

	logger.Info("###HandleRechargeGold###rdata:", rdata)

	var goldAfter int64 = 0
	_, goldAfter, err = db.OperateRequesterGold(rdata.PlayerId, rdata.Amount, db.Add)
	if err == nil {
		player, er := pmgr.GetPlayerFromMap(rdata.PlayerId)
		if er == nil && player != nil {
			//通知客户的转账成功
			var noti pb.NoticeNotifyUserGoldNum
			noti.Uid = uint32(rdata.PlayerId)
			noti.GoldNum = int64(goldAfter)
			common.SendNoti(player, uint32(0), uint32(rdata.PlayerId), pb.MSGID_MsgID_NotifyUserGoldNum_Notice, &noti)
		}
	}

	return err
}

type AllianceIncomeTransferData struct {
	UID uint32 `json:"uid"`
}

func HandleAllianceIncomeTransfer(data string) {
	var goldAfter int64 = 0
	var rdata AllianceIncomeTransferData
	err := json.Unmarshal([]byte(data), &rdata)
	if err != nil {
		logger.Info("json decode AllianceIncomeTransfer data failed:%v", err, " for:%v", data)
		return
	}

	logger.Info("###HandleAllianceIncomeTransfer###rdata:", rdata)
	//取出来
	db.AlliIncome_locker.Lock()
	for {
		if err = db.CheckAndLoadAlliIncome(uint32(rdata.UID)); err != nil {
			break
		}
		acuidIncome, _ := db.GetAlliIncome(int(rdata.UID))
		if acuidIncome == nil {
			acuidIncome = new(common.AlliCreaterIncomeInfo)
		}

		amount := int64(acuidIncome.Total)
		_, goldAfter, err = db.OperateRequesterGold(rdata.UID, amount, db.Add)
		if err == nil {
			acuidIncome.Fee = 0
			acuidIncome.Insurance = 0
			acuidIncome.Jackpot = 0
			acuidIncome.Total -= amount

			db.UpdateAlliIncome(int(rdata.UID), acuidIncome)
			if err = db.SyncAlliIncomeToDB(int(rdata.UID)); err != nil {
				break
			}
			if err = db.RecordAlliIncomeTransfer(rdata.UID, amount); err != nil {
				break
			}

			player, err := pmgr.GetPlayerFromMap(rdata.UID)
			if err == nil {
				common.SendGoldNumNotify(player, 0, uint32(rdata.UID), int64(goldAfter), int64(amount))
				logger.Info("HandleAllianceIncomeTransfer SendGoldNumNotify uid:%v", rdata.UID)
			} else {
				logger.Notic("Player not found uid:%v", rdata.UID)
			}
		} else {
			logger.Notic("HandleAllianceIncomeTransfer Add gold failed uid:%v,err:%v", rdata.UID, err)
			break
		}
		break
	}
	db.AlliIncome_locker.Unlock()
}
