package playroom

import (
	"fmt"
	"math"
	limitedTimeEventCfg "server/conf/limited_time_event"
	playroomCfg "server/conf/playroom"
	"server/game/mod/item"
	"server/game/mod/quest"
	GoUtil "server/game_util"
	"server/msg"
	"sort"
)

type PlayroomMod struct {
	Collect           map[int]int // 装饰
	NewCollect        map[int]*CollectInfo
	Room              map[int]int   // 房间
	Dress             map[int][]int // 服装仓库
	NewDress          map[int]*DressInfo
	DressSet          map[int]int         // 服装穿戴
	PetAir            []int               // 宠物空气背包
	NewPetAir         map[int]*PetAirInfo // 新宠物空气背包
	PetAirSet         int                 // 宠物空气背包穿戴
	Status            int                 // 0: 未拜访 1: 拜访
	Endtime           int64               // 结束时间
	Starttime         int64               // 开始时间
	WorkStatus        int                 // 0: 未开始 1: 进行中 2: 结束
	Visitor           map[int]*Info       // 访客
	MoodInfo          map[int]*Mood       // 心情
	AllMood           int                 // 总心情
	Reward            []*item.Item        // 奖励
	DayFirstT         int                 // 每日未首次触发次数
	Trigger           int                 // 未触发次数
	TriggerTime       int64               // 触发时间
	HasVisit          map[int]int64       // 今日已拜访的玩家
	Target            int                 // 拜访的目标
	GameId            int                 // 游戏ID
	GameReward        map[int]*item.Item  // 游戏奖励
	GameStatus        int                 // 游戏状态
	GameInfo          map[int]interface{} // 游戏信息
	Exclude           bool                // 是否排除
	LoseItem          []*item.Item        // 失去的物品
	ChipList          []*ChipInfo         // 碎片列表
	Flip              map[int]int         // 翻牌
	FlipReward        []*item.Item        // 翻牌奖励
	WorkOutline       int                 // 是否离线
	LastFlip          int                 // 上次翻牌奖励档次
	NoFlip            int                 // 连续未获取最高翻牌奖励次数
	TodayFlip         bool                // 今日是否已获得最高档奖励
	JackpotNum        int                 // 每日转盘数量
	Upvote            int                 // 收到点赞次数
	UpvoteList        []int               // 点赞列表
	RoomPoint         int                 // 房间点数
	UnlockList        map[int]int64       // 解锁
	DailyTask         map[int]*DailyTask  // 每日任务
	DailyTaskReward   []int               // 每日任务奖励
	Physiology        map[int]*Physiology
	InteractNum       int   // 互动次数
	RevengeUid        int64 // 复仇Uid
	FilterVisitor     bool  // 是否过滤访客
	TodayVisitedUsers []int // 今日已拜访过的用户
	ADItem            map[int]*ItemInfo
	WeeklyDiscount    map[int]int // 每周折扣
}

type DressInfo struct {
	Id      int    // 服装ID
	Part    int    // 服装部位
	AddTime int64  // 添加时间
	EndTime int64  // 结束时间
	Label   string // 标签
	Num     int    // 数量
}

type PetAirInfo struct {
	Id      int    // 空气ID
	Part    int    // 空气部位
	AddTime int64  // 添加时间
	EndTime int64  // 结束时间
	Label   string // 标签
	Num     int    // 数量
}

type CollectInfo struct {
	Id      int    // 空气ID
	Part    int    // 空气部位
	AddTime int64  // 添加时间
	EndTime int64  // 结束时间
	Label   string // 标签
	Num     int    // 数量
}

type ItemInfo struct {
	Watch    int   // 观看次数
	LastTime int64 // 上次观看时间
}

type DailyTask struct {
	Items  []*item.Item
	Status int
	Quest  quest.QuestProgress
	UnLock bool
	Index  int
}

const (
	STATUS_IDLE  = 0 // 未开始
	STATUS_VISIT = 1 // 拜访

	MOOD_TYPE_ENTER = 1 // 娱乐
	MOOD_TYPE_CLEAN = 2 // 清洁
	MOOD_TYPE_FOOD  = 3 // 食物

	GAME_RESULT_LOSE   = 0 // 输
	GAME_RESULT_LOW    = 1 // 低
	GAME_RESULT_MIDDLE = 2 // 中
	GAME_RESULT_HIGH   = 3 // 高

	FLIP_TYPE_COPPER = 1 // 铜
	FLIP_TYPE_SILVER = 2 // 银
	FLIP_TYPE_GOLD   = 3 // 金

	PHYSIOLOGY_TYPE_STROKE = 1 // 抚摸
	PHYSIOLOGY_TYPE_PLAY   = 2 // 玩耍
	PHYSIOLOGY_TYPE_FEED   = 3 // 进食
	PHYSIOLOGY_TYPE_CLEAN  = 4 // 清洁
	PHYSIOLOGY_TYPE_TOLIET = 5 // 上厕所

	GAME_TYPE_HOOK = 1 // 愿者上钩
	GAME_TYPE_FILP = 2 // 翻牌
	GAME_TYPE_HIDE = 3 // 捉迷藏

	DAILY_TASK_TYPE_ONE = 1 // 一阶段任务
	DAILY_TASK_TYPE_TWO = 2 // 二阶段任务

	ROOM_POINT_UNLOCK_LV = 6 // 房间点数解锁等级
)

