package fishing

import (
	"math/rand"
	"mongo.games.com/game/gamesrv/base"
	"mongo.games.com/game/srvdata"
	"sync"
	"time"
)

// FishArray 鱼阵
type FishArray struct {
	Type     uint32  //鱼阵类型
	Speed    uint32  //鱼阵速度
	Duration uint32  //持续时间
	Fishs    []*Fish //鱼阵中鱼

	//Actions  []*FishArrayAction //鱼阵动作
}

// AppearFish 出鱼
type AppearFish struct {
	id  uint64 //出鱼编号
	aid uint32 //鱼阵编号
	//mutex       sync.Mutex  //编号同步
	start       bool        //是否出鱼
	pause       int64       //暂停时间
	resumeTimer *time.Timer //恢复定时器
	SceneEx     *FishingSceneData
	appearFishs map[int32]*AppearFishConfig //出鱼策略
	fishPath    map[int32]*FishPath         //出鱼路径配置
	mutex       sync.Mutex                  //编号同步
}

type FishPath struct {
	PathId        int32
	AppearTime    int32
	DisappearTime int32
}

type AppearFishConfig struct {
	fishId    int32   //对应fish表中的fishType
	name      string  //鱼的名字
	exp       int32   //经验值
	multiple  []int32 //倍数
	prob      float64 //死亡概率 目前不用 看后期设计 每个场次单独控制 还是整体控制
	baseRates float64 //基础概率 目前不用
	path      []int32 //出鱼路径
	fishNum   []int32 //出鱼数量
	interval  int32   //出鱼间隔

}

// Start 开始
func (a *AppearFish) Start() {
	fishlogger.Trace("newFish 开始出鱼！！！！！！！！！！！！")
	a.aid = FishArrayOne //鱼阵起始标记
	a.start = true
	//最短间隔
	minInterval := int32(100000)
	for _, v := range base.FishOutEx.FishOutPool {
		if a.SceneEx.GetDBGameFree().GetSceneType() == v.SceneType && v.Interval < minInterval {
			minInterval = v.Interval
		}
	}

	//间隔差值 开始出鱼时候出鱼比较慢 让玩家早点看到屏幕鱼
	var diffInterval int32
	if minInterval > 1000 {
		diffInterval = minInterval - 1000
	}

	//遍历出鱼
	for _, v := range base.FishOutEx.FishOutPool {
		if a.SceneEx.GetDBGameFree().GetSceneType() == v.SceneType {
			tmp := v
			//定时出鱼
			time.AfterFunc(time.Duration(tmp.Interval-diffInterval)*time.Millisecond, func() {
				a.do(tmp)
			})
		}
	}
	/*	//定时鱼阵
		time.AfterFunc(time.Duration(FishArrayInterval)*time.Millisecond, func() {
			a.doArray()
		})*/

	//定时切换场景
	time.AfterFunc(FishArrayInterval, func() {
		a.cleanData()
	})
}

// Stop 停止
func (a *AppearFish) Stop() {
	a.start = false
}

// Pause 暂停
func (a *AppearFish) Pause(t int64) {
	//暂停时间
	a.pause = time.Now().Unix()
	a.pause += (t / 1000)

	//定时暂停
	if a.resumeTimer != nil {
		a.resumeTimer.Stop()
	}
	a.resumeTimer = time.AfterFunc(time.Duration(t)*time.Millisecond, func() {
		a.resume()
	})
}

// resume 恢复
func (a *AppearFish) resume() {
	a.pause = 0
	fishlogger.Trace("暂停结束，恢复出鱼！")
}

