import { ConveyorBelt } from './ConveyorBelt';
import { GameEleOfPowerBall, GameEleOfWater, GameEleOfBucket, GameEleOfGamer } from './GameEle';
import UI from '../../UI';
import { Scene } from './../../../module/views/Scene';
import { RES } from '../../../module/RES';
import { collisionJudge, SetMouseEventNone } from '../../utils/utils';
import { leftBanner } from '../../lotties/leftBanner';
import { rightBanner } from '../../lotties/rightBanner';
import { banner1 } from '../../lotties/banner1';
import { banner2 } from '../../lotties/banner2';
import { ProgressBarS } from '../../common/ProgressBarS';
import { Tools } from '../../Tools';
import { getTbData, sendTbNet, TbNetName } from '../../TaoBaoNet';

const hpPoxLis = [55, 82, 109]

export class PowerProgress extends FYGE.Container {
  _value: number = 0
  progress: ProgressBarS
  fullFunc?: Function
  status: number = 0 // 0 正常  1 动效 

  get value() {
    return this._value
  }

  set value(n) {
    if (n > 1) n = 1
    if (n < 0) n = 0
    this._value = n
    FYGE.Tween.removeTweens(this.progress)
    FYGE.Tween.get(this.progress)
      .to({
        value: n
      }, 100)
    if (n == 1 && !this.status) {
      this.powerFullAni(true)
    }
  }

  /**
   * 进度条满的时候 逻辑
   * @param f 
   */
  constructor(f?: Function) {
    super()
    this.fullFunc = f || (() => {})
    this.initUi()
  }

  add() {
    if (!this.status) {
      this.value += 0.1
    }
  }

  speedShow: FYGE.MovieClip
  powerFullAni(b: boolean = true) {
    if (b && this.status == 0) {
      this.status = 1
      this.fullFunc(true);
      (this.speedShow || (this.speedShow = UI.MoiveClip(this, 'speedShow.svga', -30, -30))).visible = true;
      FYGE.Tween.get(this)
        .to({value: 0}, 5000)
        .call(() => {
          this.fullFunc(false)
          this.powerFullAni(false)
          this.status = 0
        })
    } else {
      this.speedShow.visible = false
    }
    
  }

  initUi() {
    UI.Sp(this, 'powerProgress-back.png')
    var p = this.progress = new ProgressBarS(UI.Sp(this, 'powerProgress-p.png', 28, 52), null, 'top')
    p.value = 0
    UI.Sp(this, 'powerProgress-logo.png')
    
  }
}

class NewGuyScene extends FYGE.Container {
  finishFunc: Function
  constructor(finishFunc: Function) {
    super()
    this.finishFunc = finishFunc
    this.initUi()
  }

  gs: FYGE.Sprite
  step: number = 1
  initUi() {
    this.gs = UI.Sp(this, 'Guide1.png')
    this.addEventListener(FYGE.MouseEvent.CLICK, this.nextStep, this)
  }

  nextStep() {
    this.step += 1
    if (this.step == 4) {
      this.finishFunc()
      this.destroy()
      return
    }
    this.gs.texture = RES.getRes(`Guide${this.step}.png`)

  }

  destroy(): void {
      super.destroy()
      this.removeAllEventListener()
  }
}

export class LevonoGameScene extends Scene {
  conveyorList: Array<ConveyorBelt> = []
  besidesList: Array<ConveyorBelt> = []
  _GameStatus: number // 0 未开始 1 倒计时 2开始游戏 3 玩家 开始加速
  Gamer: GameEleOfGamer
  powerPro: PowerProgress
  _hp: number = 3
  hpSpriteList: Array<FYGE.Sprite> = []
  atomList: Array<FYGE.Container> = []
  _musicStatus: boolean = false
  musicBtn: FYGE.Button
  _score: number = 0
  scoreBitMapText: FYGE.BitmapText
  fixedTop: number = 200 // 顶部距离

  get score() {
    return this._score
  }

  set score(s) {
    this.scoreBitMapText.text = `${s}m`
    this._score = s
  }

  get musicStatus() {
    return this._musicStatus
  }

  set musicStatus(b) {
    (this.musicBtn || (this.musicBtn = UI.Btn(this, `music-${b ? 'on' : 'off'}.png`, this.musicBtnClick, this,
      670, this.fixedTop
    ))).texture = RES.getRes(`music-${b ? 'on' : 'off'}.png`)

    this.playSoundById('bgm', b, true, true)
    this._musicStatus = b;
  }

  get GameStatus() {
    return this._GameStatus
  }

  set GameStatus(n) {
    if (n === this._GameStatus) return
    this._GameStatus = n
  }

  get hp() {
    return this._hp
  }

  set hp(n) {
    for (var i = 0; i < 3; i ++) {
      this.hpSpriteList[i].visible = i < n
    }
    this._hp = n
    if (!n) {
      this.GameStatus = 0
      this.onGameOver()
    }
  }