type ChipInfo struct {
	Uid   int
	Time  int64
	Emoji int
}

type Mood struct {
	Id   int
	Num  int
	Time int64
}

type Physiology struct {
	Id   int
	Num  int
	Time int64
}

type Info struct {
	Time  int64
	Times int
}

func (p *PlayroomMod) InitData() {
	if p.Collect == nil {
		p.Collect = make(map[int]int)
	}
	if p.Dress == nil {
		p.Dress = make(map[int][]int)
	}
	if p.DressSet == nil {
		p.DressSet = make(map[int]int)
	}
	if p.GameInfo == nil {
		p.GameInfo = make(map[int]interface{})
	}
	if p.NewCollect == nil {
		p.NewCollect = make(map[int]*CollectInfo)
	}
	InitCollect := playroomCfg.GetInitDecorate()
	if len(p.NewCollect) == 0 {
		for _, v := range InitCollect {
			p.NewCollect[v] = &CollectInfo{
				Id:      v,
				AddTime: GoUtil.Now(),
				Num:     1,
			}
		}
	}
	if len(p.Collect) > 0 {
		for k, v := range p.Collect {
			p.NewCollect[k] = &CollectInfo{
				Id:      k,
				AddTime: GoUtil.Now(),
				Num:     v,
			}
		}
		p.Collect = make(map[int]int)
	}
	for _, v := range InitCollect {
		p.Collect[v] = 1
	}
	if p.Room == nil {
		p.Room = make(map[int]int)
		p.JackpotNum = playroomCfg.GetJackpotNum()
	}
	if p.Visitor == nil {
		p.Visitor = make(map[int]*Info)
	}
	if p.MoodInfo == nil {
		p.MoodInfo = make(map[int]*Mood)
	}
	if p.Physiology == nil {
		p.Physiology = make(map[int]*Physiology)
	}
	if p.HasVisit == nil {
		p.HasVisit = make(map[int]int64)
	}
	if p.GameReward == nil {
		p.GameReward = make(map[int]*item.Item)
	}
	if p.Flip == nil {
		p.Flip = make(map[int]int)
	}
	if p.UnlockList == nil {
		p.UnlockList = make(map[int]int64)
	}
	if p.DailyTask == nil {
		p.DailyTask = make(map[int]*DailyTask)
	}
	if len(p.NewPetAir) == 0 {
		p.NewPetAir = make(map[int]*PetAirInfo)
		InitPetAir := playroomCfg.GetInitAirList()
		for _, v := range InitPetAir {
			p.NewPetAir[v] = &PetAirInfo{
				Id:      v,
				AddTime: GoUtil.Now(),
				Num:     1,
			}
		}
	}

	if len(p.PetAir) > 0 {
		for _, v := range p.PetAir {
			p.NewPetAir[v] = &PetAirInfo{
				Id:      v,
				AddTime: GoUtil.Now(),
				Num:     1,
			}
		}
		p.PetAir = nil
	}
	if p.NewDress == nil {
		p.NewDress = make(map[int]*DressInfo)
	}
	if len(p.NewDress) == 0 {
		InitDressList := playroomCfg.GetInitDressList()
		for _, v := range InitDressList {
			Part := playroomCfg.GetDressPart(v)
			p.NewDress[v] = &DressInfo{
				Id:      v,
				Part:    Part,
				AddTime: GoUtil.Now(),
				Num:     1,
			}
		}
	}
	// Dress仓库重构
	if len(p.Dress) != 0 {
		for _, v := range p.Dress {
			for _, id := range v {
				Part := playroomCfg.GetDressPart(id)
				p.NewDress[id] = &DressInfo{
					Id:      id,
					Part:    Part,
					AddTime: GoUtil.Now(),
					Num:     1,
				}
			}
		}
		p.Dress = nil
	}
	if p.ADItem == nil {
		p.ADItem = make(map[int]*ItemInfo)
	}
	if p.WeeklyDiscount == nil {
		p.WeeklyDiscount = make(map[int]int)
	}
}