// do 执行
func (a *AppearFish) do(afc *base.AppearFish) {
	if !a.start {
		return
	}
	startTime := time.Now().UnixNano() / int64(time.Millisecond)
	//定时出鱼
	if a.pause != 0 {
		//不能出就不出不延迟至鱼阵结束
		time.AfterFunc(time.Duration(afc.Interval)*time.Millisecond, func() {
			a.do(afc)
		})

		return
	}

	//出鱼数量
	quantity := afc.FishNum[0]
	if afc.FishNum[0] != afc.FishNum[1] {
		//随机出鱼数量
		quantity += rand.Int31n(int32(afc.FishNum[1] - afc.FishNum[0] + 1))
	}
	//创建出鱼切片
	fishs := make([]*Fish, 0, quantity)

	for i := 0; i < int(quantity); i++ {
		//遍历鱼类
		v := afc.FishId

		//获取鱼的配置
		//conf := a.fishConfig[afc.fishId]
		conf := base.FishTemplateEx.FishPool[afc.FishId]
		if conf == nil {
			fishlogger.Errorf("出鱼 没有找到鱼的配置！！！！fishId = %v", afc.FishId)
			continue
		}

		//出鱼路径 出多条一样的鱼 路径尽量不重复
		pathTime := time.Now().UnixNano() / int64(time.Millisecond)
		path := afc.Path[0]
		var num = 0
		for {
			num++
			if afc.Path[0] != afc.Path[1] {
				path += rand.Int31n(int32(afc.Path[1] - afc.Path[0] + 1))
			}

			if a.PathUsable(path, fishs) && a.SceneEx.PathUsable(path) {
				break
			}

			path = afc.Path[0]
		}
		fishlogger.Tracef("寻找路径耗时：%v,循环了多少次：%v", time.Now().UnixNano()/int64(time.Millisecond)-pathTime, num)
		//创建出鱼
		fish := new(Fish)

		//设置属性
		fish.TemplateID = v
		fish.Path = path
		fish.Exp = conf.EXP
		//fish.SetrAppea(afc.FishAppearType)

		//计算倍数  待确认怎么随机
		//策划让直接用鱼谱里的GOLD值
		multiple := conf.Gold[0]
		if conf.Gold[0] != conf.Gold[1] {
			multiple += rand.Int31n(conf.Gold[1] - conf.Gold[0] + 1)
		}

		//设置属性
		fish.DropCoin = multiple
		//这个参数是用于财神鱼  要不要待定
		fish.MaxDropCoin = conf.Gold[1]
		fish.Speed = conf.Speed
		fish.Rate = conf.Rate
		fish.Name = conf.Name
		//设置出鱼编号
		fish.FishID = int32(a.GetFishID())
		fish.Event = afc.Event
		//不指定能打死自己的玩家
		//fish.SetPlayer(InvalidPlayer)
		fishlogger.Infof("newfish 出鱼 fish = %v", fish)
		//加入切片
		fishs = append(fishs, fish)
	}
	//桌子增加鱼
	a.SceneEx.AddFish(fishs, 0)
	fishlogger.Trace("出鱼耗时：", time.Now().UnixNano()/int64(time.Millisecond)-startTime)
	//定时出鱼
	time.AfterFunc(time.Duration(afc.Interval)*time.Millisecond, func() {
		a.do(afc)
	})
	//通知客户端出鱼
	a.SceneEx.NotifyAppearFish(fishs)

}

func (a *AppearFish) doPreArray() {
	if !a.start {
		return
	}
	//通知客户端 鱼潮来临
	//a.pfacb()
}

