package main

import (
	"mongo.games.com/game/common"
	"mongo.games.com/game/model"
	"mongo.games.com/game/proto"
	"mongo.games.com/game/protocol/tournament"
	"mongo.games.com/game/srvdata"
	"mongo.games.com/goserver/core/basic"
	"mongo.games.com/goserver/core/logger"
	"mongo.games.com/goserver/core/netlib"
	"mongo.games.com/goserver/core/task"
	"sort"
	"strconv"
	"time"
)

// 比赛场信息
type CSTMInfoPacketFactory struct {
}
type CSTMInfoHandler struct {
}

func (this *CSTMInfoPacketFactory) CreatePacket() interface{} {
	pack := &tournament.CSTMInfo{}
	return pack
}

func (this *CSTMInfoHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSTMInfoHandler Process recv ", data)
	if _, ok := data.(*tournament.CSTMInfo); ok {
		p := PlayerMgrSington.GetPlayer(sid)
		if p == nil {
			logger.Logger.Warnf("CSTMInfo p == nil.")
			return nil
		}
		pack := TournamentMgr.GetSCTMInfosPack(p.Platform, p.AppChannel)
		proto.SetDefaults(pack)
		logger.Logger.Trace("SCTMInfos++++++++++++:", pack)
		p.SendToClient(int(tournament.TOURNAMENTID_PACKET_TM_SCTMInfos), pack)
	}
	return nil
}

// 排行榜
type CSTMRankListPacketFactory struct {
}
type CSTMRankListHandler struct {
}

func (this *CSTMRankListPacketFactory) CreatePacket() interface{} {
	pack := &tournament.CSTMRankList{}
	return pack
}

func (this *CSTMRankListHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSTMRankListHandler Process recv ", data)
	if msg, ok := data.(*tournament.CSTMRankList); ok {
		p := PlayerMgrSington.GetPlayer(sid)
		if p == nil {
			logger.Logger.Warnf("CSTMRankList p == nil.")
			return nil
		}
		pack := &tournament.SCTMRankList{
			TMId:      msg.TMId,
			TimeRange: "9.1-9.30",
			TMRank: []*tournament.TMRank{
				{RankId: 1, RankName: "rankNo.1", WinnerNum: 5},
				{RankId: 2, RankName: "rankNo.2", WinnerNum: 4},
				{RankId: 3, RankName: "rankNo.3", WinnerNum: 2}},
		}
		proto.SetDefaults(pack)
		logger.Logger.Trace("CSTMRankList:", pack)
		p.SendToClient(int(tournament.TOURNAMENTID_PACKET_TM_SCTMRankList), pack)
	}
	return nil
}

// 报名
type CSSignRacePacketFactory struct {
}
type CSSignRaceHandler struct {
}

func (this *CSSignRacePacketFactory) CreatePacket() interface{} {
	pack := &tournament.CSSignRace{}
	return pack
}

func (this *CSSignRaceHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSSignRaceHandler Process recv ", data)
	if msg, ok := data.(*tournament.CSSignRace); ok {
		p := PlayerMgrSington.GetPlayer(sid)
		if p == nil {
			logger.Logger.Warnf("CSSignRace p == nil.")
			return nil
		}
		if p.scene != nil {
			logger.Logger.Warnf("CSSignRace p.scene != nil.")
			return nil
		}
		if p.IsRob {
			logger.Logger.Warnf("CSSignRace p.IsRob.")
			return nil
		}
		platform := p.Platform
		tmid := msg.TMId
		pack := &tournament.SCSignRace{}
		switch msg.GetOpCode() {
		case 0:
			ok, code := TournamentMgr.SignUp(tmid, p)
			if !ok {
				logger.Logger.Infof("player(%v) match(%v) SignUp is fail.", p.SnId, tmid)
				pack.RetCode = code //0成功 1重复报名 2比赛没有开启 3道具不足 4不在报名时间段 5金币不足 6钻石不足
			}

			if code == int32(tournament.SignRaceCode_OPRC_Close) ||
				code == int32(tournament.SignRaceCode_OPRC_Time) {
				TournamentMgr.CancelSignUpAll(platform, tmid)
			}

			waitStart := TournamentMgr.playerWaitStart[p.SnId]
			if pack.RetCode == 0 && waitStart != 0 {
				pack.WaitStartTime = waitStart
			}

			proto.SetDefaults(pack)
			logger.Logger.Trace("SCSignRace:", pack)
			signSucc := p.SendToClient(int(tournament.TOURNAMENTID_PACKET_TM_SCSignRace), pack)
			// 检查是否可以开始比赛（关闭机器人时，比赛开赛）
			if msg.GetOpCode() == 0 && pack.RetCode == 0 && signSucc && !TournamentMgr.IsUseRobot(platform, tmid) {
				if TournamentMgr.CanStart(platform, tmid) {
					TournamentMgr.Start(platform, tmid)
				}
			}

		default:
			if TournamentMgr.IsMatching(p.SnId) {
				logger.Logger.Infof("player(%v) IsMatching.", p.SnId)
			} else {
				//取消报名
				TournamentMgr.CancelSignUp(platform, tmid, p.SnId)
			}
			return nil
		}
	}
	return nil
}

