package action

import (
	"time"

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

	"mongo.games.com/game/common"
	"mongo.games.com/game/gamesrv/base"
	"mongo.games.com/game/proto"
	"mongo.games.com/game/protocol/gamehall"
	"mongo.games.com/game/srvdata"
)

type CSDestroyRoomPacketFactory struct {
}
type CSDestroyRoomHandler struct {
}

func (this *CSDestroyRoomPacketFactory) CreatePacket() interface{} {
	pack := &gamehall.CSDestroyRoom{}
	return pack
}

func (this *CSDestroyRoomHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSDestroyRoomHandler Process recv ", data)
	p := base.PlayerMgrSington.GetPlayer(sid)
	if p == nil {
		logger.Logger.Warn("CSDestroyRoomHandler p == nil")
		return nil
	}
	scene := p.GetScene()
	if scene == nil {
		logger.Logger.Warn("CSDestroyRoomHandler p.GetScene() == nil")
		return nil
	}
	if !scene.HasPlayer(p) {
		return nil
	}
	if scene.Creator != p.SnId {
		logger.Logger.Warn("CSDestroyRoomHandler s.creator != p.AccountId")
		return nil
	}
	scene.Destroy(true)
	return nil
}

type CSLeaveRoomPacketFactory struct {
}
type CSLeaveRoomHandler struct {
}

func (this *CSLeaveRoomPacketFactory) CreatePacket() interface{} {
	pack := &gamehall.CSLeaveRoom{}
	return pack
}

func (this *CSLeaveRoomHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSLeaveRoomHandler Process recv ", data)
	if msg, ok := data.(*gamehall.CSLeaveRoom); ok {
		p := base.PlayerMgrSington.GetPlayer(sid)
		if p == nil {
			logger.Logger.Warn("CSLeaveRoomHandler p == nil")
			return nil
		}
		scene := p.GetScene()
		if scene == nil {
			logger.Logger.Warnf("CSLeaveRoomHandler[%v] p.GetScene() == nil", p.SnId)
			pack := &gamehall.SCLeaveRoom{
				OpRetCode: gamehall.OpResultCode_Game_OPRC_RoomNotExit,
				Mode:      msg.Mode,
			}
			proto.SetDefaults(pack)
			p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_LEAVEROOM), pack)
			return nil
		}
		if msg.GetMode() == 0 && !scene.CanChangeCoinScene(p) {
			logger.Logger.Warnf("CSLeaveRoomHandler[%v][%v] scene.gaming==true", scene.SceneId, p.SnId)
			pack := &gamehall.SCLeaveRoom{
				OpRetCode: gamehall.OpResultCode_Game_OPRC_YourAreGamingCannotLeave_Game,
				RoomId:    proto.Int(scene.SceneId),
			}
			proto.SetDefaults(pack)
			p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_LEAVEROOM), pack)
			return nil
		}
		if msg.GetMode() == 0 { // 0退出 1暂离
			if scene.HasAudience(p) {
				scene.AudienceLeave(p, common.PlayerLeaveReason_Normal)
			} else if scene.HasPlayer(p) {
				scene.PlayerLeave(p, common.PlayerLeaveReason_Normal, false)
			}
		} else {
			pack := &gamehall.SCLeaveRoom{
				Reason:    proto.Int(0),
				OpRetCode: gamehall.OpResultCode_Game_OPRC_Sucess_Game,
				Mode:      msg.Mode,
				RoomId:    proto.Int(scene.SceneId),
			}
			proto.SetDefaults(pack)
			p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_LEAVEROOM), pack)
			scene.PlayerDropLine(p.SnId)

			//标记上暂离状态
			p.ActiveLeave = true
			p.MarkFlag(base.PlayerState_Online)
			p.MarkFlag(base.PlayerState_Leave)
			p.SyncFlag()
		}
	}
	return nil
}

type CSAudienceLeaveRoomHandler struct {
}

func (this *CSAudienceLeaveRoomHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSAudienceLeaveRoomHandler Process recv ", data)
	p := base.PlayerMgrSington.GetPlayer(sid)
	if p == nil {
		logger.Logger.Warn("CSAudienceLeaveRoomHandler p == nil")
		return nil
	}
	scene := p.GetScene()
	if scene == nil {
		logger.Logger.Warn("CSAudienceLeaveRoomHandler p.GetScene() == nil")
		return nil
	}
	if !scene.HasAudience(p) {
		return nil
	}
	scene.AudienceLeave(p, common.PlayerLeaveReason_Normal)
	return nil
}

type CSForceStartPacketFactory struct {
}
type CSForceStartHandler struct {
}

func (this *CSForceStartPacketFactory) CreatePacket() interface{} {
	pack := &gamehall.CSForceStart{}
	return pack
}

func (this *CSForceStartHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSForceStartHandler Process recv ", data)
	p := base.PlayerMgrSington.GetPlayer(sid)
	if p == nil {
		logger.Logger.Warn("CSForceStartHandler p == nil")
		return nil
	}
	if p.GetScene() == nil {
		logger.Logger.Warn("CSForceStartHandler p.GetScene() == nil")
		return nil
	}
	if p.Pos != 0 /*p.GetScene().creator != p.SnId*/ { //第1个进房间的玩家
		logger.Logger.Warn("CSForceStartHandler p.GetScene().creator != p.SnId")
		return nil
	}
	if p.GetScene().Gaming {
		logger.Logger.Warn("CSForceStartHandler p.GetScene().gaming==true")
		return nil
	}
	if !p.GetScene().GetScenePolicy().IsCanForceStart(p.GetScene()) {
		logger.Logger.Warn("CSForceStartHandler !p.GetScene().sp.IsCanForceStart(p.GetScene())")
		return nil
	}
	//强制开始
	p.GetScene().GetScenePolicy().ForceStart(p.GetScene())

	p.GetScene().NotifySceneRoundStart(1)

	packClient := &gamehall.SCForceStart{}
	proto.SetDefaults(packClient)
	p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_FORCESTART), packClient)
	return nil
}

//type CSPlayerSwitchFlagPacketFactory struct {
//}
//type CSPlayerSwitchFlagHandler struct {
//}
//
//func (this *CSPlayerSwitchFlagPacketFactory) CreatePacket() interface{} {
//	pack := &gamehall.CSPlayerSwithFlag{}
//	return pack
//}
//
//func (this *CSPlayerSwitchFlagHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
//	logger.Logger.Trace("CSPlayerSwitchFlagHandler Process recv ", data)
//	if msg, ok := data.(*gamehall.CSPlayerSwithFlag); ok {
//		p := base.PlayerMgrSington.GetPlayer(sid)
//		if p == nil {
//			logger.Logger.Warn("CSPlayerSwitchFlagHandler p == nil")
//			return nil
//		}
//		flag := int(msg.GetFlag())
//		//flag = 1 << uint(flag)
//		//if msg.Mark != nil {
//		logger.Logger.Trace("CSPlayerSwitchFlagHandler Process recv SnId(%v) Mark is %v", p.SnId, msg.GetMark())
//		if msg.GetMark() == 0 { //0取消状态 1设置状态
//			oldFlag := p.GetFlag()
//			if p.IsMarkFlag(flag) {
//				p.UnmarkFlag(flag)
//			}
//			if flag == base.PlayerState_Leave {
//				if p.GetScene() != nil {
//					//重置下房间状态
//					p.GetScene().PlayerReturn(p, true)
//				}
//			}
//			if oldFlag != p.GetFlag() {
//				p.SyncFlag()
//			}
//		} else { //设置状态
//			if flag == base.PlayerState_Leave {
//				p.ActiveLeave = false //被动暂离
//				if p.GetScene() != nil {
//					//todo dev fish 字游戏暂时被删除了 所以这里先注释掉
//					//if p.GetScene().gameId == common.GameId_HFishing || p.GetScene().gameId == common.GameId_LFishing ||
//					//	p.GetScene().gameId == common.GameId_RFishing || p.GetScene().gameId == common.GameId_DFishing ||
//					//	p.GetScene().gameId == common.GameId_NFishing || p.GetScene().gameId == common.GameId_TFishing {
//					//	p.GetScene().sp.OnPlayerOp(p.GetScene(), p, FishingPlayerOpLeave, []int64{})
//					//}
//				}
//			}
//			if !p.IsMarkFlag(flag) {
//				p.MarkFlag(flag)
//				p.SyncFlag()
//			}
//		}
//		//}
//	}
//	return nil
//}

