package main

import (
	"math/rand"
	"time"

	"mongo.games.com/goserver/core"
	"mongo.games.com/goserver/core/logger"
	"mongo.games.com/goserver/core/module"
	"mongo.games.com/goserver/core/transact"
	"mongo.games.com/goserver/srvlib"

	"mongo.games.com/game/common"
	"mongo.games.com/game/proto"
	hall_proto "mongo.games.com/game/protocol/gamehall"
	"mongo.games.com/game/protocol/server"
	server_proto "mongo.games.com/game/protocol/server"
	"mongo.games.com/game/protocol/webapi"
	"mongo.games.com/game/srvdata"
)

var CoinSceneMgrSingleton = &CoinSceneMgr{
	playerChanging: make(map[int32]int32),
	//按平台管理
	scenesOfPlatform: make(map[string]map[int32]*CoinScenePool),
	platformOfScene:  make(map[int32]string),
	//按组管理
	scenesOfGroup: make(map[int32]map[int32]*CoinScenePool),
	groupOfScene:  make(map[int32]int32),
}

type CreateRoomCache struct {
	gameFreeId   int32
	platformName string
}

type CoinSceneMgr struct {
	playerChanging map[int32]int32 // snid:gamefreeid 换桌中的玩家

	//按平台管理
	scenesOfPlatform map[string]map[int32]*CoinScenePool // platform:gamefreeid
	platformOfScene  map[int32]string                    // sceneid:platform; 创建房间后记录房间所在平台

	//按组管理
	scenesOfGroup map[int32]map[int32]*CoinScenePool // groupid:gamefreeid
	groupOfScene  map[int32]int32                    // sceneid:groupid;

	//延迟创建房间列表
	delayCache []CreateRoomCache // 待预创建房间
}

// GetCoinScenePool 获取一个场景池
// plt 平台id
// id 场次id
func (csm *CoinSceneMgr) GetCoinScenePool(plt string, id int32) *CoinScenePool {
	gf := PlatformMgrSingleton.GetGameFree(plt, id)
	if gf == nil {
		return nil
	}
	groupId := gf.GetGroupId()
	if groupId != 0 {
		if _, ok := csm.scenesOfGroup[groupId]; ok {
			if csp, ok := csm.scenesOfGroup[groupId][id]; ok {
				return csp
			}
		}
	} else {
		if ss, ok := csm.scenesOfPlatform[plt]; ok {
			if csp, ok := ss[id]; ok && csp != nil {
				return csp
			}
		}
	}

	var dbGameFree *server_proto.DB_GameFree
	if groupId != 0 {
		conf := PlatformGameGroupMgrSington.GetGameGroup(groupId)
		if conf != nil {
			dbGameFree = conf.GetDbGameFree()
		}
	}
	if dbGameFree == nil {
		dbGameFree = gf.GetDbGameFree()
	}
	if dbGameFree == nil {
		return nil
	}

	// 创建了一个新的
	// 应该是走不到这里，因为模块启动时所有场次都创建了房间池
	return NewCoinScenePool(plt, groupId, dbGameFree)
}

func (csm *CoinSceneMgr) findCoinScenePool(platform string, id int32) (pools map[int32]*CoinScenePool, groupID int32,
	dbGameFree *server.DB_GameFree) {
	gf := PlatformMgrSingleton.GetGameFree(platform, id)
	if gf == nil {
		return nil, 0, nil
	}
	groupId := gf.GetGroupId()

	var ss map[int32]*CoinScenePool
	var ok bool
	if groupId != 0 {
		pgg := PlatformGameGroupMgrSington.GetGameGroup(groupId)
		if pgg != nil {
			ss, ok = csm.scenesOfGroup[groupId]
			if !ok {
				ss = make(map[int32]*CoinScenePool)
				csm.scenesOfGroup[groupId] = ss
			}
			return ss, groupId, pgg.GetDbGameFree()
		}
	}

	if ss == nil {
		ss, ok = csm.scenesOfPlatform[platform]
		if !ok {
			ss = make(map[int32]*CoinScenePool)
			csm.scenesOfPlatform[platform] = ss
		}
		return ss, 0, gf.GetDbGameFree()
	}

	return nil, 0, nil
}

