package model

import (
	"fmt"
	"strconv"
	"time"

	"leafstalk/otherutils/deepcopy"

	"xorm.io/xorm"
)

type LoginToken struct {
	AccId    int64
	OpenId   string
	Token    string
	NickName string
	ImgUrl   string
	GdtVid   string // 进入所点击广告ID
	AdId     string
	AdSrc    string
	Flag     int //用户标志
	Plat     string
}

type PlayerSummary struct {
	LineId int `json:"serverId"`
	Level  int `json:"level"`
}

// Player 玩家信息
type Player struct {
	Id           int64
	AccId        int64            `xorm:"BIGINT index 'accId'"`
	OpenID       string           `xorm:"varchar(255) index 'openid'"`
	NickName     string           `xorm:"varchar(255) 'nickname'" json:"nickName"`
	AvatarURL    string           `xorm:"varchar(512) 'avatar'" json:"avatarUrl"` // 目前由world维护 login储存
	Account      string           `xorm:"varchar(255) 'account'"`
	Passwod      string           `xorm:"varchar(255) 'password'" json:"-"`
	Inviter      int64            `xorm:"BIGINT  'inviter'"`
	PlatOpenID   string           `xorm:"varchar(255) 'platopenid'"`
	Unionid      string           `xorm:"varchar(255) 'unionid'"`
	Plat         int              `xorm:"int 'plat'"`
	SessionKey   string           `xorm:"varchar(512) 'sessionkey'"`
	SelectServer int              `xorm:"int 'server'"`                 // 选择登录线
	Summary      []*PlayerSummary `xorm:"varchar(1024) json 'summary'"` // 玩家在各服的档案信息
	Ban          int              `xorm:"int 'ban'"`
	Flag         int              `xorm:"default 0 int 'flag'"` //用户标记，老用户为0，新用户根据openid计算，奇数为1，偶数为0

	IDCard      string `xorm:"varchar(255) 'idcard'"`
	RealName    string `xorm:"varchar(255) 'name'"`
	BornTime    int64  `xorm:"BIGINT 'borntime'"`
	GameTime    int64  `xorm:"BIGINT 'gametime'"`
	GameTimeLen int    `xorm:"int 'gametimelen'"`

	ClickId string `xorm:"varchar(255) 'clickId'"` // 进入所点击广告ID
	AdId    string `xorm:"varchar(128) 'aId'"`     //广告ID
	AdSrc   string `xorm:"varchar(128) 'adSrc'"`   //广告来源

	UpdateTime    int64  `xorm:"'updated' updated"`
	CreateTime    int64  `xorm:"'createtime' created" json:"createtime"`
	ClientVersion string `xorm:"varchar(255) 'clientVersion'"` // 客户端储存的验证版本相关信息 服务器只做储存 客户端不会发 ;
	TableNo       int    `xorm:"-"`
}

// TableName 表名
func (player *Player) TableName() string {
	if player.TableNo > 0 {
		return fmt.Sprintf("user_account_%v", player.TableNo)
	}
	return "user_account"
}

func (p *Player) GlobalId() int64 {
	return p.AccId
}

func (p *Player) Key() string {
	if len(p.OpenID) > 0 {
		return p.OpenID
	}
	if len(p.Account) > 0 {
		return fmt.Sprintf("%v@%v", p.Account, LoginPlatAccount)
	}
	return fmt.Sprintf("%v@%v", "test", LoginPlatAccount)
}

// 成长性英雄
type GrowableHero struct {
	// ID    int64 `json:"id"`
	Level int64 `json:"level"`
	Skin  int64 `json:"wear"`
}

// // 要塞时装(皮肤)
// type FortSkin struct {
// 	Wear  int64              `json:"wear"`
// 	Skins map[int64]struct{} `json:"skins"` //皮肤星级id:
// }

// func (fs *GrowableFort) FindStarSkinByModeId(modelId int64) int64 {
// 	for starId := range fs.Skins {
// 		if starId/100 == modelId {
// 			return starId
// 		}
// 	}

// 	return 0
// }

// func (fs *GrowableFort) HasStarSkin(skinId int64) bool {
// 	_, ok := fs.Skins[skinId]
// 	return ok
// }

// func (fs *GrowableFort) GetSkinModeIds() []int64 {
// 	var lst []int64
// 	for starId, _ := range fs.Skins {
// 		lst = append(lst, starId/100)
// 	}
// 	return lst
// }