func (p *PlayroomMod) ZeroUpdate() {
	p.TodayFlip = false
	p.LastFlip = 0
	p.JackpotNum = playroomCfg.GetJackpotNum()
	p.UpvoteList = nil
	p.DailyTaskReward = nil
	p.TodayVisitedUsers = nil
	p.ADItem = make(map[int]*ItemInfo)
	p.InitDailyTask()
}

func (p *PlayroomMod) InitDailyTask() {
	p.DailyTask = make(map[int]*DailyTask)
	Index := 1
	TaskList1 := playroomCfg.GetDailyTask(DAILY_TASK_TYPE_ONE)
	for k, v := range TaskList1 {
		Items := playroomCfg.GetDailyTaskReward(Index)
		Quest, _ := quest.ParseQuest(v)
		p.DailyTask[k] = &DailyTask{
			Items:  Items,
			Quest:  Quest,
			UnLock: true,
			Index:  Index,
		}
		Index++
	}
	TaskList2 := playroomCfg.GetDailyTask(DAILY_TASK_TYPE_TWO)
	for k, v := range TaskList2 {
		Items := playroomCfg.GetDailyTaskReward(Index)
		Quest, _ := quest.ParseQuest(v)
		p.DailyTask[k] = &DailyTask{
			Items:  Items,
			Quest:  Quest,
			UnLock: false,
			Index:  Index,
		}
		Index++
	}
}

func (p *PlayroomMod) QuestTrigger(Tr *quest.Trigger) bool {
	update := false
	unlock := true
	for k, v := range p.DailyTask {
		if !v.UnLock {
			continue
		}
		if v.Status != quest.QUEST_STATUS_UNFINISH {
			continue
		}
		update = quest.TriggerQuestProgress(&v.Quest, Tr) || update

		if v.Quest.Status {
			v.Status = quest.QUEST_STATUS_FINISH

		}
		Type := playroomCfg.GetDailyTaskType(k)
		if Type == DAILY_TASK_TYPE_ONE && v.Status == quest.QUEST_STATUS_UNFINISH {
			unlock = false
		}
	}
	if unlock {
		for _, v := range p.DailyTask {
			v.UnLock = true
		}
	}
	return update
}

func (p *PlayroomMod) DailyTaskCanReward(Id int) bool {
	IdList := playroomCfg.GetDailyTaskListById(Id)
	for _, v := range IdList {
		v, ok := p.DailyTask[v]
		if !ok {
			return false
		}
		if v.Status != quest.QUEST_STATUS_FINISH {
			return false
		}
	}
	return true
}

func (p *PlayroomMod) GetDailyTaskReward(Id int) ([]*item.Item, error) {
	v, ok := p.DailyTask[Id]
	if !ok {
		return nil, fmt.Errorf("GetDailyTaskReward Id is not ok")
	}
	if v.Status != quest.QUEST_STATUS_FINISH {
		return nil, fmt.Errorf("GetDailyTaskReward Status is not finish")
	}
	v.Status = quest.QUEST_STATUS_REWARD
	return v.Items, nil
}

func (p *PlayroomMod) GetVisitor() map[int]*Info {
	return p.Visitor
}

func (p *PlayroomMod) GetTarget() int {
	return p.Target
}

func (p *PlayroomMod) GetHasVisit() map[int]int64 {
	return p.HasVisit
}

func (p *PlayroomMod) GetTodayVisitedUsers() []int {
	return p.TodayVisitedUsers
}

func (p *PlayroomMod) GetMood() map[int]int {
	Mood := make(map[int]int)
	for k, v := range p.MoodInfo {
		Mood[k] = v.Num
	}
	return Mood
}

func (p *PlayroomMod) GetPhysiologyList() map[int]int {
	Physiology := make(map[int]int)
	for k, v := range p.Physiology {
		Physiology[k] = v.Num
	}
	return Physiology
}

func (p *PlayroomMod) GetMoodInfo(Id int) *Mood {
	return p.MoodInfo[Id]
}

func (p *PlayroomMod) GetPhysiology(Id int) *Physiology {
	return p.Physiology[Id]
}

func (p *PlayroomMod) GetCollect() map[int]*CollectInfo {
	return p.NewCollect
}

func (p *PlayroomMod) GetRoom() map[int]int {
	return p.Room
}

func (p *PlayroomMod) GetStatus() int {
	return p.Status
}

func (p *PlayroomMod) GetChip() int {
	return len(p.ChipList)
}

func (p *PlayroomMod) AddChip(Uid int, Time int64, Emoji int) {
	if len(p.ChipList) >= playroomCfg.GetChipNum() {
		return
	}
	p.ChipList = append(p.ChipList, &ChipInfo{Uid: Uid, Time: Time, Emoji: Emoji})
	p.RevengeUid = int64(Uid)
}