  get groupNames(): string[] {
    return [
      'LevonoGameScene',
      'LevonoSvga',
      'banner1',
      'banner2'
    ]
  }

  musicBtnClick() {
    this.musicStatus = !this.musicStatus
  }

  playSoundById(id: string, isOn: boolean = true, loop:boolean = false, force: boolean = false) {
    if (!this.musicStatus && !force) return
    sendTbNet(TbNetName.turnBgm, {
      id: id,
      loop: loop,
      play: isOn
    }, null, true, true)
  }

  initUi() {

    if (document.body.clientHeight < 650) {
      this.fixedTop = 230
    }
    UI.Sp(this, 'scene-back.jpg')

    this.atomList.push(SetMouseEventNone(UI.MoiveClip(this, 'mountain.svga',30, 280)))

    this.atomList.push(SetMouseEventNone(UI.MoiveClip(this, 'tree.svga', -10, 430)))

    // SetMouseEventNone(UI.MoiveClip(this, 'leftBanner.svga',0, 450))

    // SetMouseEventNone(UI.MoiveClip(this, 'rightBanner.svga', 420, 450))

    this.atomList.push(SetMouseEventNone(UI.Lottie(this, banner1, 0, 450)))
    this.atomList.push(SetMouseEventNone(UI.Lottie(this, banner2, 420, 450)))

    // this.addChild(new GameEleOfWater(RES.getRes('water_GE.png')))
    // this.addChild(new GameEleOfBucket(RES.getRes('bucket_GE.png')))

    // var ball =  this.addChild(new GameEleOfPowerBall(RES.getRes('powerBall.svga')))
    // ball.setPostion(130, 130)
    // ball.scale.set(0.5, 0.5)
    // UI.Rect(this, 260, 460, 0xcccccc, 20, 240, 1000, 0.7)

    this.conveyorList.push(this.addChild(new ConveyorBelt({
      start: {
        x: 358,
        y: 510,
      },
      end: {
        x: -300, y: 1624
      },
      obstacleWey: this.shouldOutObstacle,
      obstacleJudge(t, con) {
        con.setNextSpl(300 + Math.random() * 300)
      }
    })))

    this.conveyorList.push(this.addChild(new ConveyorBelt({
      start: {
        x: 380,
        y: 510,
      },
      end: {
        x: 355, y: 1624
      },
      obstacleWey: this.shouldOutObstacle,
      obstacleJudge(t, con) {
        con.setNextSpl(300 + Math.random() * 300)
      }
    })))

    this.conveyorList.push(this.addChild(new ConveyorBelt({
      start: {
        x: 402,
        y: 510,
      },
      end: {
        x: 1050, y: 1624
      },
      obstacleWey: this.shouldOutObstacle,
      obstacleJudge(t, con) {
        con.setNextSpl(300 + Math.random() * 300)
      },
      updateScore: this.updateScore
    })))

    // UI.MoiveClip(this, '障碍物.svga', 0, -5)
    // UI.MoiveClip(this, '障碍物2.svga', 0, -5)

    this.besidesList.push(this.addChild(new ConveyorBelt({
      start: {
        x: 412,
        y: 510,
      },
      end: {
        x: 1470, y: 1624
      },
      obstacleJudge(t, con) {
        con.setNextSpl(100)
      },
    }, 0, {
      conveyorItemsList: [
        {
          construct: GameEleOfWater,
          resName: 'yellow_obstacle.png'
        },
        {
          construct: GameEleOfWater,
          resName: 'right_m.png'
        },
        {
          construct: GameEleOfWater,
          resName: 'red_obstacle.png'
        },
        {
          construct: GameEleOfWater,
          resName: 'right_m.png'
        },
      ],
      isRandom: false
    })))

    this.besidesList.push(this.addChild(new ConveyorBelt({
      start: {
        x: 348,
        y: 510,
      },
      end: {
        x: -740, y: 1624
      },
      obstacleJudge(t, con) {
        con.setNextSpl(100)
      },
    }, 0, {
      conveyorItemsList: [
        {
          construct: GameEleOfWater,
          resName: 'yellow_obstacle0.png'
        },
        {
          construct: GameEleOfWater,
          resName: 'left_m.png'
        },
        {
          construct: GameEleOfWater,
          resName: 'red_obstacle0.png'
        },
        {
          construct: GameEleOfWater,
          resName: 'left_m.png'
        },
      ],
      isRandom: false
    })))

    this.Gamer = this.addChild(new GameEleOfGamer({
      isSpeedUp: false
    }))

    // hpCOnt
    const hpCont = UI.Ctn(this, 0, this.fixedTop)
    UI.Sp(hpCont, 'hpBoard-back.png')

    for (let i = 0; i < hpPoxLis.length; i++) {
      const x = hpPoxLis[i];
      this.hpSpriteList.push(UI.Sp(hpCont, 'hpBoard-hp.png', x, 14))
    }

    this.powerPro = this.addChild(new PowerProgress(this.onGamerSpeedUp))
    this.powerPro.position.set(30, 300)

    const textureList = Tools.getNumTextures('score_')
    textureList['m'] = RES.getRes('score_m.png')
    const score = this.scoreBitMapText = this.addChild(new FYGE.BitmapText(textureList))
    score.position.set(380, 260)
  }

