package main

import (
	"strconv"
	"strings"
	"time"

	"mongo.games.com/goserver/core/basic"
	"mongo.games.com/goserver/core/logger"
	"mongo.games.com/goserver/core/netlib"
	"mongo.games.com/goserver/core/task"

	"mongo.games.com/game/common"
	"mongo.games.com/game/model"
	"mongo.games.com/game/proto"
	gamehall_proto "mongo.games.com/game/protocol/gamehall"
	login_proto "mongo.games.com/game/protocol/login"
	player_proto "mongo.games.com/game/protocol/player"
	server_proto "mongo.games.com/game/protocol/server"
	"mongo.games.com/game/srvdata"
)

func init() {
	// 销毁房间
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_DESTROYSCENE), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWDestroyScene{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_DESTROYSCENE), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		logger.Logger.Trace("receive GWDestroyScene:", pack)
		if msg, ok := pack.(*server_proto.GWDestroyScene); ok {
			SceneMgrSingleton.DestroyScene(int(msg.GetSceneId()), msg.GetIsCompleted())
		}
		return nil
	}))

	// 离开房间
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_PLAYERLEAVE), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWPlayerLeave{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_PLAYERLEAVE), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		if msg, ok := pack.(*server_proto.GWPlayerLeave); ok {
			logger.Logger.Trace("receive GWPlayerLeave:", msg.GetPlayerId())
			scene := SceneMgrSingleton.GetScene(int(msg.GetRoomId()))
			if scene != nil {
				p := PlayerMgrSington.GetPlayerBySnId(msg.GetPlayerId())
				if p != nil {
					data := msg.GetPlayerData()
					if len(data) != 0 {
						logger.Logger.Trace("GWPlayerLeave p.UnmarshalData(data)")
						p.UnmarshalData(data, scene)
					}
					switch {
					case scene.IsCoinScene():
						if !CoinSceneMgrSingleton.PlayerLeave(p, int(msg.GetReason())) {
							logger.Logger.Warnf("GWPlayerLeave snid:%v sceneid:%v gameid:%v modeid:%v [coinscene]",
								p.SnId, scene.sceneId, scene.gameId, scene.gameMode)
						}
					case scene.IsMatchScene():
						if !MatchSceneMgrSingleton.PlayerLeave(p, int(msg.GetReason())) {
							logger.Logger.Warnf("GWPlayerLeave snid:%v sceneid:%v gameid:%v modeid:%v matchid:%v [matchscene]",
								p.SnId, scene.sceneId, scene.gameId, scene.gameMode, scene.matchId)
						} else {
							//结算积分
							if !p.IsRob {
								TournamentMgr.UpdateMatchInfo(p, msg.MatchId, int32(msg.GetReturnCoin()), int32(msg.GetCurIsWin()), msg.GetMatchRobotGrades())
							} else {
								p.matchCtx = nil
							}
						}
					case scene.IsHundredScene():
						if !HundredSceneMgrSington.PlayerLeave(p, int(msg.GetReason())) {
							logger.Logger.Warnf("GWPlayerLeave snid:%v sceneid:%v gameid:%v modeid:%v [hundredcene]",
								p.SnId, scene.sceneId, scene.gameId, scene.gameMode)
						}
					default:
						if scene.ClubId > 0 {
							//if club, ok := clubManager.clubList[scene.ClubId]; ok {
							//	if cp, ok1 := club.memberList[p.SnId]; ok1 {
							//		cp.GameCount += msg.GetGameTimes()
							//		cp.DayCoin += msg.GetTotalConvertibleFlow() - p.TotalConvertibleFlow
							//	}
							//}
							//if !ClubSceneMgrSington.PlayerLeave(p, int(msg.GetReason())) {
							//	logger.Logger.Warnf("Club leave room msg snid:%v sceneid:%v gameid:%v modeid:%v [coinscene]",
							//		p.SnId, scene.sceneId, scene.gameId, scene.mode)
							//	scene.PlayerLeave(p, int(msg.GetReason()))
							//}
						} else {
							scene.PlayerLeave(p, int(msg.GetReason()))
						}
					}

					if p.scene != nil {
						logger.Logger.Warnf("after GWPlayerLeave found snid:%v sceneid:%v gameid:%v modeid:%v", p.SnId, p.scene.sceneId, p.scene.gameId, p.scene.gameMode)
					}

					// 同步排位积分
					if scene.IsRankMatch() {
						if p.IsRob {
							RankMgrSingleton.UpdateRobotSeason(p.Platform, p.SnId, scene.dbGameFree.GetRankType(),
								msg.GetRankScore()[scene.dbGameFree.GetRankType()], p.Name, p.Sex, p.HeadUrl, p.Coin, p.PlayerData.GetRoleId())
						} else {
							RankMgrSingleton.UpdatePlayerSeason(p.SnId, msg.GetRankScore())
						}
					}

					//比赛场不处理下面的内容
					if !scene.IsMatchScene() {
						// 破产检测
						sdata := srvdata.PBDB_GameSubsidyMgr.GetData(GameSubsidyid)
						if sdata != nil {
							if !p.IsRob && p.takeCoin > msg.GetReturnCoin() && p.takeCoin >= int64(sdata.LimitNum) && msg.GetReturnCoin() < int64(sdata.LimitNum) {
								CostCoin := p.takeCoin - msg.GetReturnCoin()

								logger.Logger.Infof("NewBankruptLogEx: snid:%v GetReturnCoin:%v coin:%v CostCoin:%v", p.SnId, msg.GetReturnCoin(), p.takeCoin, CostCoin)
								log := model.NewBankruptLogEx(p.SnId, scene.dbGameFree.GetId(), p.CreateTime.Unix(), CostCoin, p.Platform, scene.gameId)
								if log != nil {
									LogChannelSingleton.WriteLog(log)
								}
							}
						}
						// 破产检测

						oldCoin := p.Coin

						//带回金币
						if p.Coin != msg.GetReturnCoin() {
							p.Coin = msg.GetReturnCoin()
							if p.Coin < 0 {
								p.Coin = 0
							}

							p.dirty = true
						}

						logger.Logger.Infof("SSPacketID_PACKET_GW_PLAYERLEAVE: snid:%v oldcoin:%v coin:%v", p.SnId, oldCoin, p.Coin)
						p.diffData.Coin = -1                 //强制更新金币
						p.diffData.TotalConvertibleFlow = -1 //强制更新流水
						p.SendDiffData()                     //只是把差异发给前端

						gameCoinTs := msg.GetGameCoinTs()
						if !p.IsRob && !scene.IsTestScene() {
							// 同步背包数据
							diffItems := []*Item{}
							dbItemArr := srvdata.PBDB_GameItemMgr.Datas.Arr
							if dbItemArr != nil {
								items := msg.GetItems()
								if items != nil {
									for _, dbItem := range dbItemArr {
										if itemNum, exist := items[dbItem.Id]; exist {
											oldItem := BagMgrSingleton.GetItem(p.SnId, dbItem.Id)
											diffNum := int64(itemNum)
											if oldItem != nil {
												diffNum = int64(itemNum) - oldItem.ItemNum
											}
											if diffNum != 0 {
												item := &Item{
													ItemId:  dbItem.Id,
													ItemNum: diffNum,
												}
												diffItems = append(diffItems, item)
											}
										}
									}
								}
							}
							if diffItems != nil && len(diffItems) != 0 {
								BagMgrSingleton.AddJybBagInfo(p, diffItems, 0, 0, "", "")
							}

							//对账点同步
							if p.GameCoinTs < gameCoinTs {
								p.GameCoinTs = gameCoinTs
								p.dirty = true
							}

							//破产统计
							//if int(msg.GetReason()) == common.PlayerLeaveReason_Bekickout {
							//	if len(scene.paramsEx) > 0 {
							//		gameIdEx := scene.paramsEx[0]
							//		gps := PlatformMgrSingleton.GetGameFree(scene.limitPlatform.IdStr, scene.paramsEx[0])
							//		if gps != nil {
							//			lowLimit := gps.DbGameFree.GetLowerThanKick()
							//			if lowLimit != 0 && p.Coin+p.SafeBoxCoin < int64(lowLimit) {
							//				p.ReportBankRuptcy(int32(scene.gameId), int32(scene.gameMode), gameIdEx)
							//			}
							//		}
							//	}
							//}
						}
					}
				} else {
					logger.Logger.Tracef("GWPlayerLeave LocalRobotIdMgrSington %v", msg.GetPlayerId())
					//LocalRobotIdMgrSington.FreeId(msg.GetPlayerId())
				}
			}
		}
		return nil
	}))

	// 观众离开房间
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_AUDIENCELEAVE), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWPlayerLeave{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_AUDIENCELEAVE), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		logger.Logger.Trace("receive PACKET_GW_AUDIENCELEAVE GWPlayerLeave:", pack)
		if msg, ok := pack.(*server_proto.GWPlayerLeave); ok {
			scene := SceneMgrSingleton.GetScene(int(msg.GetRoomId()))
			if scene != nil {
				p := PlayerMgrSington.GetPlayerBySnId(msg.GetPlayerId())
				if p != nil {
					gameCoinTs := msg.GetGameCoinTs()
					//带回的金币
					if p.Coin != msg.GetReturnCoin() && !scene.IsMatchScene() {
						p.Coin = msg.GetReturnCoin()
						if p.Coin < 0 {
							p.Coin = 0
						}
						p.dirty = true
					}

					//对账点同步
					if p.GameCoinTs != gameCoinTs {
						p.GameCoinTs = gameCoinTs
						p.dirty = true
					}

					CoinSceneMgrSingleton.PlayerLeave(p, int(msg.GetReason()))

					//变化金币
					p.dirty = true
					p.diffData.Coin = -1                 //强制更新金币
					p.diffData.TotalConvertibleFlow = -1 //强制更新流水
					p.SendDiffData()
				} else {
					//LocalRobotIdMgrSington.FreeId(msg.GetPlayerId())
				}
			}
		}
		return nil
	}))

	// 房间游戏开始
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_SCENESTART), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWSceneStart{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_SCENESTART), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		logger.Logger.Trace("receive SSPacketID_PACKET_GW_SCENESTART GWSceneStart:", pack)
		if msg, ok := pack.(*server_proto.GWSceneStart); ok {
			scene := SceneMgrSingleton.GetScene(int(msg.GetRoomId()))
			if scene != nil {
				scene.starting = msg.GetStart()
				scene.currRound = msg.GetCurrRound()
				scene.totalRound = msg.GetMaxRound()
				scene.lastTime = time.Now()
				if scene.starting {
					if scene.currRound == 1 {
						scene.startTime = time.Now()
						//p := PlayerMgrSington.GetPlayer(s.Sid)
					}
				}
				if scene.starting {
					logger.Logger.Trace("游戏开始------", scene.gameId, scene.sceneId, scene.replayCode, scene.currRound)
				} else {
					logger.Logger.Trace("游戏结束------", scene.gameId, scene.sceneId, scene.replayCode, scene.currRound)
				}
				PlatformMgrSingleton.OnChangeSceneState(scene, scene.starting)
			}
		}
		return nil
	}))

	// 房间游戏状态
	// 捕鱼
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_SCENESTATE), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWSceneState{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_SCENESTATE), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		logger.Logger.Trace("receive SSPacketID_PACKET_GW_SCENESTATE GWSceneState:", pack)
		if msg, ok := pack.(*server_proto.GWSceneState); ok {
			scene := SceneMgrSingleton.GetScene(int(msg.GetRoomId()))
			if scene != nil {
				scene.state = msg.GetCurrState()
				scene.fishing = msg.GetFishing()
				PlatformMgrSingleton.OnChangeSceneState(scene, scene.starting)
			}
		}
		return nil
	}))

	// 用户状态同步 flag
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_PLAYERSTATE), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWPlayerFlag{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_PLAYERSTATE), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		logger.Logger.Trace("receive GWPlayerFlag:", pack)
		if msg, ok := pack.(*server_proto.GWPlayerFlag); ok {
			player := PlayerMgrSington.GetPlayerBySnId(msg.GetSnId())
			if player != nil {
				player.flag = msg.GetFlag()
			}
		}
		return nil
	}))

	// 房间服务器状态切换
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GB_STATE_SWITCH), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.ServerStateSwitch{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GB_STATE_SWITCH), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		logger.Logger.Trace("receive SSPacketID_PACKET_GB_STATE_SWITCH ServerStateSwitch:", pack)
		if sr, ok := pack.(*server_proto.ServerStateSwitch); ok {
			srvid := int(sr.GetSrvId())
			gameSess := GameSessMgrSington.GetGameSess(srvid)
			if gameSess != nil {
				if gameSess.state == common.GAME_SESS_STATE_ON {
					gameSess.SwitchState(common.GAME_SESS_STATE_OFF)
				} else {
					gameSess.SwitchState(common.GAME_SESS_STATE_ON)
				}
			} else {
				gateSess := GameSessMgrSington.GetGateSess(srvid)
				if gateSess != nil {
					if gateSess.state == common.GAME_SESS_STATE_ON {
						gateSess.SwitchState(common.GAME_SESS_STATE_OFF)
					} else {
						gateSess.SwitchState(common.GAME_SESS_STATE_ON)
					}
				}
			}
		}
		return nil
	}))

	// 游戏服务器的系统广播
	// 捕鱼
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_NEWNOTICE), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWNewNotice{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_NEWNOTICE), netlib.HandlerWrapper(func(s *netlib.Session,
		packetid int, pack interface{}) error {
		logger.Logger.Trace("receive GWNewNotice:", pack)
		if msg, ok := pack.(*server_proto.GWNewNotice); ok {
			//立即发送改为定期发送，控制下广播包的频度
			HorseRaceLampMgrSington.PushGameHorseRaceLamp(msg.GetCh(), msg.GetPlatform(), msg.GetContent(), int32(msg.GetMsgtype()), msg.GetIsrob(), msg.GetPriority())
		}
		return nil
	}))

	// 同步每局游戏那些玩家一起玩的
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_SCENEPLAYERLOG), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWScenePlayerLog{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_SCENEPLAYERLOG), netlib.HandlerWrapper(func(s *netlib.Session,
		packetid int, pack interface{}) error {
		logger.Logger.Trace("receive GWScenePlayerLog:", pack)
		if msg, ok := pack.(*server_proto.GWScenePlayerLog); ok {
			sceneLimitMgr.ReceiveData(msg.GetGameId(), msg.GetSnids())
		}
		return nil
	}))

	// 强制离开房间
	// 返回房间失败
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_PLAYERFORCELEAVE), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWPlayerForceLeave{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_PLAYERFORCELEAVE), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		if msg, ok := pack.(*server_proto.GWPlayerForceLeave); ok {
			logger.Logger.Warn("receive GWPlayerForceLeave:", msg)
			scene := SceneMgrSingleton.GetScene(int(msg.GetRoomId()))
			if scene != nil {
				p := PlayerMgrSington.GetPlayerBySnId(msg.GetPlayerId())
				if p != nil {
					ctx := scene.GetPlayerGameCtx(p.SnId)
					if ctx != nil && p.scene == scene && scene.HasPlayer(p) && ctx.enterTs == msg.GetEnterTs() {
						switch {
						case scene.IsCoinScene():
							if !CoinSceneMgrSingleton.PlayerLeave(p, int(msg.GetReason())) {
								logger.Logger.Warnf("GWPlayerForceLeave snid:%v sceneid:%v gameid:%v modeid:%v [coinscene]", p.SnId, scene.sceneId, scene.gameId, scene.gameMode)
							}
						case scene.IsHundredScene():
							if !HundredSceneMgrSington.PlayerLeave(p, int(msg.GetReason())) {
								logger.Logger.Warnf("GWPlayerForceLeave snid:%v sceneid:%v gameid:%v modeid:%v [hundredcene]", p.SnId, scene.sceneId, scene.gameId, scene.gameMode)
							}
						case scene.IsMatchScene():
							if !MatchSceneMgrSingleton.PlayerLeave(p, int(msg.GetReason())) {
								logger.Logger.Warnf("GWPlayerLeave snid:%v sceneid:%v gameid:%v modeid:%v matchid:%v [matchscene]",
									p.SnId, scene.sceneId, scene.gameId, scene.gameMode, scene.matchId)
							}
						default:
							scene.PlayerLeave(p, int(msg.GetReason()))
						}

						if p.scene != nil {
							logger.Logger.Warnf("after GWPlayerForceLeave found snid:%v sceneid:%v gameid:%v modeid:%v", p.SnId, p.scene.sceneId, p.scene.gameId, p.scene.gameMode)
							p.scene.PlayerLeave(p, int(msg.GetReason()))
						}
					} else {
						logger.Logger.Warnf("GWPlayerForceLeave snid:%v sceneid:%v gameid:%v modeid:%v fount not p.scene==scene && scene.HasPlayer(p)", p.SnId, scene.sceneId, scene.gameId, scene.gameMode)
					}
				}
			} else {
				logger.Logger.Warnf("GWPlayerForceLeave snid:%v scene:%v had closed", msg.GetPlayerId(), msg.GetRoomId())
			}
		}
		return nil
	}))

	//一局游戏一结算
	//可处理以下业务
	//1.同步玩家游戏场内的实时金币
	//2.触发相关任务:统计有效下注金币数,赢取金币数,牌局次数等
	//3.黑名单处理
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_PLAYERDATA), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWPlayerData{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_PLAYERDATA), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		logger.Logger.Trace("receive GWPlayerBet:", pack)
		if msg, ok := pack.(*server_proto.GWPlayerData); ok {
			scene := SceneMgrSingleton.GetScene(int(msg.GetSceneId()))
			if scene == nil {
				return nil
			}
			for _, playerBet := range msg.GetDatas() {
				player := PlayerMgrSington.GetPlayerBySnId(playerBet.GetSnId())
				if player != nil && !player.IsRob {
					// task 赢次数
					if playerBet.GetGain() > 0 || playerBet.WinState == 1 {
						TaskSubjectSingleton.Touch(common.TaskTypeWinTimes, &TaskData{
							SnId:       player.SnId,
							GameID:     scene.gameId,
							GameFreeID: scene.dbGameFree.GetId(),
							Num:        1,
						})
					}
					// task 游戏局数
					TaskSubjectSingleton.Touch(common.TaskTypePlayTimes, &TaskData{
						SnId:       player.SnId,
						GameID:     scene.gameId,
						GameFreeID: scene.dbGameFree.GetId(),
						Num:        1,
					})
					// task 排位赛次数
					if scene.IsRankMatch() {
						TaskSubjectSingleton.Touch(common.TaskTypeRankMatchTimes, &TaskData{
							SnId:       player.SnId,
							GameID:     scene.gameId,
							GameFreeID: scene.dbGameFree.GetId(),
							Num:        1,
						})
					}
					if !scene.IsMatchScene() { // 比赛没金币是积分
						n := playerBet.GetGain()
						if n < 0 {
							n = -n
						}
						//游戏中输赢金币
						TaskSubjectSingleton.Touch(common.TaskTypeWinOrLose, &TaskData{
							SnId:       player.SnId,
							GameID:     scene.gameId,
							GameFreeID: scene.dbGameFree.GetId(),
							Num:        n,
						})
						// 游戏中赢金币
						if playerBet.GetGain() > 0 || playerBet.WinState == 1 {
							TaskSubjectSingleton.Touch(common.TaskTypeWinCoin, &TaskData{
								SnId:       player.SnId,
								GameID:     scene.gameId,
								GameFreeID: scene.dbGameFree.GetId(),
								Num:        playerBet.GetGain(),
							})
						}
					}
					//tienlen 游戏场次
					if common.IsTienLen(scene.gameId) {
						TaskSubjectSingleton.Touch(common.TaskTypeTienlenCount, &TaskData{
							SnId:       player.SnId,
							GameID:     scene.gameId,
							GameFreeID: scene.dbGameFree.GetId(),
							Num:        1,
						})
						if playerBet.GetGain() > 0 || playerBet.WinState == 1 {
							TaskSubjectSingleton.Touch(common.TaskTypeTienlenWinTimes, &TaskData{
								SnId:       player.SnId,
								GameID:     scene.gameId,
								GameFreeID: scene.dbGameFree.GetId(),
								Num:        1,
							})
						}
					}

					if !scene.IsMatchScene() { // 比赛没金币是积分
						player.Coin = playerBet.GetCoin()
						player.GameCoinTs = playerBet.GetGameCoinTs()
						player.GameTax += playerBet.GetTax()
						player.dirty = true
						player.WBUpdate(playerBet.GetWBGain())
					}
				}
			}
		}
		return nil
	}))

	//推送游戏的状态
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_GAMESTATE), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWGameState{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_GAMESTATE), netlib.HandlerWrapper(func(s *netlib.Session,
		packetid int, pack interface{}) error {
		logger.Logger.Trace("receive SSPacketID_PACKET_GW_GAMESTATE GWGameState:", pack)
		if msg, ok := pack.(*server_proto.GWGameState); ok {
			scene := SceneMgrSingleton.GetScene(int(msg.GetSceneId()))
			if scene != nil {
				scene.State = msg.GetState()
				scene.StateSec = msg.GetSec()
				scene.BankerListNum = msg.GetBankerListNum()
				if scene.State == scene.sp.GetBetState() {
					scene.StateTs = msg.GetTs()
					leftTime := int64(scene.StateSec) - (time.Now().Unix() - scene.StateTs)
					if leftTime < 0 {
						leftTime = 0
					}
					pack := &gamehall_proto.SCGameState{}
					pack.List = append(pack.List, &gamehall_proto.GameState{
						GameFreeId: proto.Int32(scene.dbGameFree.GetId()),
						Ts:         proto.Int64(leftTime),
						Sec:        proto.Int32(scene.StateSec),
					})
					gameStateMgr.BrodcastGameState(int32(scene.gameId), scene.limitPlatform.IdStr,
						int(gamehall_proto.GameHallPacketID_PACKET_SC_GAMESTATE), pack)
				}
			}
		}
		return nil
	}))

	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_JACKPOTLIST), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWGameJackList{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_JACKPOTLIST), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		logger.Logger.Trace("receive SSPacketID_PACKET_GW_JACKPOTLIST GWGameJackList:", pack)
		if msg, ok := pack.(*server_proto.GWGameJackList); ok {
			FishJackListMgr.Insert(msg.GetCoin(), msg.GetSnId(), msg.GetRoomId(), msg.GetJackType(), msg.GetGameId(),
				msg.GetPlatform(), msg.GetChannel(), msg.GetName())
		}
		return nil
	}))
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_JACKPOTCOIN), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWGameJackCoin{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_JACKPOTCOIN), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		logger.Logger.Trace("receive SSPacketID_PACKET_GW_JACKPOTCOIN GWGameJackCoin:", pack)
		if msg, ok := pack.(*server_proto.GWGameJackCoin); ok {
			for i, pl := range msg.Platform {
				FishJackpotCoinMgr.Jackpot[pl] = msg.Coin[i]
			}
		}
		return nil
	}))

	//强制换桌
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_GW_CHANGESCENEEVENT), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.GWChangeSceneEvent{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_GW_CHANGESCENEEVENT), netlib.HandlerWrapper(func(s *netlib.Session, packetid int, pack interface{}) error {
		logger.Logger.Trace("receive SSPacketID_PACKET_GW_CHANGESCENEEVENT GWChangeSceneEvent:", pack)
		if msg, ok := pack.(*server_proto.GWChangeSceneEvent); ok {
			scene := SceneMgrSingleton.GetScene(int(msg.GetSceneId()))
			if scene != nil {
				scene.PlayerTryChange()
			}
		}
		return nil
	}))

	//玩家中转消息
	netlib.RegisterFactory(int(server_proto.SSPacketID_PACKET_SS_REDIRECTTOPLAYER), netlib.PacketFactoryWrapper(func() interface{} {
		return &server_proto.SSRedirectToPlayer{}
	}))
	netlib.RegisterHandler(int(server_proto.SSPacketID_PACKET_SS_REDIRECTTOPLAYER), netlib.HandlerWrapper(func(s *netlib.Session,
		packetid int, pack interface{}) error {
		logger.Logger.Trace("SSRedirectToPlayer Process recv ", pack)
		if msg, ok := pack.(*server_proto.SSRedirectToPlayer); ok {
			p := PlayerMgrSington.GetPlayerBySnId(msg.GetSnId())
			if p == nil {
				return nil
			}
			p.SendToClient(int(msg.GetPacketId()), msg.GetData())
		}
		return nil
	}))
}