func (p *PlayroomMod) SetTarget(Target int) {
	p.Target = Target
	p.Status = 1
	p.HasVisit[Target] = GoUtil.Now()
}

func (p *PlayroomMod) SetGameId(GameId int) {
	p.GameId = GameId
}

func (p *PlayroomMod) CreateOrderReward(Star int, itemMod *item.ItemMod) {
	if Star == 0 {
		return
	}
	FoodItem := playroomCfg.GetFoodItem()
	CleanItem := playroomCfg.GetCleanItem()
	ToyItem := playroomCfg.GetToyItem()
	DailyItem := playroomCfg.GetDailyItem()

	FoodItemNum := itemMod.GetItemNumByList(FoodItem)
	CleanItemNum := itemMod.GetItemNumByList(CleanItem)
	ToyItemNum := itemMod.GetItemNumByList(ToyItem)
	DailyItemNum := itemMod.GetItemNumByList(DailyItem)
	type d struct {
		Id  []int
		Num int
	}
	sortList := []d{
		{Id: FoodItem, Num: FoodItemNum},
		{Id: CleanItem, Num: CleanItemNum},
		{Id: ToyItem, Num: ToyItemNum},
		{Id: DailyItem, Num: DailyItemNum},
	}
	sort.Slice(sortList, func(i, j int) bool {
		return sortList[i].Num < sortList[j].Num
	})

	Prob := GoUtil.RandSlice(sortList[0].Id)
	p.Reward = []*item.Item{{Id: Prob, Num: 1}}
}

func (p *PlayroomMod) GetReward() []*item.Item {
	return p.Reward
}

func (p *PlayroomMod) Interact(Id, Type int) ([]*item.Item, int, error) {
	MoodType, ItemList, Effect := playroomCfg.GetInteract(Id, Type)
	if MoodType == 0 {
		return nil, 0, fmt.Errorf("Interact MoodType is 0")
	}
	if Effect > 0 {
		p.AllMood = min(100, p.AllMood+10)
	}
	PType, PEffect := playroomCfg.GetInteractPhysiology(Id)
	p.AddPhysiology(PType, PEffect)
	p.AddMood(MoodType, Effect)
	return ItemList, PType, nil
}

func (p *PlayroomMod) AddInteractNum(Lv int) {
	Unlock := playroomCfg.GetInteractUnlock()
	if Lv < Unlock {
		return
	}
	p.InteractNum++
	p.InteractNum = min(p.InteractNum, playroomCfg.GetInteractNum())
}

func (p *PlayroomMod) AddMood(Id, Num int) {
	_, ok := p.MoodInfo[Id]
	if !ok {
		p.MoodInfo[Id] = &Mood{Id: Id}
	}
	p.MoodInfo[Id].Num = max(0, min(p.MoodInfo[Id].Num+Num, 100))
	if p.MoodInfo[Id].Num != 0 && p.MoodInfo[Id].Time == 0 {
		p.MoodInfo[Id].Time = GoUtil.Now()
	}
	if p.MoodInfo[Id].Num == 0 {
		p.MoodInfo[Id].Time = 0
	}
}

func (p *PlayroomMod) GetMoodNum(MoodType int) int {
	Mood, ok := p.MoodInfo[MoodType]
	if !ok {
		return 0
	}
	return Mood.Num
}

func (p *PlayroomMod) AddPhysiology(Id, Num int) {
	Phy := p.GetPhysiology(Id)
	if Phy == nil {
		Phy = &Physiology{Id: Id}
		p.Physiology[Id] = Phy
	}
	Max := playroomCfg.GetPhysiologyMax(Id)
	Phy.Num = max(0, min(Phy.Num+Num, Max))
	Phy.Time = GoUtil.Now()
	if Phy.Num == 0 {
		Phy.Time = 0
	}
}

func (p *PlayroomMod) AddVisitor(Id int, Time int64) {
	v, ok := p.Visitor[Id]
	if !ok {
		p.Visitor[Id] = &Info{Time: Time, Times: 1}
		return
	}
	v.Times++
	v.Time = Time
}

func (p *PlayroomMod) SetRoom(Room map[int]int) (map[int]int, error) {
	diff := GoUtil.DiffMap(p.Room, Room)
	p.Room = Room
	return diff, nil
}

func (p *PlayroomMod) AddCollect(Id int, Label string) {
	p.NewCollect[Id] = &CollectInfo{
		Id:      Id,
		AddTime: GoUtil.Now(),
		Label:   Label,
	}
}