// PlayerEnter 玩家进入房间池
func (csm *CoinSceneMgr) PlayerEnter(p *Player, id int32, roomId int32, exclude []int32, ischangeroom bool) hall_proto.OpResultCode {
	logger.Logger.Tracef("(csm *CoinSceneMgr) PlayerEnter snid:%v id:%v roomid:%v exclude:%v", p.SnId, id, roomId, exclude)
	if p.isDelete { //删档用户不让进游戏
		return hall_proto.OpResultCode_OPRC_RoomHadClosed
	}

	//多平台支持
	platform := p.GetPlatform()
	if platform == nil {
		return hall_proto.OpResultCode_OPRC_RoomHadClosed
	}

	// 玩家已经在房间里了
	if p.scene != nil {
		logger.Logger.Warnf("(csm *CoinSceneMgr) PlayerEnter snid:%v find in gameId:%v gamefreeid:%v", p.SnId, p.scene.gameId, id)
		return hall_proto.OpResultCode_OPRC_Error
	}

	pools, groupID, free := csm.findCoinScenePool(platform.IdStr, id)
	if pools == nil {
		return hall_proto.OpResultCode_OPRC_RoomHadClosed
	}

	csp, ok := pools[id]
	if !ok || csp == nil {
		csp = NewCoinScenePool(platform.IdStr, groupID, free)
		if csp == nil {
			logger.Logger.Warnf("(csm *CoinSceneMgr) PlayerEnter snid:%v find in id:%v exclude:%v NewCoinScenePool failed", p.SnId, id, exclude)
			return hall_proto.OpResultCode_OPRC_Error
		}
		pools[id] = csp
	}

	ret := csp.PlayerEnter(p, roomId, exclude, ischangeroom)

	logger.Logger.Warnf("(csm *CoinSceneMgr) PlayerEnter snid:%v find in id:%v exclude:%v return false", p.SnId, id, exclude)
	return ret
}

// AudienceEnter 观众进入房间
func (csm *CoinSceneMgr) AudienceEnter(p *Player, id int32, roomId int32, exclude []int32, ischangeroom bool) hall_proto.OpResultCode {
	//多平台支持
	platform := p.GetPlatform()
	if platform == nil {
		return hall_proto.OpResultCode_OPRC_RoomHadClosed
	}

	pools, _, _ := csm.findCoinScenePool(platform.IdStr, id)
	if pools == nil {
		return hall_proto.OpResultCode_OPRC_RoomHadClosed
	}

	if len(pools) == 0 {
		return hall_proto.OpResultCode_OPRC_NoFindDownTiceRoom
	}

	if csp, ok := pools[id]; ok && csp != nil {
		ret := csp.AudienceEnter(p, roomId, exclude, ischangeroom)
		logger.Logger.Warnf("(csm *CoinSceneMgr) AudienceEnter snid:%v find in id:%v exclude:%v return false", p.SnId, id, exclude)
		return ret
	}
	logger.Logger.Warnf("(csm *CoinSceneMgr) AudienceEnter snid:%v find in id:%v exclude:%v csp.AudienceEnter return false", p.SnId, id, exclude)
	return hall_proto.OpResultCode_OPRC_Error
}

func (csm *CoinSceneMgr) playerLeave(p *Player, reason int) bool {
	if p == nil || p.scene == nil {
		return true
	}

	s := p.scene
	if s.groupId != 0 {
		if ss, ok := csm.scenesOfGroup[s.groupId]; ok && ss != nil {
			if csp, ok := ss[s.dbGameFree.GetId()]; ok && csp != nil {
				if !csp.PlayerLeave(p, reason) {
					csp.AudienceLeave(p, reason)
				}
			}
			return true
		}
	}

	// 玩家身上平台
	if platform := p.GetPlatform(); platform != nil {
		if ss, ok := csm.scenesOfPlatform[platform.IdStr]; ok && ss != nil {
			if csp, ok := ss[s.dbGameFree.GetId()]; ok && csp != nil {
				if !csp.PlayerLeave(p, reason) {
					csp.AudienceLeave(p, reason)
				}
			}
			return true
		}
	}

	// 房间所在平台
	if s.limitPlatform != nil {
		if ss, ok := csm.scenesOfPlatform[s.limitPlatform.IdStr]; ok && ss != nil {
			if csp, ok := ss[s.dbGameFree.GetId()]; ok && csp != nil {
				if !csp.PlayerLeave(p, reason) {
					csp.AudienceLeave(p, reason)
				}
			}
			return true
		}
	}

	return true
}

