import { RES } from '../../../module/RES';
import Clock from '../../Clock';
import { GDispatcher } from '../../Main';
import { getRandomNum, spliceArrItem } from '../../utils/utils';
import { GPool } from './../../../module/tools/GPool';
import { GameDiffConfig, GameEleOfBucket, GameEleOfPowerBall, GameEleOfWater } from './GameEle';
import { Pos } from "./GameTypes";

interface ConveyorBeltInfer {
  start: Pos,
  end: Pos,
  obstacleWey?: () => boolean, // 障碍物出来的逻辑
  obstacleJudge?: (item: FYGE.Container, con: ConveyorBelt) => void, // 障碍物 处理判断
  updateScore?: (score: number) => void // 更新分数
}

type ConveyorBeltItemConstruct = GameEleOfBucket | GameEleOfWater | GameEleOfPowerBall

type ConveyorItemResName = string

type ConveyorBeltItemType = {
  construct: any,
  resName: ConveyorItemResName,
  isObstacle?: boolean
}

// 默认升序
const ConveyorBeltItemList: Array<ConveyorBeltItemType> = [
  {
    construct: GameEleOfPowerBall,
    resName: 'powerBall.svga',
    isObstacle: false
  },
  {
    construct: GameEleOfWater,
    resName: 'water_GE.png',
    isObstacle: true
  },
  {
    construct: GameEleOfBucket,
    resName: 'bucket_GE.png',
    isObstacle: true
  }
]

type ConveyorItemConfig = {
  conveyorItemsList: Array<ConveyorBeltItemType>,
  isRandom: boolean
}

const defaultConveyorConfig:ConveyorItemConfig = {
  conveyorItemsList: ConveyorBeltItemList,
  isRandom: true
}

export class ConveyorBelt extends FYGE.Container {
  startPos: Pos
  endPos: Pos
  obstacleWey?: () => boolean
  obstacleJudge?: Function
  _speed: number = 300 // 当前速度
  spl: number // 下一个 出现的 距离 后面就去取 随机值
  tanValue: number
  totalDisY: number // 全部距离
  ty: number = 0 // y 经历的距离 用来判断是否出下一个
  isMove: boolean = false // 是否已经开始
  clock: Clock
  conveyorItems: Array<ConveyorBeltItemConstruct> = []
  scaleEndProportion: number = 0.3
  _config: ConveyorItemConfig
  _totalTy: number = 0 // 一共走了多少距离 计算分数
  updateScore: Function
  acc: number = 0 // 加速度

  get speed() {
    return this._speed
  }

  set speed(n) {
    this.initAcc()
    this._speed = n
  }

  constructor(props: ConveyorBeltInfer, splt?: number, config: ConveyorItemConfig = defaultConveyorConfig) {
    super()
    this.spl = splt || getRandomNum(0, 300)
    this._config = config
    this.clock = new Clock()
    this.startPos = props.start
    this.endPos = props.end
    this.obstacleWey = props.obstacleWey
    this.obstacleJudge = props.obstacleJudge
    this.updateScore = props.updateScore
    this.tanValue = Math.abs(props.start.x - props.end.x) ? (props.start.y - props.end.y) / (props.start.x - props.end.x) : 0
    this.totalDisY = Math.abs(props.start.y - props.end.y)

    this.initEvents()
  }

  /**
   * 计算加速度
   */
  initAcc() {
    let t = this.totalDisY / this.speed
    this.acc = 2 * this.totalDisY / Math.pow(t, 2)
  }

  reStart() {
    this.conveyorItems.forEach(i => {
      this.popConveyor(i)
    })
    this.start()
  }

  start() {
    this.isMove = true
    this.totalTy = 0
    this.clock.restart()
  }

  stop() {
    this.isMove = false
  }

  initEvents() {
    this.addEventListener(FYGE.Event.ENTER_FRAME, this.onUpdate, this)
  }

  removeEvents() {
    this.removeEventListener(FYGE.Event.ENTER_FRAME, this.onUpdate, this)
  }

  destroy(): void {
    super.destroy()
    GPool.clear()
    this.removeEvents()
  }

