package game

import (
	"bytes"
	"encoding/gob"
	"fmt"
	userCfg "server/conf/user"
	"server/db"
	"server/game/mod/activity"
	"server/game/mod/avatar"
	"server/game/mod/base"
	"server/game/mod/card"
	"server/game/mod/catnip"
	"server/game/mod/champship"
	"server/game/mod/charge"
	"server/game/mod/chess"
	"server/game/mod/collect"
	"server/game/mod/compensation"
	dailyTask "server/game/mod/daily_task"
	"server/game/mod/decorate"
	"server/game/mod/emoji"
	"server/game/mod/endless"
	"server/game/mod/face"
	"server/game/mod/friend"
	friendTreasure "server/game/mod/friend_treasure.go"
	guesscolor "server/game/mod/guess_color"
	"server/game/mod/guide"
	guideTask "server/game/mod/guide_task"
	"server/game/mod/handbook"
	"server/game/mod/invite"
	"server/game/mod/item"
	"server/game/mod/kv"
	limitedTimeEvent "server/game/mod/limited_time_event"
	"server/game/mod/mail"
	"server/game/mod/mining"
	"server/game/mod/order"
	"server/game/mod/pass"
	piggyBank "server/game/mod/piggy_bank"
	"server/game/mod/playroom"
	"server/game/mod/race"
	sevenLogin "server/game/mod/seven_login"
	Var "server/game/mod/var"
	"server/pkg/github.com/name5566/leaf/log"
	"sync"
	"time"
)

// buffer 对象池，复用 bytes.Buffer 减少内存分配
var bufferPool = sync.Pool{
	New: func() interface{} {
		return bytes.NewBuffer(make([]byte, 0, 128*1024))
	},
}

type PlayerData struct {
	Name         string
	IsHaveDataDb bool
	M_Player     *Player
}

func (d *PlayerData) SetPlayer(p *Player) {
	d.M_Player = p
}

func (d *PlayerData) GetPlayer() *Player {
	return d.M_Player
}

func (d *PlayerData) GetData() interface{} {
	res := struct{}{}
	return res
}

func NewPlayerData(name string, player *Player) *PlayerData {
	return &PlayerData{
		Name:     name,
		M_Player: player,
	}
}

type PlayerModData struct {
	*PlayerData
	Data    db.SqlModStruct
	ModList PlayerModList
}

// PlayerModList 玩家模块列表
type PlayerModList struct {
	Base             base.Base                            // 基础信息
	Chess            chess.ChessBorad                     // 棋盘
	Handbook         handbook.Handbook                    // 图鉴
	Order            order.OrderMod                       //订单
	Decorate         decorate.Decorate                    //装饰
	Card             card.CardMod                         //卡牌
	Var              Var.Var                              // 变量
	Guide            guide.Guide                          // 引导
	DailyTask        dailyTask.DailyTaskMod               // 每日任务
	Face             face.FaceMod                         // 头像
	Avatar           avatar.AvatarMod                     // 头像框
	SevenLogin       sevenLogin.SevenLoginMod             // 七天签到
	LimitedTimeEvent limitedTimeEvent.LimitedTimeEventMod // 限时事件
	Friend           friend.FriendMod                     // 好友
	Mail             mail.MailMod                         // 邮件
	Charge           charge.ChargeMod                     // 商店充值
	Endless          endless.EndlessMod                   // 无尽礼包
	PiggyBank        piggyBank.PiggyBankMod               // 小猪存钱
	Champship        champship.ChampshipMod               // 锦标赛
	Invite           invite.InviteMod                     // 邀请
	Kv               kv.KvMod                             //  客户端数据
	Mining           mining.MiningMod                     // 挖矿活动
	Item             item.ItemMod                         // 道具
	GuessColor       guesscolor.GuessColorMod             // 猜颜色活动
	Race             race.RaceMod                         // 竞赛活动
	Playroom         playroom.PlayroomMod                 // 玩家小屋
	FriendTreasure   friendTreasure.FriendTreasureMod     // 好友宝藏
	Emoji            emoji.EmojiMod                       // 表情
	Collect          collect.Collect                      // 收集
	Activity         activity.Activity                    // 活动
	Compensation     compensation.Compensation            // 补偿
	Catnip           catnip.CatnipMod                     // 猫草大作战
	GuideTask        guideTask.GuideTaskMod               // 引导任务
	Pass             pass.PassMod                         // 通行证
}

func (p *PlayerModData) LoadDataFromDB(dwUin interface{}) bool {
	sqlStr := "SELECT * FROM t_player_mod WHERE dwUin = ?"
	p.Data = db.SqlModStruct{}
	if err := db.SqlDb.Get(&p.Data, sqlStr, dwUin.(int64)); err != nil {

		p.IsHaveDataDb = false
	} else {
		p.IsHaveDataDb = true
	}
	p.Data.DwUin = dwUin.(int64)
	return true
}

func (p *PlayerModData) ClearData() bool {
	return true
}