func (p *PlayroomMod) AddDress(Id int, Label string) {
	Part := playroomCfg.GetDressPart(Id)
	if _, ok := p.NewDress[Id]; !ok {
		p.NewDress[Id] = &DressInfo{
			Id:      Id,
			Part:    Part,
			AddTime: GoUtil.Now(),
			Label:   Label,
			Num:     1,
		}
	} else {
		p.NewDress[Id].Num++
	}
}

func (p *PlayroomMod) ResetGame() {
	p.TodayVisitedUsers = append(p.TodayVisitedUsers, p.Target)
	p.Target = 0
	p.Status = STATUS_IDLE
	p.GameId = 0
	p.GameReward = make(map[int]*item.Item)
	p.InteractNum = 0
	p.RevengeUid = 0
}
func (p *PlayroomMod) GetGameId() int {
	return p.GameId
}

func (p *PlayroomMod) ResetLose() {
	p.LoseItem = nil
}

func (p *PlayroomMod) SetGameReward(Chess1, Chess2, Star int) {
	p.GameReward[1] = &item.Item{Id: Chess1, Num: 1}
	p.GameReward[2] = &item.Item{Id: Chess2, Num: 1}
	p.GameReward[3] = &item.Item{Id: item.ITEM_STAR_ID, Num: Star}
}
func (p *PlayroomMod) SetGameReward2(Chess1, Star int) {
	p.GameReward[1] = &item.Item{Id: Chess1, Num: 1}
	p.GameReward[2] = &item.Item{Id: item.ITEM_STAR_ID, Num: Star}
	p.GameReward[3] = &item.Item{Id: item.ITEM_STAR_ID, Num: Star}
}
func (p *PlayroomMod) SetGameReward3(Star int) {
	p.GameReward[1] = &item.Item{Id: item.ITEM_STAR_ID, Num: Star}
	p.GameReward[2] = &item.Item{Id: item.ITEM_STAR_ID, Num: Star}
	p.GameReward[3] = &item.Item{Id: item.ITEM_STAR_ID, Num: Star}
}

func (p *PlayroomMod) SetGameRewardFlip(N1, N2, N3 int) {
	p.GameReward[1] = &item.Item{Id: item.ITEM_STAR_ID, Num: N1}
	p.GameReward[2] = &item.Item{Id: item.ITEM_STAR_ID, Num: N2}
	p.GameReward[3] = &item.Item{Id: item.ITEM_STAR_ID, Num: N3}
}

func (p *PlayroomMod) SelectReward(Id int) []*item.Item {
	v, ok := p.GameReward[Id]
	if !ok {
		return nil
	}
	var Items []*item.Item
	Items = append(Items, v)
	if Id < 3 {
		Items = append(Items, item.NewItem(item.ITEM_STAR_ID, 5))
	}
	return Items
}

func (p *PlayroomMod) Lose(Item []*item.Item) {
	p.LoseItem = append(p.LoseItem, Item...)
}

func (p *PlayroomMod) Work() ([]*item.Item, error) {
	if p.Endtime > GoUtil.Now() {
		p.WorkStatus = 1
		return nil, nil
	}
	p.Starttime = GoUtil.Now()
	p.Endtime = GoUtil.Now() + 86400
	p.WorkStatus = 1
	ItemId := playroomCfg.GetWorkItem()
	return []*item.Item{item.NewItem(ItemId, 1)}, nil
}

func (p *PlayroomMod) Rest() {
	p.WorkStatus = 2
}

func (p *PlayroomMod) SetWorkOutline(Status int) {
	p.WorkOutline = Status
}

func (p *PlayroomMod) ResetWork() {
	p.WorkStatus = 0
	p.Endtime = 0
}

func (p *PlayroomMod) Outline() {
	p.WorkOutline = 1
}

func (p *PlayroomMod) GetVisitorInfo(Id int) (int, int64) {
	v, ok := p.Visitor[Id]
	if !ok {
		return 0, 0
	}
	return v.Times, v.Time
}