// 赛季信息
type CSTMSeasonInfoPacketFactory struct {
}
type CSTMSeasonInfoHandler struct {
}

func (this *CSTMSeasonInfoPacketFactory) CreatePacket() interface{} {
	pack := &tournament.CSTMSeasonInfo{}
	return pack
}

func (this *CSTMSeasonInfoHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSTMSeasonInfoHandler Process recv ", data)
	if _, ok := data.(*tournament.CSTMSeasonInfo); ok {
		p := PlayerMgrSington.GetPlayer(sid)
		if p == nil {
			logger.Logger.Warnf("CSTMSeasonInfoHandler p == nil.")
			return nil
		}
		if p.Platform == DefaultPlatform {
			logger.Logger.Warnf("CSTMSeasonInfoHandler Platform == Default_Platform.")
			return nil
		}
		msid := MatchSeasonMgrSington.GetMatchSeasonId(p.Platform)
		if msid == nil {
			logger.Logger.Warnf("CSTMSeasonInfoHandler msid == nil.")
			return nil
		}
		send := func(ms *MatchSeason) {
			pack := &tournament.SCTMSeasonInfo{
				Id:              msid.SeasonId,
				SeasonTimeStamp: []int64{msid.StartStamp, msid.EndStamp},
				Lv:              ms.Lv,
				LastLv:          ms.LastLv,
				IsAward:         ms.IsAward,
			}
			proto.SetDefaults(pack)
			logger.Logger.Trace("CSTMSeasonInfoHandler:", pack)
			p.SendToClient(int(tournament.TOURNAMENTID_PACKET_TM_SCTMSeasonInfo), pack)
		}
		snid := p.SnId
		ms := MatchSeasonMgrSington.GetMatchSeason(snid)
		if ms == nil {
			task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
				ret, err := model.QueryMatchSeasonBySnid(p.Platform, snid)
				if err != nil {
					return nil
				}
				return ret
			}), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) {
				var ret *model.MatchSeason
				dirty := false
				if data == nil || data.(*model.MatchSeason) == nil { //新数据
					player := PlayerMgrSington.GetPlayerBySnId(snid)
					if player != nil {
						ret = model.NewMatchSeason(player.Platform, snid, player.Name, msid.SeasonId, 1)
						dirty = true
					} else {
						logger.Logger.Trace("CSTMSeasonInfoHandler error: player==nil ", snid)
					}
				} else {
					ret = data.(*model.MatchSeason)
					if ret.SeasonId < msid.SeasonId { //不同赛季段位继承
						num := msid.SeasonId - ret.SeasonId
						finalLv := ret.Lv
						for i := 0; i < int(num); i++ { //继承几次
							if i == int(num)-1 { //上个赛季
								ret.LastLv = finalLv
							}
							finalLv = MatchSeasonMgrSington.MatchSeasonInherit(finalLv)
						}
						ret.Lv = finalLv
						ret.SeasonId = msid.SeasonId
						ret.IsAward = false
						ret.UpdateTs = time.Now().Unix()
						dirty = true
					}
				}
				ms = MatchSeasonMgrSington.exchangeModel2Cache(ret)
				ms.dirty = dirty
				MatchSeasonMgrSington.SetMatchSeason(ms)
				send(ms)
			})).StartByFixExecutor("SnId:" + strconv.Itoa(int(snid)))
		} else {
			if ms.SeasonId < msid.SeasonId { //不同赛季段位继承
				num := msid.SeasonId - ms.SeasonId
				finalLv := ms.Lv
				for i := 0; i < int(num); i++ { //继承几次
					if i == int(num)-1 { //上个赛季
						ms.LastLv = finalLv
					}
					finalLv = MatchSeasonMgrSington.MatchSeasonInherit(finalLv)
				}
				ms.Lv = finalLv
				ms.SeasonId = msid.SeasonId
				ms.IsAward = false
				ms.UpdateTs = time.Now().Unix()
				ms.dirty = true
				MatchSeasonMgrSington.SetMatchSeason(ms)
			}
			send(ms)
		}
	}
	return nil
}

