package maps

import (
	"blazing/common/data/xmlres"
	"blazing/logic/service"
	"blazing/logic/service/space"

	"blazing/modules/blazing/model"
	"math/rand"
	"strings"
	"time"

	"github.com/creasty/defaults"
	"github.com/gogf/gf/v2/util/gconv"
)

type InInfo struct {
	Head service.TomeeHeader `cmd:"2001" struc:"[0]pad"` //切换地图
	// 地图类型
	MapType uint32

	MapId uint32
	// Point: 直接给坐标x，y
	Point    model.Pos `fieldDesc:"直接给坐标x，y"`
	monsters [3]int
	// Reverse2: 暂定 占位字符2
	//Reverse2 string `struc:"[2]byte"`
}

func (t *InInfo) Broadcast(mapid uint32, o OutInfo) {

	space.GetSpace(mapid).Range(func(playerID uint32, player service.PlayerI) bool {
		t.Head.Result = 0

		player.SendPack(t.Head.Pack(&o))
		return true
	})
}

// 刷怪具体实现
func (t *InInfo) SpawnMonsters(c *service.Player, isfrist bool) {
	// 获取当前地图的怪物配置

	if c == nil || c.Info.MapID == 0 { //用户离线
		return
	}
	if !c.IsLogin {
		defer func() {

			if c.StopChan != nil {
				close(c.StopChan)
				c.StopChan = nil
			}
		}()
	}

	// 创建数据包
	tt := service.NewTomeeHeader(2004, c.Info.UserID)

	if isfrist {
		t.monsters = generateThreeUniqueNumbers()
	} else {

		t.monsters, _, _ = replaceOneNumber(t.monsters)
	}
	t1 := t.genMonster(c.Info.MapID)
	if t1 != nil {
		c.OgreInfo = t1
		t1 := tt.Pack(t1)
		c.SendPack(t1)
	}

}

// 2. 从 string 类型 slice 随机选一个元素
func RandomStringFromSlice(s []string) string {

	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	randomIdx := r.Intn(len(s))
	return s[randomIdx]
}

// 应该根据怪物信息决定后端生成
func (t *InInfo) genMonster(mapid uint32) *service.OgreInfo {
	// 设置怪物信息
	t1 := service.OgreInfo{}
	mapss, ok := xmlres.MonsterMap[gconv.Int(mapid)]

	if ok && mapss.Monsters != nil {
		for i, m := range mapss.Monsters.Monsters { //这里是9个
			id := strings.Split(m.ID, " ")
			lv := strings.Split(m.Lv, " ")
			ttt := service.OgrePetInfo{
				Id: gconv.Uint32(RandomStringFromSlice(id)),
			}
			if ttt.Id != 0 {
				ttt.Shiny = 0 //待确认是否刷新异色
				ttt.Lv = gconv.Uint32(RandomStringFromSlice(lv))
			}
			t1.Data[i] = ttt

		}

	}

	t2 := service.OgreInfo{}
	for i := 0; i < 3; i++ {

		t2.Data[t.monsters[i]] = t1.Data[t.monsters[i]]
	}

	return &t2
}

// 计算整数的二进制1的个数（Integer.bitCount）
func bitsCount(n int) int {
	count := 0
	for n > 0 {
		count += n & 1
		n >>= 1
	}
	return count
}

// 生成0-9之间三个不重复的随机数 进地图5s
func generateThreeUniqueNumbers() [3]int {
	rand.Seed(time.Now().UnixNano())
	selected := make(map[int]bool)
	var result [3]int
	index := 0

	for index < 3 {
		num := rand.Intn(9)
		if !selected[num] {
			selected[num] = true
			result[index] = num
			index++
		}
	}
	return result
}

// 从三个数字中移除一个，并从剩余6个数字中选一个补充 10s
func replaceOneNumber(original [3]int) ([3]int, int, int) {
	// 随机选择要移除的索引（0-2）
	removeIndex := rand.Intn(3)
	removedNum := original[removeIndex]

	// 找出所有不在原始数组中的数字（候选数字）
	candidates := []int{}
	originalMap := make(map[int]bool)
	for _, num := range original {
		originalMap[num] = true
	}

	for i := 0; i < 8; i++ {
		if !originalMap[i] {
			candidates = append(candidates, i)
		}
	}

	// 从候选数字中随机选择一个
	newNum := candidates[rand.Intn(len(candidates))]

	// 创建新数组并替换数字
	newNumbers := original
	newNumbers[removeIndex] = newNum

	return newNumbers, removedNum, newNum
}

// 这里存储星球的map
//var planetmap utils.SyncMap[] //= space.NewSyncMap()