func (p *PlayroomMod) GetTaskReward(Type int) (int, []*item.Item, error) {
	if GoUtil.InArray(Type, p.DailyTaskReward) {
		return 0, nil, fmt.Errorf("GetTaskReward Type is already in DailyTaskReward")
	}
	finish := 0
	for _, v := range p.DailyTask {
		if v.Status >= quest.QUEST_STATUS_FINISH {
			finish++
		}
	}
	if Type == DAILY_TASK_TYPE_ONE && finish < playroomCfg.GetPlayroomTaskDailyNum1() {
		return 0, nil, fmt.Errorf("GetTaskReward Type is DAILY_TASK_TYPE_ONE but finish is %d", finish)
	}
	if Type == DAILY_TASK_TYPE_TWO && finish < playroomCfg.GetPlayroomTaskDailyNum1()+playroomCfg.GetPlayroomTaskDailyNum2() {
		return 0, nil, fmt.Errorf("GetTaskReward Type is DAILY_TASK_TYPE_TWO but finish is %d", finish)
	}
	p.DailyTaskReward = append(p.DailyTaskReward, Type)
	Id := 0
	var Items []*item.Item
	if Type == DAILY_TASK_TYPE_TWO {
		ProbList := limitedTimeEventCfg.GetSenceJackpotProb()
		Id = GoUtil.RandMap(ProbList)
		Items = limitedTimeEventCfg.GetSenceJackpotReward(Id)
	} else {
		ProbList := playroomCfg.GetTaskJackpotProb()
		Id = GoUtil.RandMap(ProbList)
		Items = playroomCfg.GetTaskJackpotReward(Id)
	}
	if len(Items) > 1 {
		// 多个奖励时，随机选择一个
		Items = []*item.Item{GoUtil.RandItem(Items)}
	}
	return Id, Items, nil
}

func (p *PlayroomMod) Draw() (int, []*item.Item, error) {
	// if p.AllMood < 100 {
	// 	return 0, nil, fmt.Errorf("Draw AllMood < 100")
	// }
	if p.JackpotNum == 0 {
		return 0, nil, fmt.Errorf("Draw JackpotNum is 0")
	}
	p.JackpotNum--
	p.AllMood = 0
	ProbList := limitedTimeEventCfg.GetSenceJackpotProb()
	Id := GoUtil.RandMap(ProbList)
	Items := limitedTimeEventCfg.GetSenceJackpotReward(Id)
	if len(Items) > 1 {
		// 多个奖励时，随机选择一个
		Items = []*item.Item{GoUtil.RandItem(Items)}
	}
	return Id, Items, nil
}

func (p *PlayroomMod) NotifyWork() *msg.NotifyPlayroomWork {
	return &msg.NotifyPlayroomWork{
		WorkStatus: int32(p.WorkStatus),
		StartTime:  int32(p.Starttime),
	}
}

func (p *PlayroomMod) NotifyLose() *msg.NotifyPlayroomLose {
	ChipMessage := make([]*msg.ChipInfo, 0, len(p.ChipList))
	for _, v := range p.ChipList {
		ChipMessage = append(ChipMessage, &msg.ChipInfo{
			Uid: int64(v.Uid),
		})
	}
	return &msg.NotifyPlayroomLose{
		LoseItem: item.ItemToMsg(p.LoseItem),
		Chip:     ChipMessage,
		Revenge:  p.RevengeUid,
	}
}
func (p *PlayroomMod) ResetPhysiology(MoodType int) {
	PhysiologyList := playroomCfg.GetPhysiologyList(MoodType)
	for _, v := range PhysiologyList {
		Phy := p.GetPhysiology(v)
		if Phy != nil {
			Phy.Num = 0
			Phy.Time = 0
		}
	}
}
func (p *PlayroomMod) NotifyStatus() *msg.NofiPlayroomStatus {
	return &msg.NofiPlayroomStatus{
		WorkOutline: int32(p.WorkOutline),
	}
}

func (p *PlayroomMod) NotifyMood() *msg.NotifyPlayroomMood {
	Mood := make(map[int32]int32)
	for k, v := range p.MoodInfo {
		Mood[int32(k)] = int32(v.Num)
	}
	var resAdItems []*msg.AdItem
	for k, v := range p.ADItem {
		resAdItems = append(resAdItems, &msg.AdItem{
			ItemId:    int32(k),
			Watch:     int32(v.Watch),
			LastWatch: int32(v.LastTime),
		})
	}
	return &msg.NotifyPlayroomMood{
		AllMood:    int32(p.AllMood),
		Mood:       Mood,
		Physiology: GoUtil.MapIntToInt32(p.GetPhysiologyList()),
		AdItem:     resAdItems,
	}
}

func (p *PlayroomMod) Fire(ChargeId int) []*item.Item {
	WorkChargeId := playroomCfg.GetWorkChargeId()
	if ChargeId == WorkChargeId {
		ItemId := playroomCfg.GetWorkItem()
		return []*item.Item{item.NewItem(ItemId, 1)}
	}
	return nil
}

func (p *PlayroomMod) RemoveChip(Uids []int64) ([]*item.Item, int, error) {
	len1 := len(p.ChipList)
	len2 := len(Uids)
	if len1 == 0 {
		return nil, 0, fmt.Errorf("RemoveChip Uids is 0")
	}
	if len1 == len2 {
		p.ChipList = nil
	} else {
		uidCount := make(map[int64]int)
		for _, uid := range Uids {
			uidCount[uid]++
		}

		var newChipList []*ChipInfo
		for _, chip := range p.ChipList {
			if uidCount[int64(chip.Uid)] > 0 {
				uidCount[int64(chip.Uid)]--
			} else {
				newChipList = append(newChipList, chip)
			}
		}
		p.ChipList = newChipList
	}
	return []*item.Item{item.NewItem(item.ITEM_STAR_ID, len2*25)}, len2, nil
}