// 赛季排行榜
type CSTMSeasonRankPacketFactory struct {
}
type CSTMSeasonRankHandler struct {
}

func (this *CSTMSeasonRankPacketFactory) CreatePacket() interface{} {
	pack := &tournament.CSTMSeasonRank{}
	return pack
}

func (this *CSTMSeasonRankHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSTMSeasonRankHandler Process recv ", data)
	if _, ok := data.(*tournament.CSTMSeasonRank); ok {
		p := PlayerMgrSington.GetPlayer(sid)
		if p == nil {
			logger.Logger.Warnf("CSTMSeasonRankHandler p == nil.")
			return nil
		}
		platform := p.Platform
		if platform == DefaultPlatform {
			logger.Logger.Warnf("CSTMSeasonRankHandler Platform == Default_Platform.")
			return nil
		}
		pack := &tournament.SCTMSeasonRank{}
		tmpMsrs := []*MatchSeasonRank{}
		msr := MatchSeasonRankMgrSington.GetMatchSeasonRank(platform)
		if msr != nil {
			for _, ms := range msr {
				sr := &MatchSeasonRank{
					SnId: ms.SnId,
					Name: ms.Name,
					Lv:   ms.Lv,
				}
				tmpMsrs = append(tmpMsrs, sr)
			}
		}
		robotmsr := MatchSeasonRankMgrSington.GetRobotMatchSeasonRank(platform)
		if robotmsr != nil {
			for _, ms := range robotmsr {
				sr := &MatchSeasonRank{
					SnId: ms.SnId,
					Name: ms.Name,
					Lv:   ms.Lv,
				}
				tmpMsrs = append(tmpMsrs, sr)
			}
		}
		if tmpMsrs != nil && len(tmpMsrs) > 0 {
			sort.Slice(tmpMsrs, func(i, j int) bool {
				return tmpMsrs[i].Lv > tmpMsrs[j].Lv
			})
			if len(tmpMsrs) > model.GameParamData.MatchSeasonRankMaxNum {
				tmpMsrs = append(tmpMsrs[:model.GameParamData.MatchSeasonRankMaxNum])
			}
			for i := 0; i < len(tmpMsrs); i++ {
				ms := tmpMsrs[i]
				sr := &tournament.SeasonRank{
					Snid: ms.SnId,
					Name: ms.Name,
					Lv:   ms.Lv,
					Rank: int32(i) + 1,
				}
				pack.ReasonRanks = append(pack.ReasonRanks, sr)
			}
		}
		proto.SetDefaults(pack)
		logger.Logger.Trace("CSTMSeasonRankHandler:", pack)
		p.SendToClient(int(tournament.TOURNAMENTID_PACKET_TM_SCTMSeasonRank), pack)
	}
	return nil
}

// 领取赛季奖励
type CSTMSeasonAwardPacketFactory struct {
}
type CSTMSeasonAwardHandler struct {
}

func (this *CSTMSeasonAwardPacketFactory) CreatePacket() interface{} {
	pack := &tournament.CSTMSeasonAward{}
	return pack
}