// PlayerLeave 玩家离开
func (csm *CoinSceneMgr) PlayerLeave(p *Player, reason int) bool {
	logger.Logger.Tracef("玩家离开: snid %v, reason %v isAudience %v", p.SnId, reason)
	return csm.playerLeave(p, reason)
}

// OnDestroyScene 解散房间
// sceneId 房间id
func (csm *CoinSceneMgr) OnDestroyScene(sceneId int) {
	if platformName, ok := csm.platformOfScene[int32(sceneId)]; ok {
		if ss, ok := csm.scenesOfPlatform[platformName]; ok {
			for _, csp := range ss {
				csp.OnDestroyScene(sceneId)
			}
		}
		delete(csm.platformOfScene, int32(sceneId))
	}

	if groupId, ok := csm.groupOfScene[int32(sceneId)]; ok {
		if ss, ok := csm.scenesOfGroup[groupId]; ok {
			for _, csp := range ss {
				csp.OnDestroyScene(sceneId)
			}
		}
		delete(csm.groupOfScene, int32(sceneId))
	}
}

// GetPlatformBySceneId 获取房间所在平台
func (csm *CoinSceneMgr) GetPlatformBySceneId(sceneId int) string {
	if platformName, ok := csm.platformOfScene[int32(sceneId)]; ok {
		return platformName
	}
	s := SceneMgrSingleton.GetScene(sceneId)
	if s != nil && s.limitPlatform != nil {
		return s.limitPlatform.IdStr
	}
	return DefaultPlatform
}

// GetPlayerNums 获取场次人数
func (csm *CoinSceneMgr) GetPlayerNums(p *Player, gameId, gameMode int32) []int32 {
	//多平台支持
	platform := p.GetPlatform()
	var nums [10]int32
	wantNum := [10]int32{80, 50, 30, 20, 10, 10, 10, 10, 10, 10}
	for i := 0; i < 10; i++ {
		if wantNum[i]/2 > 0 {
			nums[i] = rand.Int31n(wantNum[i]/2) + wantNum[i]
		}
	}
	if platform == nil {
		return nums[:]
	}
	ids, _ := srvdata.DataMgr.GetGameFreeIds(gameId, gameMode)
	for _, id := range ids {
		gps := PlatformMgrSingleton.GetGameFree(platform.IdStr, id)
		if gps != nil {
			if gps.GroupId != 0 {
				if ss, exist := csm.scenesOfGroup[gps.GroupId]; exist {
					if csp, exist := ss[id]; exist {
						sceneType := csp.GetSceneType() - 1
						if sceneType >= 0 && sceneType < len(nums) {
							nums[sceneType] += csp.GetPlayerNum() + csp.GetFakePlayerNum()
						}
					}
				}
			} else {
				if ss, ok := csm.scenesOfPlatform[platform.IdStr]; ok {
					if csp, exist := ss[id]; exist {
						sceneType := csp.GetSceneType() - 1
						if sceneType >= 0 && sceneType < len(nums) {
							nums[sceneType] += csp.GetPlayerNum() + csp.GetFakePlayerNum()
						}
					}
				}
			}
		}
	}

	if len(ids) <= 10 {
		return nums[:len(ids)]
	}
	return nums[:]
}