func (p *PlayroomMod) FlipCard(Pos int) (int, error) {
	if p.Status != STATUS_VISIT {
		return 0, fmt.Errorf("FlipCard Status is not STATUS_VISIT")
	}
	RandMap := map[int]int{
		FLIP_TYPE_COPPER: 35,
		FLIP_TYPE_SILVER: 45,
		FLIP_TYPE_GOLD:   20,
	}
	Prob := GoUtil.RandMap(RandMap)

	/**
	若玩家同一天内上一次游玩猫猫小金库未能获得金币档位奖励，且当天还未获得过金币档位奖励
	或玩家已连续三次未能获得金币档位奖励，则启用以下保底逻辑
	玩家已翻出两个银币或铜币图案的情况下，后续翻牌必然为金币
	*/
	check := make(map[int]int)
	for _, v := range p.Flip {
		check[v]++
	}
	if check[FLIP_TYPE_COPPER] == 2 || check[FLIP_TYPE_SILVER] == 2 {
		if p.LastFlip != FLIP_TYPE_GOLD && !p.TodayFlip {
			Prob = FLIP_TYPE_GOLD
		}
		if p.NoFlip == 3 {
			Prob = FLIP_TYPE_GOLD
		}
	}
	p.Flip[Pos] = Prob

	return Prob, nil
}

func (p *PlayroomMod) GetFlipReward() ([]*item.Item, int, int, error) {
	check := make(map[int]int)
	var Items []*item.Item
	T := p.Target
	Result := FLIP_TYPE_COPPER
	for _, v := range p.Flip {
		check[v]++
		if check[v] == 3 {
			switch v {
			case FLIP_TYPE_COPPER:
				p.NoFlip++
				Items = append(Items, p.GameReward[FLIP_TYPE_COPPER])
			case FLIP_TYPE_SILVER:
				p.NoFlip++
				Result = FLIP_TYPE_SILVER
				Items = append(Items, p.GameReward[FLIP_TYPE_SILVER])
			case FLIP_TYPE_GOLD:
				p.NoFlip = 0
				p.TodayFlip = true
				Result = FLIP_TYPE_GOLD
				Items = append(Items, p.GameReward[FLIP_TYPE_GOLD])
			}
			p.LastFlip = v
			p.Flip = make(map[int]int)
			p.ResetGame()
			return Items, T, Result, nil
		}
	}

	return Items, T, Result, fmt.Errorf("GetFlipReward check is not 3")
}

func (p *PlayroomMod) BuyItem(Id int) ([]*item.Item, []*item.Item) {
	return playroomCfg.GetBuyItem(Id)
}

func (p *PlayroomMod) UnLock(Lv int) bool {
	UnlockLv := playroomCfg.GetUnLockLv()
	if Lv < UnlockLv || len(p.Physiology) != 0 {
		return false
	}
	Now := GoUtil.Now()
	p.Physiology = make(map[int]*Physiology)
	TypeList := playroomCfg.GetPhysiologyTypeList()
	for _, v := range TypeList {
		Max := playroomCfg.GetPhysiologyMax(v)
		p.Physiology[v] = &Physiology{Id: v, Num: Max, Time: Now}
	}
	if len(p.MoodInfo) == 0 {
		p.MoodInfo = make(map[int]*Mood)
		for k := 1; k <= 3; k++ {
			p.MoodInfo[k] = &Mood{Id: k, Num: 100}
		}
	}

	return true
}

// shop
func (p *PlayroomMod) ShopBuy(Id, Num int, WeeklyDiscount bool) ([]*item.Item, []*item.Item, error) {
	AddItemId, CostItem, Discount, Limit := playroomCfg.GetShopItem(Id)
	if AddItemId == 0 {
		return nil, nil, fmt.Errorf("ShopBuy AddItemId is 0")
	}
	NewCostItem := CostItem[0].Num * Num
	if WeeklyDiscount {
		LimitNum := p.WeeklyDiscount[Id]
		if LimitNum < Limit {
			NewCostItem = int(math.Ceil(float64(NewCostItem) * float64(Discount) / 100))
		}
		p.WeeklyDiscount[Id] = LimitNum + Num
	}
	CostItem[0].Num = NewCostItem
	return []*item.Item{item.NewItem(AddItemId, Num)}, CostItem, nil
}