func (this *CSTMSeasonAwardHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSTMSeasonAwardHandler Process recv ", data)
	if msg, ok := data.(*tournament.CSTMSeasonAward); ok {
		p := PlayerMgrSington.GetPlayer(sid)
		if p == nil {
			logger.Logger.Warnf("CSTMSeasonAwardHandler p == nil.")
			return nil
		}
		if p.Platform == DefaultPlatform {
			logger.Logger.Warnf("CSTMSeasonInfoHandler Platform == Default_Platform.")
			return nil
		}
		lv := msg.GetLv()
		logger.Logger.Trace("CSTMSeasonAwardHandler lv: ", lv)
		pack := &tournament.SCTMSeasonAward{
			Lv:   lv,
			Code: 1,
		}
		ms := MatchSeasonMgrSington.GetMatchSeason(p.SnId)
		msi := MatchSeasonMgrSington.GetMatchSeasonId(p.Platform)
		if ms != nil && msi != nil {
			if !ms.IsAward && ms.LastLv == lv && msi.SeasonId > 1 { //领取上赛季奖励
				for _, v := range srvdata.PBDB_GamMatchLVMgr.Datas.GetArr() {
					if v.Star != nil && len(v.Star) > 1 {
						startStar := v.Star[0]
						endStar := v.Star[1]
						if lv >= startStar && lv <= endStar { //匹配段位
							pack.Code = 0
							MatchSeasonMgrSington.UpdateMatchSeasonAward(p.SnId)
							if v.Number1 > 0 {
								switch v.AwardType1 {
								case 1: //金币
									p.AddCoin(int64(v.Number1), 0, common.GainWay_MatchSeason, "system", "赛季奖励")
									LogChannelSingleton.WriteMQData(model.GenerateSystemFreeGive(p.SnId, p.Name, p.Platform, model.SystemFreeGive_GiveType_MatchSeason, model.SystemFreeGive_CoinType_Coin, int64(v.Number1)))
								case 2: //钻石
									p.AddDiamond(int64(v.Number1), 0, common.GainWay_MatchSeason, "system", "赛季奖励")
									LogChannelSingleton.WriteMQData(model.GenerateSystemFreeGive(p.SnId, p.Name, p.Platform, model.SystemFreeGive_GiveType_MatchSeason, model.SystemFreeGive_CoinType_Diamond, int64(v.Number1)))
								case 3: //道具
									item := &Item{
										ItemId:  v.AwardId1,
										ItemNum: int64(v.Number1),
									}
									BagMgrSingleton.AddJybBagInfo(p, []*Item{item}, 0, common.GainWay_MatchSeason, "system", "赛季奖励")
									itemData := srvdata.PBDB_GameItemMgr.GetData(item.ItemId)
									if itemData != nil {
										BagMgrSingleton.RecordItemLog(p.Platform, p.SnId, ItemObtain, item.ItemId, itemData.Name, item.ItemNum, "赛季奖励")
									}
								}
							}
							if v.Number2 > 0 {
								switch v.AwardType2 {
								case 1: //金币
									p.AddCoin(int64(v.Number2), 0, common.GainWay_MatchSeason, "system", "赛季奖励")
									LogChannelSingleton.WriteMQData(model.GenerateSystemFreeGive(p.SnId, p.Name, p.Platform, model.SystemFreeGive_GiveType_MatchSeason, model.SystemFreeGive_CoinType_Coin, int64(v.Number2)))
								case 2: //钻石
									p.AddDiamond(int64(v.Number2), 0, common.GainWay_MatchSeason, "system", "赛季奖励")
									LogChannelSingleton.WriteMQData(model.GenerateSystemFreeGive(p.SnId, p.Name, p.Platform, model.SystemFreeGive_GiveType_MatchSeason, model.SystemFreeGive_CoinType_Diamond, int64(v.Number2)))
								case 3: //道具
									item := &Item{
										ItemId:  v.AwardId2,
										ItemNum: int64(v.Number2),
									}
									BagMgrSingleton.AddJybBagInfo(p, []*Item{item}, 0, common.GainWay_MatchSeason, "system", "赛季奖励")
									itemData := srvdata.PBDB_GameItemMgr.GetData(item.ItemId)
									if itemData != nil {
										BagMgrSingleton.RecordItemLog(p.Platform, p.SnId, ItemObtain, item.ItemId, itemData.Name, item.ItemNum, "赛季奖励")
									}
								}
							}
							if v.Number3 > 0 {
								switch v.AwardType3 {
								case 1: //金币
									p.AddCoin(int64(v.Number3), 0, common.GainWay_MatchSeason, "system", "赛季奖励")
									LogChannelSingleton.WriteMQData(model.GenerateSystemFreeGive(p.SnId, p.Name, p.Platform, model.SystemFreeGive_GiveType_MatchSeason, model.SystemFreeGive_CoinType_Coin, int64(v.Number3)))
								case 2: //钻石
									p.AddDiamond(int64(v.Number3), 0, common.GainWay_MatchSeason, "system", "赛季奖励")
									LogChannelSingleton.WriteMQData(model.GenerateSystemFreeGive(p.SnId, p.Name, p.Platform, model.SystemFreeGive_GiveType_MatchSeason, model.SystemFreeGive_CoinType_Diamond, int64(v.Number3)))
								case 3: //道具
									item := &Item{
										ItemId:  v.AwardId3,
										ItemNum: int64(v.Number3),
									}
									BagMgrSingleton.AddJybBagInfo(p, []*Item{item}, 0, common.GainWay_MatchSeason, "system", "赛季奖励")
									itemData := srvdata.PBDB_GameItemMgr.GetData(item.ItemId)
									if itemData != nil {
										BagMgrSingleton.RecordItemLog(p.Platform, p.SnId, ItemObtain, item.ItemId, itemData.Name, item.ItemNum, "赛季奖励")
									}
								}
							}
							break
						}
					}
				}
			}
		}
		if pack.Code != 0 {
			logger.Logger.Trace("CSTMSeasonAwardHandler ms: ", ms)
			logger.Logger.Trace("CSTMSeasonAwardHandler msi: ", msi)
		}
		proto.SetDefaults(pack)
		logger.Logger.Trace("SCTMSeasonAward:", pack)
		p.SendToClient(int(tournament.TOURNAMENTID_PACKET_TM_SCTMSeasonAward), pack)
	}
	return nil
}