func FortSkinStarIdToSkinId(skinStarId int64) int64 {
	return skinStarId / 100
}

func FortSkinIdToStarId(skinId int64, level int64) int64 {
	return (skinId*100 + level)
}

// 要塞部位
type FortPart struct {
	Level    int64 `json:"level"`       //部位等级
	WearRune int64 `json:"wear,string"` //部位镶嵌的符文
}

// 要塞
type GrowableFort struct {
	Level      int64           `json:"level"`   //等级
	Parts      [6]*FortPart    `json:"parts"`   //部位
	TalentTree [2]int64        `json:"talents"` //天赋树
	WearSkin   int64           `json:"wear"`
	Skins      map[int64]int64 `json:"skins"` //皮肤id:星级
	SkillIds   [3]int64        `json:"skill"` //技能对应的皮肤ID 不时星级ID
	// Skin       *FortSkin          `json:"skin"`    //皮肤
}

// type DropMaterial struct {
// 	MaterialData map[int64]*MaterialData `json:"materialData"`
// }

type HeadFrame struct {
	HeadId   int64 `json:"headId"`  // 头像 -1 代表使用 AvatarURL 微信授权头像
	FrameId  int64 `json:"frameId"` // 头像框
	HIdEndTs int64 `json:"hEndTs"`  // 头像结束时间 -1 无限制
	FIdEndTs int64 `json:"fEndTs"`  // 头像框结束时间
}

type RuneAffix struct {
	Type  int64   `json:"typ"`
	Value float64 `json:"val"`
}

type RuneAffixAndPos struct {
	*RuneAffix     //`json:"runeAffix"` //
	Pos        int `json:"pos"` //
}

type RuneRecastAttr struct {
	Gid   int64
	Ts    int64
	Items []*RuneAffixAndPos
}

// 符文
type BagRune struct {
	ModeId int64        `json:"id"`
	Attrs  []*RuneAffix `json:"attrs,omitempty"` // 附加属性 [几条属性][属性类型,值]
	// WearPos int64        `json:"pos,omitempty"`   // 穿戴位置
}

// type ClientBagRune struct {
// 	ModeId int64        `json:"id"`
// 	Attrs  []*RuneAffix `json:"attrs,omitempty"` // 附加属性 [几条属性][属性类型,值]
// 	// WearPos int64        `json:"pos,omitempty"`   // 穿戴位置
// }

type DropedRune struct {
	*BagRune
	GId int64 `json:"gId"`
}

func NewChapterSummary() *ChapterSummary {
	it := new(ChapterSummary)
	it.Process = make([]*ChapterProcess, 0, 1)
	it.Levels = make(map[int64]*LevelSummary)
	return it
}

type ChapterSummary struct {
	Process []*ChapterProcess       `json:"process"`
	Levels  map[int64]*LevelSummary `json:"levels"`
}

func NewChapterProcess2(typ int64) *ChapterProcess {
	it := new(ChapterProcess)
	it.Type = typ
	return it
	// it.Chapter =

	// return &ChapterProcess{
	// 	ChapterLevels: make(map[int64][2]int64),
	// 	LevelWaves:    make(map[int64]*ChapterLevel),
	// }
}

type ChapterProcess struct {
	Type    int64 `json:"type"`
	Chapter int64 `json:"chapter"`
	Level   int64 `json:"level"`
	Passed  int64 `json:"passed"`
}

func NewLevelSummary() *LevelSummary {
	it := new(LevelSummary)
	return it
}

type LevelSummary struct {
	// Level    int64 `json:"id"`
	Wave     int64 `json:"wave"`
	Geted    int64 `json:"geted"`
	SubWave  int64 `json:"subWave"`
	SubGeted int64 `json:"subGeted"`
	JoinTs   int64 `json:"joinTs"`
}