func (p *PlayerModData) SaveDataFromDB(Key interface{}) bool {
	//序列化数据
	db.FormatAllMemUpdateDb(&p.Data, "t_player_mod", "dwUin")
	p.IsHaveDataDb = true
	return true
}

func (p *PlayerModData) ReqModData(buf []byte) {

}

// 推送基础数据
func (p *PlayerModData) Reconnect(b bool) []byte {
	return []byte{}
}

func (p *PlayerModData) InitMod(player *Player) (bool, error) {
	playerModList := PlayerModList{}
	if len(p.Data.ModData) > 0 {
		buf := bytes.NewBuffer(p.Data.ModData)
		decoder := gob.NewDecoder(buf)
		err := decoder.Decode(&playerModList)
		if err != nil {
			log.Debug("playmod get data failed, err:%v\n", err)
			return false, fmt.Errorf("playmod get data failed, err:%v", err)
		}
	}
	p.ModList = playerModList
	is_update := false

	// 初始化棋盘模块

	if p.ModList.Chess.IsEmpty() {
		var chessMod chess.ChessBorad
		chessMod.InitData()
		p.ModList.Chess = chessMod
		is_update = true
	}
	BaseMod := &p.ModList.Base
	PlayerBaseMod := player.GetPlayerBaseMod()
	if BaseMod.Uid == 0 {
		BaseMod.Uid = PlayerBaseMod.Data.DwUin
		BaseMod.SetLevel(1)
		BaseMod.SetExp(0)
		BaseMod.SetEnergy(userCfg.GetInitEnergy())
		BaseMod.SetStar(userCfg.GetInitStar())
		BaseMod.SetDiamond(userCfg.GetInitDiamond())
		BaseMod.SetRecoverTime(int64(PlayerBaseMod.Data.RecoverTime))
		BaseMod.FackBookId = PlayerBaseMod.Data.FaceBookId
		is_update = true
	}
	BaseMod.SetAccount(PlayerBaseMod.Data.UserName)
	Ip := p.GetPlayer().GetIp()
	p.ModList.Handbook.InitData()
	p.ModList.Order.InitData()
	p.ModList.Decorate.InitData()
	p.ModList.Card.InitData()
	p.ModList.Var.InitData()
	p.ModList.Guide.InitData()
	p.ModList.DailyTask.InitData()
	p.ModList.Face.InitData()
	p.ModList.Avatar.InitData()
	p.ModList.Base.InitData(int(p.Data.DwUin), Ip)
	p.ModList.SevenLogin.InitData()
	p.ModList.LimitedTimeEvent.InitData(BaseMod.GetLevel())
	p.ModList.Friend.InitData()
	p.ModList.Mail.InitData()
	p.ModList.Charge.InitData()
	p.ModList.Endless.InitData()
	p.ModList.Invite.InitData()
	p.ModList.Kv.InitData()
	p.ModList.Mining.InitData()
	p.ModList.Item.InitData()
	p.ModList.GuessColor.InitData()
	p.ModList.Playroom.InitData()
	p.ModList.Emoji.InitData()
	p.ModList.Collect.InitData()
	p.ModList.Activity.InitData()
	p.ModList.Catnip.InitData()
	p.ModList.Compensation.InitData()
	p.ModList.GuideTask.InitData()
	p.ModList.Pass.InitData()
	return is_update, nil
}

type PlayerMod struct {
	mod_list  PlayerModList
	is_update bool
}

func (p *PlayerMod) save() {
	p.is_update = true
}

func (p *PlayerMod) IsBlackList() bool {
	BaseMod := p.getBaseMod()
	return BaseMod.Account == "cecf89cd063b93c63da531daf7204afa"
}

func (p *PlayerMod) ClearData(player *Player) {
	ChessMod := p.getChessMod()
	if len(ChessMod.ChessMap) > 0 && len(ChessMod.ChessList) != len(ChessMod.ChessMap) {
		log.Debug("uid: %d, SaveData, chess error ", player.M_DwUin)
		return
	}
	if p.is_update && !p.IsBlackList() {
		//序列化模块
		buf := bufferPool.Get().(*bytes.Buffer)
		buf.Reset() // 清空之前的数据
		encode := gob.NewEncoder(buf)
		err := encode.Encode(p.mod_list)
		if err != nil {
			bufferPool.Put(buf) // 即使出错也要归还
			log.Debug("uid: %d, SaveData, playmod error %v", player.M_DwUin, err)
			return
		}
		// log.Debug("uid: %d, ClearData, playmod", player.M_DwUin)
		modData := &db.SqlModStruct{
			DwUin:      player.M_DwUin,
			ModData:    buf.Bytes(),
			UpdataTime: int32(time.Now().Unix()),
		}

		err = db.SavePlayerModData(modData)
		if err != nil {
			bufferPool.Put(buf) // 即使出错也要归还
			log.Debug("uid: %d, SaveData, playmod error %v", player.M_DwUin, err)
			return
		}
		p.is_update = false
		bufferPool.Put(buf) // 归还到对象池
	}
}

