import React from 'react';
import { observer } from 'mobx-react';
import './GamePage.less';
import { Button } from "@grace/ui";

import { Application, Assets, Ticker } from "pixi.js";
import { Tween } from "./tween";

import { initBundle } from "@/pages/GamePage/Helper.ts";
import MusicBtn from "@/core/components/MusicBtn/MusicBtn.tsx";
import { PageCtrl } from "@/core/ctrls/PageCtrl.tsx";
import { Game } from "@/pages/GamePage/Game.ts";
import { winSize } from "@/pages/GamePage/config/Config.ts";

import { Stats } from 'pixi-stats';

import { System } from 'detect-collisions';
import gameStore from "@/store/gameStore.ts";
import { prefixInteger } from "@/utils/utils.ts";

export const collisionSys: System = new System();
const DEBUG = true ;

export function getApp(): Application {
  return window["__app"];
}

export interface IGamePageState {
}


@observer
class GamePage extends React.Component {

  gameOver: boolean = false;

  state: IGamePageState = {
  }

  gameCanvas: HTMLCanvasElement = null;

  debugCanvas: HTMLCanvasElement = null;
  debugCtx: CanvasRenderingContext2D = null;

  app: Application = null;
  game: Game = null;
  interval: any = 0;

  async componentDidMount() {
    gameStore.reset();

    await initBundle();

    this.initEvent();

    if (DEBUG) {
      this.debugCtx = this.debugCanvas.getContext("2d");
      this.debugCanvas.width = winSize.width;
      this.debugCanvas.height = winSize.height;
    }

    await this.initStage();

    this.startCd();

  }

  startCd = () => {
    this.interval = setInterval(() => {
      gameStore.gameInfo.cd -= 1;
      if (gameStore.gameInfo.cd <= 0) {
        clearInterval(this.interval);
        gameStore.gameInfo.cd = 0;
        this.gameOver = true;
        gameStore.submit();
      }
    }, 1000);
  }

  initEvent() {
  }

  componentWillUnmount() {
    this.app?.destroy();
    window["__app"] = null;
    collisionSys.clear();
    Tween.removeAllTweens();
  }

  async initStage() {
    const app = this.app = new Application();

    await app.init({
      canvas: this.gameCanvas,
      backgroundColor: 0xffffff,
      width: winSize.width,
      height: winSize.height,
      powerPreference: "high-performance",
      // resolution: Math.min(window.devicePixelRatio, 2) || 1,
      resolution: 1,
      preference: "webgl",
      webgl: {
        // preserveDrawingBuffer: true,
        // antialias: true,
      },
      eventMode: "static",
    });

    window["__app"]?.destroy();
    window["__app"] = app;

    if (DEBUG) {
      const stats = new Stats(app.renderer);
    }

    app.renderer.accessibility.destroy();

    await Assets.loadBundle("Game");

    app.ticker.add(this.onUpdate);

    this.game = app.stage.addChild(new Game());

  }

  onUpdate = (time: Ticker) => {
    if (this.gameOver) return;

    Tween.flush();
    this.game.onUpdate(time);
    collisionSys.update();

    if (DEBUG) {
      this.debugCtx.clearRect(0, 0, winSize.width, winSize.height);
      this.debugCtx.strokeStyle = "#FF0000";
      this.debugCtx.beginPath();
      collisionSys.draw(this.debugCtx);
      collisionSys.drawBVH(this.debugCtx);
      this.debugCtx.stroke();
    }

  };

  /**
   * 点击返回
   */
  clickBack = () => {
    PageCtrl.backPage();
  }

  render() {

    const { score, cd } = gameStore.gameInfo;

    const min = prefixInteger(Math.floor(cd / 60), 2);
    const sec = prefixInteger(cd % 60, 2);

    return <div className="GamePage">
      <div className="gameBg"/>
      <canvas
        className="gameCanvas"
        ref={(el) => this.gameCanvas = el}
      />
      {
        DEBUG && <canvas
          className="gameCanvas debugCanvas"
          ref={(el) => this.debugCanvas = el}
        />
      }
      <div className="scoreArea">
        <div className="scoreNum">{score}</div>
      </div>
      <div className="cd">
        <div className="cdNum">{min}:{sec}</div>
      </div>
      <MusicBtn className="musicBtn"/>
      <Button className="backBtn" onClick={this.clickBack}/>
    </div>;
  }
}

export default GamePage;