// 机器人服务器向worldsrv发送
type CSPMCmdPacketFactory struct {
}
type CSPMCmdHandler struct {
}

func (this *CSPMCmdPacketFactory) CreatePacket() interface{} {
	pack := &player_proto.CSPMCmd{}
	return pack
}

func (this *CSPMCmdHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSPMCmdHandler Process recv ", data)
	if msg, ok := data.(*player_proto.CSPMCmd); ok {
		p := PlayerMgrSington.GetPlayer(sid)
		if p == nil {
			logger.Logger.Trace("CSPMCmdHandler p == nil")
			return nil
		}

		if !p.IsRob && p.GMLevel < 3 {
			logger.Logger.Trace("CSPMCmdHandler p.Channel != common.Channel_Rob && p.GMLevel < 3")
			return nil
		}

		cmd := msg.GetCmd()
		logger.Logger.Infof("CSPMCmdHandler %v %v", p.SnId, cmd)
		args := strings.Split(cmd, common.PMCmd_SplitToken)
		argsCnt := len(args)
		if argsCnt != 0 {
			switch args[0] {
			case common.PMCmd_AddCoin:
				if argsCnt > 1 {
					coin, err := strconv.ParseInt(args[1], 10, 64) //strconv.Atoi(args[1])
					if err != nil {
						logger.Logger.Warnf("CSPMCmdHandler %v parse %v err:%v", p.SnId, cmd, err)
						return nil
					}
					if coin != 0 {
						p.CoinPayTotal += int64(coin)
						p.dirty = true
						p.AddCoin(coin, 0, common.GainWay_ByPMCmd, p.GetName(), cmd)
						p.ReportSystemGiveEvent(int32(coin), common.GainWay_ByPMCmd, true)
						p.SendDiffData()
					}
				}
			case common.PMCmd_Privilege:
				if p.GMLevel >= 3 {
					if p.Flags&model.PLAYER_FLAGS_PRIVILEGE == 0 {
						p.Flags |= model.PLAYER_FLAGS_PRIVILEGE
					} else {
						p.Flags &= ^model.PLAYER_FLAGS_PRIVILEGE
					}
				}
			}
		}
	}
	return nil
}