// PeopleInfo PeopleInfo类，实现OutboundMessage接口
type OutInfo struct {
	UserID uint32 `struc:"uint32" fieldDesc:"米米号" json:"user_id"`

	// 16字节昵称
	Nick string `struc:"[16]byte" fieldDesc:"16字节昵称" json:"nick"`

	// 机器人人物颜色 00 rgb
	Color uint32 `struc:"uint32" fieldDesc:"机器人人物颜色 00 rgb" json:"color"`

	// 固定值0
	Texture uint32 `struc:"uint32" fieldDesc:"固定值0" json:"texture"`

	// 暂时不明建议先给固定值0
	Vip uint16 `    json:"vip"`

	// 暂时不明建议先给固定值15
	Viped uint16 `  default:"15"   json:"viped"`

	// 暂时不明建议先给固定值1
	VipStage uint32 `struc:"uint32" fieldDesc:"暂时不明建议先给固定值1" json:"vip_stage"`

	// 人物状态 =0 步行 !=0 飞行
	ActionType uint32 `struc:"uint32" fieldDesc:"人物状态 =0 步行 !=0 飞行" json:"action_type"`

	// 上线的地图id
	Pos model.Pos `fieldDesc:"上线的地图id" json:"pos"`

	// 暂时不明给0
	Action uint32 `struc:"uint32" fieldDesc:"暂时不明给0" json:"action"`

	// 暂时不明给2
	Direction uint32 `struc:"uint32" default:"2" fieldDesc:"暂时不明给2" json:"direction"`

	// 暂时不明给0
	ChangeShape uint32 `struc:"uint32" fieldDesc:"暂时不明给0" json:"change_shape"`

	// 暂时不明给0
	SpiritTime uint32 `struc:"uint32" fieldDesc:"暂时不明给0" json:"spirit_time"`

	// 暂时不明给0
	SpiritID uint32 `struc:"uint32" fieldDesc:"暂时不明给0" json:"spirit_id"`

	// 宠物 ID 暂时无法测试，给 0
	PetDV uint32 `struc:"uint32" fieldDesc:"宠物ID暂时无法测试, 给0" json:"pet_dv"`
	// 宠物闪光暂时无法测试，给 0
	PetShiny uint32 `struc:"uint32" fieldDesc:"宠物闪光暂时无法测试, 给0" json:"pet_shiny"`
	// 宠物皮肤暂时无法测试，给 0
	PetSkin uint32 `struc:"uint32" fieldDesc:"宠物皮肤暂时无法测试, 给0" json:"pet_skin"`
	// 填充字符
	Reserved uint32 `struc:"uint32" fieldDesc:"填充字符" json:"reserved"`
	// 填充字符
	Reserved1 uint32 `struc:"uint32" fieldDesc:"填充字符" json:"reserved1"`
	// 填充字符
	Reserved2 uint32 `struc:"uint32" fieldDesc:"填充字符" json:"reserved2"`

	// 暂时不明给0
	FightFlag uint32 `struc:"uint32" fieldDesc:"暂时不明给0" json:"fight_flag"`

	// 教官ID
	TeacherID uint32 `struc:"uint32" fieldDesc:"教官ID" json:"teacher_id"`

	// 学员ID
	StudentID uint32 `struc:"uint32" fieldDesc:"学员ID" json:"student_id"`

	// nono状态 固定值-1
	NonoState uint32 `struc:"uint32" default:"0xFFFFFFFF" fieldDesc:"nono状态 固定值-1" json:"nono_state"`

	// nono颜色 00 FF FF FF
	NonoColor uint32 `struc:"uint32" fieldDesc:"nono颜色 00 FF FF FF" json:"nono_color"`

	// 是不是超能nono 固定值1
	SuperNono uint32 `struc:"uint32" default:"1" fieldDesc:"是不是超能nono 固定值1" json:"super_nono"`

	// 暂时不明给0
	PlayerForm uint32 `struc:"uint32" fieldDesc:"暂时不明给0" json:"player_form"`

	// 暂时不明给0
	TransTime uint32 `struc:"uint32" fieldDesc:"暂时不明给0" json:"trans_time"`

	// 暂时不明给0
	TeamID uint32 `struc:"uint32" fieldDesc:"暂时不明给0" json:"team_id"`

	// 暂时不明给0
	TeamCoreCount uint32 `struc:"uint32" fieldDesc:"暂时不明给0" json:"team_core_count"`

	// 暂时不明给0
	TeamIsShow uint32 `struc:"uint32" fieldDesc:"暂时不明给0" json:"team_is_show"`

	// 暂时不明给0
	LogoBg uint16 `json:"logo_bg"`

	// 暂时不明给0
	LogoIcon uint16 ` json:"logo_icon"`

	// 暂时不明给0
	LogoColor uint16 `json:"logo_color"`

	// 暂时不明给0
	TxtColor uint16 `json:"txt_color"`

	// 4字节
	LogoWord   [4]byte `struc:"[4]byte" fieldDesc:"4字节" json:"logo_word"`
	ClothesLen uint32  `struc:"sizeof=Clothes" fieldDesc:"穿戴装备的信息" json:"clothes_len"`

	// 穿戴装备的信息
	Clothes []model.PeopleItemInfo `fieldDesc:"穿戴装备的信息" json:"clothes"`
}

func NewOutInfo() *OutInfo {
	l := &OutInfo{}

	// 自动填充 struct tag 里的 default 值
	if err := defaults.Set(l); err != nil {
		panic(err) // 方便发现 default 设置错误
	}

	return l
}