func init() {
	common.RegisterHandler(int(tournament.TOURNAMENTID_PACKET_TM_CSTMInfo), &CSTMInfoHandler{})
	netlib.RegisterFactory(int(tournament.TOURNAMENTID_PACKET_TM_CSTMInfo), &CSTMInfoPacketFactory{})

	common.RegisterHandler(int(tournament.TOURNAMENTID_PACKET_TM_CSTMRankList), &CSTMRankListHandler{})
	netlib.RegisterFactory(int(tournament.TOURNAMENTID_PACKET_TM_CSTMRankList), &CSTMRankListPacketFactory{})

	// 比赛报名
	common.RegisterHandler(int(tournament.TOURNAMENTID_PACKET_TM_CSSignRace), &CSSignRaceHandler{})
	netlib.RegisterFactory(int(tournament.TOURNAMENTID_PACKET_TM_CSSignRace), &CSSignRacePacketFactory{})

	common.RegisterHandler(int(tournament.TOURNAMENTID_PACKET_TM_CSTMSeasonInfo), &CSTMSeasonInfoHandler{})
	netlib.RegisterFactory(int(tournament.TOURNAMENTID_PACKET_TM_CSTMSeasonInfo), &CSTMSeasonInfoPacketFactory{})

	common.RegisterHandler(int(tournament.TOURNAMENTID_PACKET_TM_CSTMSeasonRank), &CSTMSeasonRankHandler{})
	netlib.RegisterFactory(int(tournament.TOURNAMENTID_PACKET_TM_CSTMSeasonRank), &CSTMSeasonRankPacketFactory{})

	common.RegisterHandler(int(tournament.TOURNAMENTID_PACKET_TM_CSTMSeasonAward), &CSTMSeasonAwardHandler{})
	netlib.RegisterFactory(int(tournament.TOURNAMENTID_PACKET_TM_CSTMSeasonAward), &CSTMSeasonAwardPacketFactory{})
}