func CSRoomEvent(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Tracef("CSRoomEvent %v", data)
	msg, ok := data.(*gamehall.CSRoomEvent)
	if !ok {
		return nil
	}

	p := base.PlayerMgrSington.GetPlayer(sid)
	if p == nil {
		return nil
	}

	scene := p.GetScene()
	if scene == nil {
		return nil
	}

	if !scene.HasPlayer(p) {
		return nil
	}

	pack := &gamehall.SCRoomEvent{
		OpCode:  gamehall.OpResultCode_Game_OPRC_Sucess_Game,
		Tp:      msg.GetTp(),
		Pos:     int32(p.GetPos()),
		Content: msg.GetContent(),
		Param:   msg.GetParam(),
		Ts:      time.Now().Unix(),
	}

	switch msg.GetTp() {
	case 1: // 普通消息

	case 2: // 互动表情
		var totalCoin int64
		for _, v := range msg.GetParam() {
			item := srvdata.PBDB_GameItemMgr.GetData(v)
			switch item.GetType() {
			case common.ItemTypeInteract:
				totalCoin += item.GetNum()
			}
		}
		if p.GetCoin() >= totalCoin {
			for _, v := range msg.GetParam() {
				item := srvdata.PBDB_GameItemMgr.GetData(v)
				if item.GetNum() > 0 {
					p.AddCoin(-item.GetNum(), common.GainWay_Interact, base.SyncFlag_ToClient|base.SyncFlag_Broadcast, "system", "互动表情")
				}
			}
		} else {
			pack.OpCode = gamehall.OpResultCode_Game_OPRC_CoinNotEnough_Game
		}

	default:
		return nil
	}

	scene.Broadcast(int(gamehall.GameHallPacketID_PACKET_SCRoomEvent), pack, 0)
	logger.Logger.Tracef("SCRoomEvent %v", pack)
	return nil
}

func init() {
	// 房间创建者解散房间
	common.RegisterHandler(int(gamehall.GameHallPacketID_PACKET_CS_DESTROYROOM), &CSDestroyRoomHandler{})
	netlib.RegisterFactory(int(gamehall.GameHallPacketID_PACKET_CS_DESTROYROOM), &CSDestroyRoomPacketFactory{})

	// 离开或暂离房间
	common.RegisterHandler(int(gamehall.GameHallPacketID_PACKET_CS_LEAVEROOM), &CSLeaveRoomHandler{})
	netlib.RegisterFactory(int(gamehall.GameHallPacketID_PACKET_CS_LEAVEROOM), &CSLeaveRoomPacketFactory{})

	// 观众离开房间
	common.RegisterHandler(int(gamehall.GameHallPacketID_PACKET_CS_AUDIENCE_LEAVEROOM), &CSAudienceLeaveRoomHandler{})
	netlib.RegisterFactory(int(gamehall.GameHallPacketID_PACKET_CS_AUDIENCE_LEAVEROOM), &CSLeaveRoomPacketFactory{})

	// 第一个进房间的玩家强制开始游戏
	common.RegisterHandler(int(gamehall.GameHallPacketID_PACKET_CS_FORCESTART), &CSForceStartHandler{})
	netlib.RegisterFactory(int(gamehall.GameHallPacketID_PACKET_CS_FORCESTART), &CSForceStartPacketFactory{})

	// 同步玩家状态
	//common.RegisterHandler(int(gamehall.GameHallPacketID_PACKET_CS_PLAYER_SWITCHFLAG), &CSPlayerSwitchFlagHandler{})
	//netlib.RegisterFactory(int(gamehall.GameHallPacketID_PACKET_CS_PLAYER_SWITCHFLAG), &CSPlayerSwitchFlagPacketFactory{})

	// 房间事件
	common.Register(int(gamehall.GameHallPacketID_PACKET_CSRoomEvent), gamehall.CSRoomEvent{}, CSRoomEvent)
}