func (p *PlayerMod) BackUp(B *PlayerBackUp) {
	// 从对象池获取 buffer，复用以减少内存分配
	buf := bufferPool.Get().(*bytes.Buffer)
	buf.Reset() // 清空之前的数据

	encode := gob.NewEncoder(buf)
	err := encode.Encode(p.mod_list)
	if err != nil {
		log.Debug("Backup, playmod error %v", err)
		bufferPool.Put(buf) // 即使出错也要归还
		return
	}

	// 复制数据，因为 buf 会被放回池中
	B.PlayMod = append([]byte(nil), buf.Bytes()...)

	// 归还到对象池供下次使用
	bufferPool.Put(buf)
}

func (p *PlayerMod) Recover(B *PlayerBackUp) {
	if len(B.PlayMod) > 0 {
		PlayMod := PlayerModList{}
		buf := bytes.NewBuffer(B.PlayMod)
		decoder := gob.NewDecoder(buf)
		err := decoder.Decode(&PlayMod)
		if err != nil {
			log.Debug("Recover, playmod error %v", err)
			return
		}
		p.mod_list = PlayMod
	}
}

func (p *PlayerMod) getChessMod() *chess.ChessBorad {
	return &p.mod_list.Chess
}

func (p *PlayerMod) getBaseMod() *base.Base {
	return &p.mod_list.Base
}

func (p *PlayerMod) getHandbookMod() *handbook.Handbook {
	return &p.mod_list.Handbook
}

func (p *PlayerMod) getOrderMod() *order.OrderMod {
	return &p.mod_list.Order
}

func (p *PlayerMod) getDecorateMod() *decorate.Decorate {
	return &p.mod_list.Decorate
}

func (p *PlayerMod) getCardMod() *card.CardMod {
	return &p.mod_list.Card
}

func (p *PlayerMod) getVarMod() *Var.Var {
	return &p.mod_list.Var
}

func (p *PlayerMod) getGuideMod() *guide.Guide {
	return &p.mod_list.Guide
}

func (p *PlayerMod) getDailyTaskMod() *dailyTask.DailyTaskMod {
	return &p.mod_list.DailyTask
}

func (p *PlayerMod) getFaceMod() *face.FaceMod {
	return &p.mod_list.Face
}

func (p *PlayerMod) getAvatarMod() *avatar.AvatarMod {
	return &p.mod_list.Avatar
}

func (p *PlayerMod) getSevenLoginMod() *sevenLogin.SevenLoginMod {
	return &p.mod_list.SevenLogin
}

func (p *PlayerMod) getLimitedTimeEventMod() *limitedTimeEvent.LimitedTimeEventMod {
	return &p.mod_list.LimitedTimeEvent
}

func (p *PlayerMod) getFriendMod() *friend.FriendMod {
	return &p.mod_list.Friend
}

func (p *PlayerMod) getMailMod() *mail.MailMod {
	return &p.mod_list.Mail
}

func (p *PlayerMod) getChargeMod() *charge.ChargeMod {
	return &p.mod_list.Charge
}

func (p *PlayerMod) getEndlessMod() *endless.EndlessMod {
	return &p.mod_list.Endless
}

func (p *PlayerMod) getPiggyBankMod() *piggyBank.PiggyBankMod {
	return &p.mod_list.PiggyBank
}

func (p *PlayerMod) getChampshipMod() *champship.ChampshipMod {
	return &p.mod_list.Champship
}

func (p *PlayerMod) getInviteMod() *invite.InviteMod {
	return &p.mod_list.Invite
}

func (p *PlayerMod) getKvMod() *kv.KvMod {
	return &p.mod_list.Kv
}

func (p *PlayerMod) getMiningMod() *mining.MiningMod {
	return &p.mod_list.Mining
}

func (p *PlayerMod) getItemMod() *item.ItemMod {
	return &p.mod_list.Item
}

func (p *PlayerMod) getGuessColorMod() *guesscolor.GuessColorMod {
	return &p.mod_list.GuessColor
}

func (p *PlayerMod) getRaceMod() *race.RaceMod {
	return &p.mod_list.Race
}

func (p *PlayerMod) getPlayroomMod() *playroom.PlayroomMod {
	return &p.mod_list.Playroom
}

func (p *PlayerMod) getFriendTreasureMod() *friendTreasure.FriendTreasureMod {
	return &p.mod_list.FriendTreasure
}

func (p *PlayerMod) getEmojiMod() *emoji.EmojiMod {
	return &p.mod_list.Emoji
}

func (p *PlayerMod) getCollectMod() *collect.Collect {
	return &p.mod_list.Collect
}

func (p *PlayerMod) getActivityMod() *activity.Activity {
	return &p.mod_list.Activity
}
func (p *PlayerMod) getCompensationMod() *compensation.Compensation {
	return &p.mod_list.Compensation
}
func (p *PlayerMod) getCatnipMod() *catnip.CatnipMod {
	return &p.mod_list.Catnip
}
func (p *PlayerMod) getGuideTaskMod() *guideTask.GuideTaskMod {
	return &p.mod_list.GuideTask
}

func (p *PlayerMod) getPassMod() *pass.PassMod {
	return &p.mod_list.Pass
}