func (p *PlayroomMod) UnlockDress(Type, Id int) error {
	p.NewDress[Id] = &DressInfo{
		Id:      Id,
		Part:    Type,
		AddTime: GoUtil.Now(),
		Num:     1,
	}
	return nil
}

func (p *PlayroomMod) RandGameType() int {
	return GoUtil.RandMap(map[int]int{1: 50, 3: 50})
}

func (p *PlayroomMod) UnlockPetAir(Id int) {
	p.NewPetAir[Id] = &PetAirInfo{
		Id:      Id,
		AddTime: GoUtil.Now(),
		Num:     1,
	}
}

func (p *PlayroomMod) PlayroomDressSet(DressSet map[int]int) ([]int, map[int]int, error) {
	// 判断服装是否存在
	var Part []int
	Diff := GoUtil.DiffMap(DressSet, p.DressSet)
	for Type, Id := range DressSet {
		if Id == 0 {
			continue
		}
		dressInfo, ok := p.NewDress[Id]
		if !ok {
			return nil, nil, fmt.Errorf("dress type not found")
		}
		if dressInfo.EndTime < GoUtil.Now() && dressInfo.EndTime != 0 {
			return nil, nil, fmt.Errorf("dress timeout")
		}
		if p.DressSet[Type] != Id && Id != 0 {
			Part = append(Part, Type)
		}
	}
	p.DressSet = DressSet
	return Part, Diff, nil
}

func (p *PlayroomMod) GiveUpvote(Uid int) ([]*item.Item, error) {
	if GoUtil.InArray(Uid, p.UpvoteList) {
		return nil, fmt.Errorf("upvote already")
	}
	p.UpvoteList = append(p.UpvoteList, Uid)
	return []*item.Item{item.NewItem(item.ITEM_ENERGY_ID, 5)}, nil
}

func (p *PlayroomMod) AddUpvote() {
	p.Upvote++
}

func (p *PlayroomMod) PlayroomPetAirSet(Id int) error {
	if _, ok := p.NewPetAir[Id]; !ok {
		return fmt.Errorf("PlayroomPetAirSet Id is not ok")
	}
	p.PetAirSet = Id
	return nil
}

func (p *PlayroomMod) Unlock(Id int) error {
	Need := playroomCfg.GetUnlockNeed(Id)
	if Need == 0 || Need > p.RoomPoint {
		return fmt.Errorf("unlock need is 0 or need > RoomPoint")
	}
	p.UnlockList[Id] = GoUtil.Now()
	return nil
}

func (p *PlayroomMod) GetUnlockIds() []int32 {
	UnlockIds := make([]int32, 0, len(p.UnlockList))
	for k := range p.UnlockList {
		UnlockIds = append(UnlockIds, int32(k))
	}
	return UnlockIds
}

func (p *PlayroomMod) GetDressSet() map[int]int {
	return p.DressSet
}

func (p *PlayroomMod) GetPetAirSet() int {
	return p.PetAirSet
}

func (p *PlayroomMod) GetDress() map[int]*DressInfo {
	return p.NewDress
}

func (p *PlayroomMod) GetPetAir() map[int]*PetAirInfo {
	return p.NewPetAir
}

func (p *PlayroomMod) BackDataTask() []*msg.DailyTask {
	DailyTask := make([]*msg.DailyTask, 0, len(p.DailyTask))
	for k, v := range p.DailyTask {
		DailyTask = append(DailyTask, &msg.DailyTask{
			Status:   int32(v.Status),
			UnLock:   v.UnLock,
			Progress: quest.QuestProgressToMsg(&v.Quest),
			Items:    item.ItemToMsg(v.Items),
			Index:    int32(v.Index),
			Id:       int32(k),
		})
	}
	sort.Slice(DailyTask, func(i, j int) bool {
		return DailyTask[i].Index < DailyTask[j].Index
	})
	return DailyTask
}

func (p *PlayroomMod) Guide(Type int) error {
	if _, ok := p.Physiology[Type]; !ok {
		return fmt.Errorf("Guide Type is not ok")
	}
	p.Physiology[Type].Num = 0
	return nil
}

func (p *PlayroomMod) AdWatch(Id int) error {
	if _, ok := p.ADItem[Id]; !ok {
		p.ADItem[Id] = &ItemInfo{}
	}
	p.ADItem[Id].Watch++
	p.ADItem[Id].LastTime = GoUtil.Now()
	if p.ADItem[Id].Watch > playroomCfg.GetShopItemAdNum(Id) {
		return fmt.Errorf("AdWatch Watch is over limit")
	}
	return nil
}

func (p *PlayroomMod) ResetWeeklyDiscount() {
	p.WeeklyDiscount = make(map[int]int)
}