type ChapterProcess2 struct {
	ChapterLevels map[int64][2]int64      `json:"cl"`     //已解锁的章节关卡 章节[小章节ID,是否已通关？1:0]
	LevelWaves    map[int64]*LevelSummary `json:"levels"` //需要处理的关卡进度及奖励 关卡编号[大章节ID,关卡ID,首次通过波数,首通奖励领取到的波次,循环通过的波次,循环奖励领取到的波次,循环波次完成时间]

	// Chapter int64  `json:"id"` //大章节ID
	// Level   int64  `json:"lv"` //关卡 1,2,3，。。
	// First   [2]int `json:"fw"` //首次通过波数 [首次通过波数,首次奖励领取到的波次]
	// Cycle   [2]int `json:"cw"` //循环通过的波次 [循环通过的波次,循环奖励领取到的波次]

	// FirstReward int64 `json:"fr"` //首通奖励领取到的波次
	// CycleWave   int64 `json:"cw"` //循环通过的波次
	// CycleReward int64 `json:"cr"` //循环奖励领取到的波次

	// Chpater     int64 `json:"id"`   //关卡ID
	// Door        int64 `json:"door"` //关卡门
	// FirstWave   int64 `json:"fw"`   //首次通过波数
	// FirstReward int64 `json:"fr"`   //首通奖励领取到的波次
	// CycleWave   int64 `json:"cw"`   //循环通过的波次
	// CycleReward int64 `json:"cr"`   //循环奖励领取到的波次
	// FirstPass   int64 `json:"pass"` //是否通关
}

// type WaveAndReward struct {
// 	Wave   int64 `json:"w"` //首次通过波数
// 	Reward int64 `json:"r"` //首通奖励领取到的波次
// }

type ChapterLevel2 struct {
	First  [2]int64 `json:"fw"` //首次通过波数 [首次通过波数,首次奖励领取到的波次]
	Normal [2]int64 `json:"nw"` //循环通过的波次 [循环通过的波次,循环奖励领取到的波次]
	JoinTs int64    `json:"js"` //循环波次完成时间

	// Chapter int64  `json:"id"` //大章节ID
	// Level   int64  `json:"lv"` //关卡 1,2,3，。。

	// Chapter     int64 `json:"id"` //关卡ID
	// Level       int64 `json:"lv"` //关卡
	// FirstWave   int64 `json:"fw"` //首次通过波数
	// FirstReward int64 `json:"fr"` //首通奖励领取到的波次
	// CycleWave   int64 `json:"cw"` //循环通过的波次
	// CycleReward int64 `json:"cr"` //循环奖励领取到的波次
	// CycleTs     int64 `json:"ts"` //循环波次完成时间
	// // FirstPass   int64 `json:"pass"` //是否通关
}

// 宝物
type GrowableTreasure struct {
	Level int64 `json:"level"` // 等级
	Star  int64 `json:"star"`  // 星级
}

type RecruitStatis struct {
	HeroNum     int64    `json:"heroNum"`     // 英雄招募次数（暗保底使用，触发暗保底后会清0）
	TreasureNum [2]int64 `json:"treasureNum"` // 宝物招募次数（暗保底使用，触发暗保底后会清0） 10次保底和500次保底
	EpigraphNum int64    `json:"epigraphNum"` // 铭文招募次数（暗保底使用，触发暗保底后会清0）
}

type TicketData struct {
	// Stamina      int   `json:"stamina"`      // 当前体力 放背包
	LastStamTick    int64 `json:"lastStamTick"`    // 生效时间
	DayStamTick     int64 `json:"dayStamTick"`     // 购买时间
	DayStamBuyCount int   `json:"dayStamBuyCount"` // 今日购买次数
	AdStamCount     int   `json:"adStamCount"`     // 今日使用免费次数

	LastEnergyTick    int64 `json:"lastEnergyTick"`    // 精力生效时间
	DayEnergyTick     int64 `json:"dayEnergyTick"`     // 精力购买时间
	DayEnergyBuyCount int   `json:"dayEnergyBuyCount"` // 今日精力购买次数
	AdEnergyCount     int   `json:"adEnergyCount"`     // 今日精力使用免费次数
}