  onInitConveyorItem(e: ConveyorBeltItemType) {
    let item: ConveyorBeltItemConstruct
    item = GPool.takeOut<ConveyorBeltItemConstruct>(e.resName) || new e.construct(e.resName)
    // if (e.resName === 'bucket_GE.png') {
      
    // } else if (e.resName === 'powerBall.svga') {
    //   item = GPool.takeOut<GameEleOfPowerBall>(e.resName) || new GameEleOfPowerBall(e.resName)
    // } else if (e.resName === 'water_GE.png') {
    //   item = GPool.takeOut<GameEleOfWater>(e.resName) || new GameEleOfWater(e.resName)
    // }
    item.setPostion(this.startPos.x, this.startPos.y)
    item.reset()
    this.conveyorItems.push(item)
    return item
  }

  setNextSpl(n: number) {
    this.spl = n
  }

  getNext = (() => {
    let i = 0
    return (isPowerBall: boolean = false) => {
      if (this._config.isRandom) {
        if (isPowerBall) {
          return this._config.conveyorItemsList[0]
        }
        const p = Math.random()
        const currDiff = this.currConfig.proportion
        // this._config.conveyorItemsList
        const r = currDiff.findIndex((n: number) => {
          return p < n
        })
        return this._config.conveyorItemsList[r]
      } else {
        const len = this._config.conveyorItemsList.length
        return this._config.conveyorItemsList[i++%len]
      }
    }
  })()

  onRenderConveyorItem() {
    let con: ConveyorBeltItemConstruct
    if (this.obstacleWey) {
      con = this.onInitConveyorItem(this.getNext(this.obstacleWey()))
    } else {
      con = this.onInitConveyorItem(this.getNext())
    }
    
    this.addChild(con)
  }

  get totalTy() {
    return this._totalTy
  }

  _score: number = 0
  currConfig: any
  set totalTy(n) {
    this._score = Math.floor(n / 10)
    this.currConfig = GameDiffConfig.getCurrGameDiff(this._score, (curr) => {
      // this.speed = curr.speed
    })
    this.speed = this.currConfig.speed
    this._totalTy = n
  }

  onChangeTime(t: number) {
    this.conveyorItems.forEach(item => {
      let _y = item.speed * t // vt + 1/2 *a t^2
      let _x = _y / this.tanValue
      // item.setPostion()
      item.position.set(item.x + _x, item.y + _y)
      const yp = _y / (this.totalDisY * this.scaleEndProportion)
      item.scaleX < 1 && (item.scaleX += yp);
      item.scaleX < 1 && (item.scaleY += yp);


      if (item.y >= this.endPos.y) {
        this.popConveyor(item)
      }

      item.speed += this.acc * t
    })
  }

  onChangePosByY(changeY: number) {
    this.ty += changeY
    this.totalTy += changeY
    this.updateScore && this.updateScore(this._score)
    if (this.ty >= this.spl) {
      // console.log('渲染一个：', this.ty)
      this.ty = 0
      this.onRenderConveyorItem()
      this.obstacleJudge && this.obstacleJudge(null, this)
    }
    // this.conveyorItems.forEach(target => {
    //   if (!this.tanValue) {
    //   } else {
    //     target.x += changeY / this.tanValue
    //   }
    //   target.y += changeY
    //   const yp = changeY / (this.totalDisY * this.scaleEndProportion)
    //   // target.alpha += yp
    //   target.scaleX < 1 && (target.scaleX += yp);
    //   target.scaleX < 1 && (target.scaleY += yp);
    //   if (target.y >= this.endPos.y) {
    //     this.popConveyor(target)
    //     this.obstacleJudge && this.obstacleJudge(target, this)
    //   }
    // })
    
  }

  // 因为碰撞或者移动出去的 销毁
  popConveyor(item: ConveyorBeltItemConstruct, didu?: boolean) {
    if (didu) {
      item.onCollision()
    }
    item.visible = false
    spliceArrItem(this.conveyorItems, item)
    GPool.takeIn(item._res, item)
  }

  onUpdate() {
    if (!this.isMove) return
    
    const diff =  this.clock.getDelta()
    if (diff > 0.1) return

    const currSpeed = this.speed
    this.onChangePosByY(diff * currSpeed)
    this.onChangeTime(diff)
  }

}