// InCoinScene 是否在场次中
func (csm *CoinSceneMgr) InCoinScene(p *Player) bool {
	if p == nil {
		logger.Logger.Tracef("(csm *CoinSceneMgr) InCoinScene p == nil snid:%v ", p.SnId)
		return false
	}

	if p.scene == nil {
		return false
	}

	if p.scene.csp == nil {
		return false
	}
	return true
}

// PlayerTryLeave 通知游戏服务玩家要离开房间
func (csm *CoinSceneMgr) PlayerTryLeave(p *Player, isAudience bool) hall_proto.OpResultCode {
	if !csm.InCoinScene(p) {
		logger.Logger.Tracef("(csm *CoinSceneMgr) PlayerTryLeave !csm.InCoinScene(p) snid:%v ", p.SnId)
		return hall_proto.OpResultCode_OPRC_Sucess
	}

	// 通知gamesrv
	op := common.CoinSceneOp_Leave
	if isAudience {
		op = common.CoinSceneOp_AudienceLeave
	}
	pack := &hall_proto.CSCoinSceneOp{
		Id:     proto.Int32(p.scene.csp.id),
		OpType: proto.Int32(op),
	}
	proto.SetDefaults(pack)
	common.TransmitToServer(p.sid, int(hall_proto.CoinSceneGamePacketID_PACKET_CS_COINSCENE_OP), pack, p.scene.gameSess.Session)
	logger.Logger.Tracef("(csm *CoinSceneMgr) PlayerTryLeave snid:%v id:%v", p.SnId, pack.GetId())
	return hall_proto.OpResultCode_OPRC_OpYield
}

func (csm *CoinSceneMgr) PlayerInChanging(p *Player) bool {
	_, exist := csm.playerChanging[p.SnId]
	return exist
}

func (csm *CoinSceneMgr) ClearPlayerChanging(p *Player) {
	delete(csm.playerChanging, p.SnId)
}

func (csm *CoinSceneMgr) PlayerTryChange(p *Player, id int32, exclude []int32, isAudience bool) hall_proto.OpResultCode {
	if csm.InCoinScene(p) {
		return csm.StartChangeCoinSceneTransact(p, id, exclude, isAudience)
	}

	if isAudience {
		return csm.AudienceEnter(p, id, 0, exclude, true)
	}
	return csm.PlayerEnter(p, id, 0, exclude, true)
}

func (csm *CoinSceneMgr) StartChangeCoinSceneTransact(p *Player, id int32, exclude []int32, isAudience bool) hall_proto.OpResultCode {
	if p == nil || p.scene == nil {
		logger.Logger.Warnf("(csm *CoinSceneMgr) StartChangeCoinSceneTransact p == nil || p.scene == nil snid:%v id:%v", p.SnId, id)
		return hall_proto.OpResultCode_OPRC_Error
	}

	tNow := time.Now()
	if !p.lastChangeScene.IsZero() && tNow.Sub(p.lastChangeScene) < time.Second {
		logger.Logger.Warnf("(csm *CoinSceneMgr) StartChangeCoinSceneTransact !p.lastChangeScene.IsZero() && tNow.Sub(p.lastChangeScene) < time.Second snid:%v id:%v", p.SnId, id)
		return hall_proto.OpResultCode_OPRC_ChangeRoomTooOften
	}

	tnp := &transact.TransNodeParam{
		Tt:     common.TransType_CoinSceneChange,
		Ot:     transact.TransOwnerType(common.GetSelfSrvType()),
		Oid:    common.GetSelfSrvId(),
		AreaID: common.GetSelfAreaId(),
	}
	ctx := &CoinSceneChangeCtx{
		id:         id,
		isClub:     false,
		snid:       p.SnId,
		sceneId:    int32(p.scene.sceneId),
		exclude:    exclude,
		isAudience: isAudience,
	}
	tNode := transact.DTCModule.StartTrans(tnp, ctx, CoinSceneChangeTimeOut)
	if tNode != nil {
		tNode.Go(core.CoreObject())
		csm.playerChanging[p.SnId] = id
		p.lastChangeScene = tNow
		return hall_proto.OpResultCode_OPRC_Sucess
	}
	logger.Logger.Warnf("(csm *CoinSceneMgr) StartChangeCoinSceneTransact tNode == nil snid:%v id:%v", p.SnId, id)
	return hall_proto.OpResultCode_OPRC_Error
}

