import {
  Animation,
  Component,
  Node,
  NodePool,
  Prefab,
  Tween,
  Vec2,
  Vec3,
  _decorator,
  game,
  instantiate,
  tween,
} from 'cc'

import FishBase from '../../../fish/script/FishBase'
import FishMover from '../../../fish/script/FishMover'
import FishUI from '../../../fish/script/FishUI'
import { Logger } from '../../engine/utils/Logger'
import RandomUtil from '../../engine/utils/RandomUtil'
import { FishConfig } from '../config/FishConfig'
import { FishInfo } from '../config/FishInfo'
import { FishMap } from '../config/FishMap'
import { FishMapInfo } from '../config/FishMapInfo'
import { FishPathConfig } from '../config/FishPathConfig'
import GameMusicHelper from '../utils/GameMusicHelper'

import TimeHelper from '../utils/TimeHelper'

import ScoreManager from './ScoreManager'
import WsManager from './WsManager'
import { FishPathInfo } from '../config/FishPathInfo'

const { ccclass, property } = _decorator

interface dataType {
  fisn: Array<FishType>
}

interface FishType {
  fishId: string
  fishInfo: FishInfo
  fishType: string
  isDead: number
  fishPathInfo: Array<fishPathInfoType>
}

interface fishPathInfoType {
  pathId: string
  path: Array<PathPoint>
}

interface PathPoint {
  x: number
  y: number
}

// 鱼管理类
@ccclass('FishManager')
export default class FishManager extends Component {
  public static instance: FishManager = null
  @property({ type: Node })
  private fishContainer: Node | null = null

  @property({ type: [Prefab] })
  public fishPrefabList: Array<Prefab> = []

  private fishPool: Array<NodePool> = []
  private fishList: Map<string, FishBase> = new Map()
  private nextRandomFishTime: number = 0
  private minRandomTime: number = 2 * (game.frameRate as number)
  private maxRandomTime: number = 5 * (game.frameRate as number)
  private isFishMap: boolean = false
  private mapCount: number = 0

  private _fishPosCache: Vec3

  onLoad() {
    WsManager.instance.on(100, this.randomFish, this)
    FishManager.instance = this
    this._fishPosCache = new Vec3()
    Logger.log('maxRandomTime=', this.minRandomTime, this.maxRandomTime, game.frameRate)
  }

  start() {
    // this.randomFish()
  }

  update() {
    // this.checkRandomFish()
    this.checkFishMoveEnd()
    // this.checkFishMap()
  }

  private checkFishMap() {
    if (!this.isFishMap) {
      if (this.mapCount > 0) {
        this.mapCount--
        if (this.mapCount <= 0) FishUI.instance.playWaveEffect()
      }
    }
  }

  // 检测是否随机鱼
  private checkRandomFish() {
    if (!this.isFishMap) {
      if (this.nextRandomFishTime > 0) {
        this.nextRandomFishTime--
        // if (this.nextRandomFishTime === 0) this.randomFish()
      }
    }
  }

  // 检测鱼是否移动结束
  private checkFishMoveEnd() {
    this.fishList.forEach(async (item: FishBase, key: string) => {
      if (this.isFishMap) {
        // 鱼阵回收
        if (item.isDead === 2) {
          item.node.getPosition(this._fishPosCache)
          this._fishPosCache.x -= 2
          item.node.setPosition(this._fishPosCache)
          if (this._fishPosCache.x <= -screen.width / 2) {
            // winSize.width
            await WsManager.instance.onSend({
              type: 102,
              fish_id: item.fishId,
            })
            // this.fishList.splice(index, 1)
            this.destroyFish(item)
            // this.fishList.delete(item.fishId)
            this.checkEndFishMap()
          }
        }
      } else if (!item.getComponent(FishMover).isMoving) {
        // 普通鱼回收
        await WsManager.instance.onSend({
          type: 102,
          fish_id: item.fishId,
        })
        // this.fishList.splice(index, 1)
        this.destroyFish(item)
        // this.fishList.delete(item.fishId)
      }
    })
  }

  private checkEndFishMap() {
    // Logger.log('checkEndFishMap==', this.isFishMap, this.fishList)
    if (this.isFishMap && this.fishList.size <= 0) {
      this.isFishMap = false
      // this.randomFish()
    }
  }