// 鱼阵 doArray 执行
func (a *AppearFish) doArray() {
	/*
		if !a.start {
			return
		}

		//定时鱼阵
		if a.pause != 0 {
			time.AfterFunc(time.Duration(a.GetPauseTime())*time.Second, func() {
				a.doArray()
			})

			return
		}

		//最大持续时间
		var maxDuration uint32

		//创建鱼阵切片
		var fishArrays []FishArray

		//子鱼阵编号
		ids := CMIns().FishArrayConf[a.aid-1]
		a.aid = a.aid%FishArraySeven + 1

		//遍历子鱼阵
		for _, v := range ids {
			//创建鱼阵
			var fishArray FishArray

			//获取鱼阵配置
			fishArrayConfig := CMIns().GetFishArrayConfig(v)

			//遍历鱼阵组
			for _, i := range fishArrayConfig.FishArrayGroups {
				//获取鱼类配置
				conf := CMIns().GetFishConfig(i.FishType)
				if conf == nil {
					continue
				}

				//遍历鱼阵鱼
				for _, j := range i.FishArrayFishs {
					//创建出鱼
					fish := new(Fish)

					//计算倍数
					multiple := conf.FishMinMultiple
					if conf.FishMinMultiple != conf.FishMaxMultiple {
						multiple += uint32(rand.Int31n(int32(conf.FishMaxMultiple - conf.FishMinMultiple + 1)))
					}

					//设置属性
					fish.SetType(i.FishType)
					fish.SetMultiple(multiple)
					fish.SetProbability(conf.FishProbability)
					fish.SetLotteryProbability(conf.LotteryProbability)
					fish.SetName(conf.FishName)
					fish.SetAngle(j.FishAngle)
					fish.SetX(j.FishX)
					fish.SetY(j.FishY)

					//设置出鱼编号
					fish.SetID(a.GetFishID())

					//不指定能打死自己的玩家
					fish.SetPlayer(InvalidPlayer)

					//加入切片
					fishArray.Fishs = append(fishArray.Fishs, fish)
				}
			}

			//设置鱼阵属性
			fishArray.Type = fishArrayConfig.FishArrayType
			fishArray.Speed = fishArrayConfig.FishArraySpeed
			fishArray.Duration = fishArrayConfig.FishArrayDuration
			fishArray.Actions = fishArrayConfig.FishArrayActions

			//最高持续时间
			if maxDuration < fishArrayConfig.FishArrayDuration {
				maxDuration = fishArrayConfig.FishArrayDuration
			}

			//加入鱼阵切片
			fishArrays = append(fishArrays, fishArray)
		}

		//清空鱼
		a.table.ClearFish()

		//暂停出鱼
		a.Pause(int64(maxDuration + 5000))

		//增加鱼阵
		a.table.AddFishArray(fishArrays)

		//定时鱼阵
		time.AfterFunc(time.Duration(CMIns().FishArrayInterval)*time.Millisecond, func() {
			a.doArray()
		})
		//time.AfterFunc(time.Duration(CMIns().FishArrayInterval-15)*time.Millisecond, func() {
		//	a.doPreArray()
		//})

		//设置标识
		a.table.SetFishArray(true)

		//鱼阵回调 //通知客户端
		a.facb(0, fishArrays)
	*/

}