// ListRooms 给客户端发送场次房间列表
// id 场次id
func (csm *CoinSceneMgr) ListRooms(p *Player, id int32) bool {
	//多平台支持
	platform := p.GetPlatform()
	if platform == nil {
		return false
	}

	pools, groupID, free := csm.findCoinScenePool(platform.IdStr, id)
	if pools == nil {
		return false
	}

	if csp, ok := pools[id]; ok && csp != nil {
		return csp.ListRoom(p)
	}
	csp := NewCoinScenePool(platform.IdStr, groupID, free)
	if csp == nil {
		return false
	}
	pools[id] = csp
	return csp.ListRoom(p)
}

// CreateRoomByCache 创建预创建房间
// 每2秒创建一次
func (csm *CoinSceneMgr) CreateRoomByCache() {
	cnt := len(csm.delayCache)
	if cnt > 0 {
		data := csm.delayCache[cnt-1]
		csm.delayCache = csm.delayCache[:cnt-1]
		pdd := PlatformMgrSingleton.GetGameFree(data.platformName, data.gameFreeId)
		//对战场和捕鱼场 预创建
		if pdd != nil && pdd.DbGameFree != nil {
			var ss map[int32]*CoinScenePool
			var ok bool
			//分组模式
			if pdd.GroupId != 0 {
				pgg := PlatformGameGroupMgrSington.GetGameGroup(pdd.GroupId)
				if pgg != nil {
					ss, ok = csm.scenesOfGroup[pdd.GroupId]
					if !ok {
						ss = make(map[int32]*CoinScenePool)
						csm.scenesOfGroup[pdd.GroupId] = ss
					}
				}
			}
			//独立模式
			if ss == nil {
				ss, ok = csm.scenesOfPlatform[data.platformName]
				if !ok {
					ss = make(map[int32]*CoinScenePool)
					csm.scenesOfPlatform[data.platformName] = ss
				}
			}
			if ss == nil {
				return
			}
			if csp, ok := ss[pdd.DbGameFree.Id]; ok && csp != nil {
				csp.PreCreateRoom()
				return
			}
			csp := NewCoinScenePool(data.platformName, 0, pdd.DbGameFree)
			if csp != nil {
				ss[pdd.DbGameFree.Id] = csp
				csp.PreCreateRoom()
				return
			}
		}
	}
}

func (csm *CoinSceneMgr) ModuleName() string {
	return "CoinSceneMgr"
}

func (csm *CoinSceneMgr) Init() {
	// 场次池预创建
	for _, platform := range PlatformMgrSingleton.GetPlatforms() {
		if platform.Isolated || platform.IdStr == "" {
			arr := srvdata.PBDB_GameFreeMgr.Datas.GetArr()
			for _, dbGame := range arr {
				gps := PlatformMgrSingleton.GetGameFree(platform.IdStr, dbGame.GetId())
				if gps != nil {
					// dbGameFree
					dbGameFree := gps.DbGameFree
					if gps.GroupId != 0 {
						pgg := PlatformGameGroupMgrSington.GetGameGroup(gps.GroupId)
						if pgg != nil {
							dbGameFree = pgg.DbGameFree
						}
					}
					// CoinScenePool
					csp := NewCoinScenePool(platform.IdStr, gps.GroupId, dbGameFree)
					if csp != nil {
						if gps.GroupId != 0 {
							if ss, exist := csm.scenesOfGroup[gps.GroupId]; exist {
								ss[dbGame.GetId()] = csp
							} else {
								ss = make(map[int32]*CoinScenePool)
								ss[dbGame.GetId()] = csp
								csm.scenesOfGroup[gps.GroupId] = ss
							}
						} else {
							if ss, exist := csm.scenesOfPlatform[platform.IdStr]; exist {
								ss[dbGame.GetId()] = csp
							} else {
								ss = make(map[int32]*CoinScenePool)
								ss[dbGame.GetId()] = csp
								csm.scenesOfPlatform[platform.IdStr] = ss
							}
						}
					}
				}
			}
		}
	}
}