type CSRobotChgDataPacketFactory struct {
}
type CSRobotChgDataHandler struct {
}

func (this *CSRobotChgDataPacketFactory) CreatePacket() interface{} {
	pack := &player_proto.CSRobotChgData{}
	return pack
}

func (this *CSRobotChgDataHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSRobotChgDataHandler Process recv ", data)
	if _, ok := data.(*player_proto.CSRobotChgData); ok {
		p := PlayerMgrSington.GetPlayer(sid)
		if p == nil {
			logger.Logger.Trace("CSRobotChgDataHandler p == nil")
			return nil
		}

		if !p.IsRob {
			logger.Logger.Trace("CSRobotChgDataHandler !p.IsRob")
			return nil
		}
	}
	return nil
}

type CSAccountInvalidPacketFactory struct {
}
type CSAccountInvalidHandler struct {
}

func (this *CSAccountInvalidPacketFactory) CreatePacket() interface{} {
	pack := &login_proto.CSAccountInvalid{}
	return pack
}

func (this *CSAccountInvalidHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSAccountInvalidHandler Process recv ", data)
	if _, ok := data.(*login_proto.CSAccountInvalid); ok {
		p := PlayerMgrSington.GetPlayer(sid)
		if p != nil && p.IsRobot() {
			snid := p.SnId
			acc := p.AccountId
			task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
				err := model.RemoveAccount(p.Platform, acc)
				if err != nil {
					logger.Logger.Error("Remove robot account data error:", err)
				}
				err = model.RemovePlayerByAcc(p.Platform, acc)
				if err != nil {
					logger.Logger.Error("Remove robot player data error:", err)
				}
				logger.Logger.Trace("CSAccountInvalid message remove :", acc)
				return nil
			}), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) {
				PlayerMgrSington.DelPlayer(snid)
				LoginStateMgrSington.DelAccountByAccid(acc)
				return
			}), "RemoveAccount").StartByFixExecutor("RemoveAccount")
		}
	}
	return nil
}

func init() {
	common.RegisterHandler(int(player_proto.PlayerPacketID_PACKET_CS_PMCMD), &CSPMCmdHandler{})
	netlib.RegisterFactory(int(player_proto.PlayerPacketID_PACKET_CS_PMCMD), &CSPMCmdPacketFactory{})

	common.RegisterHandler(int(player_proto.PlayerPacketID_PACKET_CS_ROBOTCHGDATA), &CSRobotChgDataHandler{})
	netlib.RegisterFactory(int(player_proto.PlayerPacketID_PACKET_CS_ROBOTCHGDATA), &CSRobotChgDataPacketFactory{})

	common.RegisterHandler(int(login_proto.LoginPacketID_PACKET_CS_ACCOUNTINVALID), &CSAccountInvalidHandler{})
	netlib.RegisterFactory(int(login_proto.LoginPacketID_PACKET_CS_ACCOUNTINVALID), &CSAccountInvalidPacketFactory{})
}