  /**
   * 原：本地随机生成鱼
   * 新：服务端生成鱼
   */
  private async randomFish(data: dataType) {
    const arr = data.fisn
    const paths: Array<FishPathInfo> = []
    if (!Array.isArray(arr) || this.isFishMap) return
    for (let i = 0; i < arr.length; i++) {
      const fish: FishBase = this.createFishByType(arr[i])
      for (let k = 0; k < arr[i].fishPathInfo.length; k++) {
        const path: Array<Vec2> = []

        for (let j = 0; j < arr[i].fishPathInfo[k].path.length; j++) {
          const p: Vec2 = new Vec2(
            arr[i].fishPathInfo[k].path[j].x,
            arr[i].fishPathInfo[k].path[j].y,
          )
          path.push(p)
        }
        paths.push(new FishPathInfo(arr[i].fishPathInfo[k].pathId, path))
      }
      fish.fishPathInfo = paths[0]
      this._fishPosCache.z = 0
      this._fishPosCache.x = fish.fishPathInfo.path[0].x
      this._fishPosCache.y = fish.fishPathInfo.path[0].y
      fish.node.setPosition(this._fishPosCache)
      fish.getComponent(FishMover).bezierPList = fish.fishPathInfo.path
      fish.getComponent(FishMover).startMove()
      // this.fishList.push(fish)
      this.fishList.set(fish.fishId, fish)
      // this.fishContainer.addChild(fish.node)
      this.fishContainer.addChild(this.fishList.get(fish.fishId).node)
    }
  }

  // 创建鱼类
  public createFishByType(data: FishType | any): FishBase {
    let fishNode: Node
    const fishType: number = Number(data.fishType)
    if (this.fishPool[fishType - 1] && this.fishPool[fishType - 1].size() > 0) {
      fishNode = this.fishPool[fishType - 1].get()
    } else {
      fishNode = instantiate(this.fishPrefabList[fishType - 1])
    }
    TimeHelper.exeNextFrame(fishNode, () => fishNode.getComponent(Animation).play())
    const fishInfo: FishInfo = FishConfig.getFishInfoByType(fishType)
    fishNode.getComponent(FishBase).fishInfo = fishInfo
    fishNode.getComponent(FishBase).fishType = fishType
    fishNode.getComponent(FishBase).fishId = data.fishId
    fishNode.getComponent(FishBase).isDead = 2
    return fishNode.getComponent(FishBase)
  }

  // 销毁鱼类
  public killFish(res: any) {
    const fishCheck = this.fishList.get(res.fish_id)
    // console.log('正在执行销毁=', fishCheck.fishId, res.fish_id, res.fish_status, fishCheck.isDead)
    if (fishCheck) {
      fishCheck.isDead = 1
      setTimeout(() => {
        GameMusicHelper.playFishDead(fishCheck.fishType)
        fishCheck.node.getPosition(this._fishPosCache)
        const vec2 = new Vec2(this._fishPosCache.x, this._fishPosCache.y)
        ScoreManager.instance.addScore(Number(res.fish_number), vec2)
        this.destroyFish(fishCheck)
        // console.log('killFish=', fishCheck.fishId, fishCheck.fishInfo.name)
        this.checkEndFishMap()
      }, 500)
      tween(fishCheck.node)
        .repeatForever(tween().by(0.6, { angle: -360 }))
        .start()

      // this.fishList.splice(index, 1)
    }
  }

  private destroyFish(fish: FishBase) {
    const f = this.fishList.get(fish.fishId)
    if (!f) return
    if (!this.fishPool[f.fishType - 1]) {
      this.fishPool[f.fishType - 1] = new NodePool()
    }
    this.fishPool[f.fishType - 1].put(f.node)
    this.fishList.delete(f.fishId)
  }

  public playFishMap() {
    this.isFishMap = true
    this.fishList.forEach((fish: FishBase, key: string) => {
      this.destroyFish(fish)
    })
  }

  public startFishMap() {
    const map: FishMap = FishPathConfig.randomFishMap()
    const fishMapInfoList: Array<FishMapInfo> = map.fishMapInfoList
    Logger.log('startFishMap==', this.isFishMap, this.fishList, map)
    for (let i = 0; i < fishMapInfoList.length; i++) {
      const fishMapInfo: FishMapInfo = fishMapInfoList[i]
      // 暂时屏蔽
      // @ts-ignore
      const fish: FishBase = this.createFishByType(fishMapInfo.fishType)
      fish.node.angle = 0
      this.fishContainer.addChild(fish.node)
      fish.node.setPosition(fishMapInfo.x + screen.width, fishMapInfo.y)
      this.fishList.set(fish.fishId, fish)
    }
  }

  onDestroy() {
    FishManager.instance = null
    WsManager.instance.off(100)
  }

  protected onDisable(): void {}
}