func (csm *CoinSceneMgr) Update() {
	// 预创建房间
	csm.CreateRoomByCache()
}

func (csm *CoinSceneMgr) Shutdown() {
	module.UnregisteModule(csm)
}

//=====================PlatformObserver======================

func (this *CoinSceneMgr) OnPlatformCreate(p *Platform) {
	if p.IdStr == DefaultPlatform {
		return
	}
	//获取配置
	gps := PlatformMgrSingleton.GetGameFrees(p.IdStr)
	for _, v := range gps {
		if v.Status && v.DbGameFree.GetCreateRoomNum() > 0 {
			this.delayCache = append(this.delayCache, CreateRoomCache{gameFreeId: v.DbGameFree.Id, platformName: p.IdStr})
		}
	}
}

func (this *CoinSceneMgr) OnPlatformDestroy(p *Platform) {
	if p == nil {
		return
	}
	if csps, ok := this.scenesOfPlatform[p.IdStr]; ok {
		for _, csp := range csps {
			pack := &server_proto.WGGraceDestroyScene{}
			for _, scene := range csp.scenes {
				pack.Ids = append(pack.Ids, int32(scene.sceneId))
			}
			// 房间中记录的有游服连接，广播的方式也可以
			srvlib.ServerSessionMgrSington.Broadcast(int(server_proto.SSPacketID_PACKET_WG_GRACE_DESTROYSCENE), pack, common.GetSelfAreaId(), srvlib.GameServerType)
		}
	}
}

func (this *CoinSceneMgr) OnPlatformChangeIsolated(p *Platform, isolated bool) {
	if !isolated {
		this.OnPlatformDestroy(p)
	}
}

func (this *CoinSceneMgr) OnPlatformChangeDisabled(p *Platform, disabled bool) {
	if disabled {
		this.OnPlatformDestroy(p)
	}
}

func (this *CoinSceneMgr) OnPlatformGameFreeUpdate(p *Platform, oldCfg, newCfg *webapi.GameFree) {
	if p == nil || newCfg == nil {
		return
	}

	var ss map[int32]*CoinScenePool
	var ok bool
	if oldCfg.GroupId != newCfg.GroupId || oldCfg.GroupId != 0 {
		ss, ok = this.scenesOfGroup[oldCfg.GroupId]
	} else {
		ss, ok = this.scenesOfPlatform[p.IdStr]
	}
	if !ok || ss == nil {
		return
	}

	if cps, ok := ss[newCfg.DbGameFree.Id]; ok {
		cps.dbGameFree = newCfg.DbGameFree
		pack := &server_proto.WGGraceDestroyScene{}
		for _, scene := range cps.scenes {
			pack.Ids = append(pack.Ids, int32(scene.sceneId))
		}
		srvlib.ServerSessionMgrSington.Broadcast(int(server_proto.SSPacketID_PACKET_WG_GRACE_DESTROYSCENE),
			pack, common.GetSelfAreaId(), srvlib.GameServerType)

		//预创建房间配置更新
		if newCfg.DbGameFree.GetCreateRoomNum() != 0 && p.IdStr != DefaultPlatform && newCfg.Status {
			logger.Logger.Tracef(">>>预创建房间 platform:%v %v_%v gamefreeid:%v CreateRoomNum:%v", p.Name,
				newCfg.DbGameFree.GetName(), newCfg.DbGameFree.GetTitle(), newCfg.DbGameFree.GetId(), newCfg.DbGameFree.GetCreateRoomNum())
			this.delayCache = append(this.delayCache, CreateRoomCache{gameFreeId: newCfg.DbGameFree.GetId(), platformName: p.IdStr})
		}
	}
}