/*// DeadFishArray 死鱼鱼阵
func (a *AppearFish) DeadFishArray(tp uint32, fid uint64) {
	//获取配置
	conf := CMIns().GetFishConfig(tp)
	if conf == nil {
		return
	}

	//校验鱼类
	if conf.DeadFish == 0 {
		return
	}

	//确定鱼类
	fishType := conf.DeadFish
	redFishType := conf.DeadRedFish

	//获取鱼类配置
	fishconfig := CMIns().GetFishConfig(fishType)
	if fishconfig == nil {
		return
	}

	//创建鱼阵切片
	var fishArrays []FishArray

	//随机红鱼位置
	index := int(rand.Int31n(int32(NumberPreCircle)))

	//获取红鱼配置
	redFishConfig := CMIns().GetFishConfig(redFishType)

	//发散三圈
	for i := 0; i < CircleNumber; i++ {
		//创建鱼阵
		var fishArray FishArray
		for j := 0; j < NumberPreCircle; j++ {
			//创建出鱼
			fish := new(Fish)

			//红鱼属性
			if i == 2 && j == index && redFishConfig != nil {
				//计算倍数
				multiple := redFishConfig.FishMinMultiple
				if redFishConfig.FishMinMultiple != redFishConfig.FishMaxMultiple {
					multiple += uint32(rand.Int31n(int32(redFishConfig.FishMaxMultiple - redFishConfig.FishMinMultiple + 1)))
				}

				//设置属性
				fish.SetType(redFishType)
				fish.SetMultiple(multiple)
				fish.SetProbability(redFishConfig.FishProbability)
				fish.SetLotteryProbability(redFishConfig.LotteryProbability)
				fish.SetName(redFishConfig.FishName)
			} else {
				//计算倍数
				multiple := fishconfig.FishMinMultiple
				if fishconfig.FishMinMultiple != fishconfig.FishMaxMultiple {
					multiple += uint32(rand.Int31n(int32(fishconfig.FishMaxMultiple - fishconfig.FishMinMultiple + 1)))
				}

				//设置属性
				fish.SetType(fishType)
				fish.SetMultiple(multiple)
				fish.SetProbability(fishconfig.FishProbability)
				fish.SetLotteryProbability(fishconfig.LotteryProbability)
				fish.SetName(fishconfig.FishName)
			}

			fish.SetAngle((float32(360) / float32(NumberPreCircle)) * float32(j))

			//设置出鱼编号
			fish.SetID(a.GetFishID())

			//不指定能打死自己的玩家
			fish.SetPlayer(InvalidPlayer)

			//加入切片
			fishArray.Fishs = append(fishArray.Fishs, fish)
		}

		//设置鱼阵属性
		fishArray.Type = FishArrayDisperse
		fishArray.Speed = CMIns().FishArrays[17+i].FishArraySpeed
		fishArray.Duration = CMIns().FishArrays[17+i].FishArrayDuration
		//fishArray.Actions = CMIns().FishArrays[17+i].FishArrayActions

		//加快死鱼鱼阵出圈速度
		fishArrayAction := &FishArrayAction{
			Path: CMIns().FishArrays[17+i].FishArrayActions[0].Path,
			Time: CMIns().FishArrays[17+i].FishArrayActions[0].Time / 2,
		}

		fishArray.Actions = append(fishArray.Actions, fishArrayAction)
		fishArray.Actions = append(fishArray.Actions, CMIns().FishArrays[17+i].FishArrayActions[1])

		//加入鱼阵切片
		fishArrays = append(fishArrays, fishArray)
	}

	//增加鱼阵
	a.table.AddFishArray(fishArrays)

	//通知客户端鱼阵消息
	a.facb(fid, fishArrays)
}
*/
//====================
//simple interface
//====================

// GetID 出鱼编号
func (a *AppearFish) GetID() uint64 {
	return a.id
}

// GetAID 鱼阵编号
func (a *AppearFish) GetAID() uint32 {
	return a.aid
}

// IsStart 是否开始
func (a *AppearFish) IsStart() bool {
	return a.start
}

// IsPause 是否暂停
func (a *AppearFish) IsPause() bool {
	return a.pause != 0
}

// GetFishID 获取出鱼编号
func (a *AppearFish) GetFishID() uint64 {
	a.mutex.Lock()
	defer a.mutex.Unlock()

	a.id++
	return a.id
}

// GetPauseTime 获取暂停时间
func (a *AppearFish) GetPauseTime() int64 {
	surplus := a.pause - time.Now().Unix()
	if surplus <= 0 {
		surplus = 1
	}

	return surplus
}

// PathUsable 路径可用
func (a *AppearFish) PathUsable(path int32, fishs []*Fish) bool {
	for _, v := range fishs {
		if v.Path == path {
			return false
		}
	}

	return true
}

// 鱼潮策略初始化
func (a *AppearFish) InitFishArray() {
	//后续再做
}

// 初始化鱼的路径
func (a *AppearFish) InitFishPath() {
	a.fishPath = make(map[int32]*FishPath)
	for _, v := range srvdata.PBDB_FishPathMgr.Datas.Arr {
		a.fishPath[v.Id] = &FishPath{
			PathId:        v.Id,
			AppearTime:    v.AppearTime,
			DisappearTime: v.DisappearTime,
		}
	}
}

// 清理数据
func (a *AppearFish) cleanData() {
	//重置出鱼编号
	a.id = 0
	//重置场景里的鱼
	a.SceneEx.fish_list = make(map[int32]*Fish) // 鱼标识 存活的鱼
	//重置逻辑帧
	a.SceneEx.TimePoint = 0
	fishlogger.Trace("定时切换场景，清理数据！！！！！！！！")
	//通知客户端切换场景
	a.SceneEx.NotifyChangeScene()
	//定时切换场景
	time.AfterFunc(FishArrayInterval, func() {
		if a.start {
			a.cleanData()
		}
	})
}