type GamePlayer struct {
	Id             int64     //`xorm:"BIGINT pk autoincr 'id'"`
	PlayerId       int64     `xorm:"BIGINT index 'playerid'"`
	AccId          int64     `xorm:"BIGINT index(serveracc) 'accId'"`
	LineId         int64     `xorm:"int index(serveracc) 'line'"`
	Level          int64     `xorm:"int 'level'"`
	Exp            int64     `xorm:"BIGINT 'exp'"`
	LastLoginTick  int64     `xorm:"BIGINT 'lastlogintick'"`
	LastLogoutTick int64     `xorm:"BIGINT 'lastlogouttick'"`
	OpenId         string    `xorm:"VARCHAR(255) 'openId'"`
	NickName       string    `xorm:"VARCHAR(255) index 'nickName'"`
	ImgUrl         string    `xorm:"VARCHAR(512) 'imgUrl'"`
	HeadImg        HeadFrame `xorm:"Text json 'headImg'"`
	CreateTime     time.Time `xorm:"created"`
	Ban            int       `xorm:"int 'ban'"`
	AdId           string    `xorm:"VARCHAR(128) 'adId'"`
	ClickId        string    `xorm:"VARCHAR(255) 'clickId'"`
	AdSrc          string    `xorm:"VARCHAR(128) 'adSrc'"`
	Plat           string    `xorm:"VARCHAR(20) 'plat'"`    // wx tt
	SubPlat        int       `xorm:"int default 0 subPlat"` // 1 抖音; 2 抖音极速
	Flag           int       `xorm:"int 'flag'"`            //标记
	GateId         int64     `xorm:"-"`                     // 所在网关
	Online         bool      `xorm:"-"`                     // 在线状态

	Materials  map[int64]int64             `xorm:"Text 'materials'"`      // 道具
	Heros      map[int64]*GrowableHero     `xorm:"Text json 'heros'"`     // 英雄
	HeroSkins  map[int64]struct{}          `xorm:"Text json 'heroSkins'"` // 英雄皮肤，玩家可以不拥有英雄却拥有皮肤。所以单独记录。
	Fort       *GrowableFort               `xorm:"Text json 'fort'"`      //时装
	Runes      map[int64]*BagRune          `xorm:"Text 'runes'"`          //符文
	Chapters   *ChapterSummary             `xorm:"Text json 'chapters'"`  //章节进度
	Treasures  map[int64]*GrowableTreasure `xorm:"Text json 'treasures'"` // 宝物
	Recruit    *RecruitStatis              `xorm:"Text json 'recruit'"`   // 招募
	RuneRecast *RuneRecastAttr             `xorm:"Text json 'recast'"`    //符文重铸
	// StaminaInfo *StaminaData                `xorm:"Text json 'stamina'"`   // 体力信息
	Crystals   map[int64]int64 `xorm:"Text 'crystal'"`         //水晶 [水晶id]领取过奖励
	TicketInfo *TicketData     `xorm:"Text json 'ticketdata'"` // 体力 精力信息
	// WearRunes  map[int64]struct{}          `xorm:"-"`                     //穿戴的符文[符文类型]符文id

	// Coin          int64            `xorm:"BIGINT 'coin'"`
	// Diamond       int              `xorm:"int 'diamond'"`

	// Exterior      *Exterior        `xorm:"Text json 'exterior'"` // 外观
	// CombatEffe    int64            `xorm:"BIGINT default 0 combatEffe"`
	// MaxCombatEffe int64            `xorm:"BIGINT default 0 maxCombatEffe"`
	// HeadFrames    *DropedHeadFrame `xorm:"Text json 'headFrames'"` // 头像

	// Heros         *DropedHero      `xorm:"Text json 'heros'"`      // 英雄
	// PassRoom      *PassRoom        `xorm:"Text json 'passRoom'"`   // 关卡数据
	// Fortress      *DropedFortress  `xorm:"Text json 'fortress'"`   // 要塞
	// Fashion       *DropedFashion   `xorm:"Text json 'fashion'"`    // 时装
	// New           bool             `xorm:"-"`                      // 新注册玩家
}

func (m GamePlayer) TableName() string {
	return "player_attr"
}

// 需要保存的数据需确保在这里能复制到new1 中
func (m *GamePlayer) DeepCopy() interface{} {
	new1 := new(GamePlayer)
	*new1 = *m

	return new1
}

func (m *GamePlayer) QueryExist(eng *xorm.Engine) (bool, error) {
	player := new(GamePlayer)
	player.PlayerId = m.PlayerId
	return eng.Exist(player)
}

func (m *GamePlayer) UpdateDB(eng *xorm.Engine) (int64, error) {
	return eng.Where("playerid=?", m.PlayerId).MustCols("stamina", "lastStamTick").Update(m)
}

func (m *GamePlayer) GetUniqueKey() string {
	//return m.UserId
	return strconv.FormatInt(m.PlayerId, 10)
}

// 实现DeepCopy接口
func CopyGamePlayer(old *GamePlayer) *GamePlayer {
	new2, err := deepcopy.Copy(old) //
	if err != nil {
		return nil
	}
	return new2.(*GamePlayer)
}