func (this *CoinSceneMgr) OnPlatformDestroyByGameFreeId(p *Platform, gameFreeId int32) {
	if p == nil {
		return
	}
	if csps, ok := this.scenesOfPlatform[p.IdStr]; ok {
		for _, csp := range csps {
			pack := &server_proto.WGGraceDestroyScene{}
			for _, scene := range csp.scenes {
				if scene.dbGameFree.Id == gameFreeId {
					pack.Ids = append(pack.Ids, int32(scene.sceneId))
				}
			}
			srvlib.ServerSessionMgrSington.Broadcast(int(server_proto.SSPacketID_PACKET_WG_GRACE_DESTROYSCENE), pack, common.GetSelfAreaId(), srvlib.GameServerType)
		}
	}
}

//=========================PlatformGameGroupObserver==============================

func (this *CoinSceneMgr) OnGameGroupUpdate(oldCfg, newCfg *webapi.GameConfigGroup) {
	if newCfg == nil {
		return
	}
	if scenes, exist := this.scenesOfGroup[newCfg.Id]; exist {
		if cps, ok := scenes[newCfg.DbGameFree.Id]; ok {
			needDestroy := false
			if cps.dbGameFree.GetBot() != newCfg.DbGameFree.GetBot() ||
				cps.dbGameFree.GetBaseScore() != newCfg.DbGameFree.GetBaseScore() ||
				cps.dbGameFree.GetLimitCoin() != newCfg.DbGameFree.GetLimitCoin() ||
				cps.dbGameFree.GetMaxCoinLimit() != newCfg.DbGameFree.GetMaxCoinLimit() ||
				cps.dbGameFree.GetTaxRate() != newCfg.DbGameFree.GetTaxRate() ||
				!common.SliceInt64Equal(cps.dbGameFree.GetOtherIntParams(), newCfg.DbGameFree.GetOtherIntParams()) ||
				!common.SliceInt64Equal(cps.dbGameFree.GetRobotTakeCoin(), newCfg.DbGameFree.GetRobotTakeCoin()) ||
				!common.SliceInt64Equal(cps.dbGameFree.GetRobotLimitCoin(), newCfg.DbGameFree.GetRobotLimitCoin()) {
				needDestroy = true
			}
			//TODO 预创建房间配置更新,unsupport group model
			cps.dbGameFree = newCfg.DbGameFree
			if needDestroy {
				pack := &server_proto.WGGraceDestroyScene{}
				for _, scene := range cps.scenes {
					pack.Ids = append(pack.Ids, int32(scene.sceneId))
				}
				srvlib.ServerSessionMgrSington.Broadcast(int(server_proto.SSPacketID_PACKET_WG_GRACE_DESTROYSCENE), pack, common.GetSelfAreaId(), srvlib.GameServerType)
			}
		}
	}
}

//=========================GameSessionListener======================================

func (csm *CoinSceneMgr) OnGameSessionRegiste(gs *GameSession) {
	wildGs := len(gs.gameIds) == 0 || common.InSliceInt32(gs.gameIds, 0) // 是否所有游戏都支持
	for _, platform := range PlatformMgrSingleton.GetPlatforms() {
		if platform.IdStr == DefaultPlatform {
			continue
		}
		//获取配置
		gps := PlatformMgrSingleton.GetGameFrees(platform.IdStr)
		for _, v := range gps {
			if v.Status && v.DbGameFree.GetCreateRoomNum() > 0 && (wildGs || common.InSliceInt32(gs.gameIds, v.DbGameFree.GetGameId())) {
				csm.delayCache = append(csm.delayCache, CreateRoomCache{gameFreeId: v.DbGameFree.Id, platformName: platform.IdStr})
			}
		}
	}
}

func (this *CoinSceneMgr) OnGameSessionUnregiste(gs *GameSession) {
	//todo 游戏服务断开，是否解散房间？
}

func init() {
	module.RegisteModule(CoinSceneMgrSingleton, time.Second*2, 0)

	PlatformMgrSingleton.RegisterObserver(CoinSceneMgrSingleton)
	PlatformGameGroupMgrSington.RegisteObserver(CoinSceneMgrSingleton)
	RegisteGameSessionListener(CoinSceneMgrSingleton)
}