  start(data?: any): void {
    super.start()
    this.GameStatus = 0
    this.onGameStop()

    if (data.isNewGuy) {
      this.addChild(new NewGuyScene(async () => {
        this.onGameRestart()
      }))
      return
    }
    this.onGameRestart()

    // this.musicStatus = true
    // setTimeout(() => {
    //   this.GameStatus = 1
    // }, 500)
  }

  updateScore = (score: number) => {
    this.score = score
  } 

  ActiveFunc(func: Function, statusList: Array<number>, toast?:any) {
    return (...args:any) => {
      if (statusList.includes(this.GameStatus)) {
        return func.apply(this, args)
      } else {
      }
    }
  }

  async onGameRestart() {
    const {success} = await sendTbNet(TbNetName.startGame)
    if (!success) {
      return
    }
    this.onGamePreStart()
  }

  /**
   * 游戏前置处理
   */
  onGamePreStart() {
    this.musicStatus = Tools.PAGE.musicSwitchDefault
    this.GameStatus = 1
    this.score = 0
    this.showAniCountDown()
  }

  CountDownSvga: FYGE.MovieClip
  showAniCountDown() {
    var s = (this.CountDownSvga || SetMouseEventNone(this.CountDownSvga = UI.MoiveClip(this, 'countDown.svga', 260, 600)));
    s.visible = true
    this.playSoundById('countDown')
    s.startAniRange(0, s.totalFrames, 1, () => {
      this.GameStatus = 2
      this.onGameStart()
      s.visible = false
    })
  }

  onGamerSpeedUp = this.ActiveFunc((b: boolean) => {
    this.GameStatus = b ? 3 : 2
    if (b) {
      this.Gamer.isSpeedUp = true
    } else {
      this.Gamer.isSpeedUp = false
    }
  }, [2, 3])

  onGameStart() {
    this.conveyorList.forEach(e => {
      e.start()
    })
    this.besidesList.forEach(e => {
      e.start()
    })
    // @ts-ignore
    this.atomList.forEach(i => i.play && i.play())
    this.Gamer.start()
  }

  onGameStop() {
    this.conveyorList.forEach(e => {
      e.stop()
    })
    this.besidesList.forEach(e => {
      e.stop()
    })
    // @ts-ignore
    this.atomList.forEach(i => i.stop && i.stop())
    this.Gamer.stop()
  }

  async onGameOver() {
    this.onGameStop()
    const {success, data} = await sendTbNet(TbNetName.submitGame, {
      score: this.score,
      timestamp: Date.now(),
      startId: getTbData(TbNetName.startGame).data.startId
    })
  }

  initEvents(): void {
    this.addEventListener(FYGE.MouseEvent.MOUSE_DOWN, this.onTouchStart, this)
    this.addEventListener(FYGE.Event.ENTER_FRAME, this.onFrameUpdate, this)
  }

  removeEvents(): void {
    this.removeAllEventListener()
  }

  touchStartX: number
  onTouchStart(e) {
    if ([0, 1].includes(this.GameStatus)) return
    this.touchStartX = e.clientX
    this.stage.once(FYGE.MouseEvent.MOUSE_UP, (e) => {
      if (!this.touchStartX) return
      const mx = e.clientX - this.touchStartX
      this.Gamer.setGamerPosIndex((mx > 0 ? 1 : -1) *  (Math.abs(mx) > 100 ? 1 : 0))
      this.touchStartX = null
    }, this)
  }

  /**
   * 是否只出 能量
   * @returns 
   */
  shouldOutObstacle = () => {
    let b = this.conveyorList.filter(item => {
      return item.conveyorItems.some(i => {
        return i.y < 800 && i._type === 'obstacle'
      })
    }).length == 2
    return b
  }

  onAddPower() {
    this.playSoundById('powerSound')
    this.GameStatus !== 3 && this.powerPro.add()
  }

  onReducePower() {
    this.playSoundById('obstacleSound')
    if (this.GameStatus !== 3) {
      this.Gamer.onBulingBuling()
      this.hp -= 1
    }
    
  }

  onFrameUpdate() {
    if (!this.GameStatus) return
    for (let con of this.conveyorList) {
      const items = con.conveyorItems
      for ( let item of items ) {
        if (item.y > 800) {
          const isCollisioned = collisionJudge(this.Gamer.getMaterialCollisionObj(), item.getMaterialCollisionObj())
          if (isCollisioned) {
            if (item._type === 'obstacle') {
              this.onReducePower()
            } else {
              this.onAddPower()
            }
            con.popConveyor(item)
            item.onCollision && item.onCollision()
          }
        }
        
      }
    }
  }
}