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

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

import bgImg from "../../assets/GamePage/bg.jpg";
import {Card, TCardInfo} from "@/pages/GamePage/Card.ts";
import {shuffle, waitTime} from "@/utils/utils.ts";
import {globalMsg} from "@/pages/GamePage/event/MessageManager.ts";
import {GameEvent} from "@/pages/GamePage/GameEvent.ts";
import CompositePanel from "@/pages/GamePage/CompositePanel/CompositePanel.tsx";
import {initBundle} from "@/pages/GamePage/Helper.ts";
import store from "@/store/store.ts";
import {PAGE_MAP} from "@/utils/constants.ts";
import gameStore from "@/store/gameStore.ts";
import {ECard, ECardType} from "@/common.ts";
import MusicBtn from "@/core/components/MusicBtn/MusicBtn.tsx";
import musicStore from "@/store/musicStore.ts";

const cardSlot = [
  {x: 68, y: 587,},
  {x: 275, y: 587,},
  {x: 483, y: 587,},
  {x: 68, y: 872,},
  {x: 275, y: 872,},
  {x: 483, y: 872,},
]

export interface IGamePageState {
  compositeCard: ECard,
  completeCount: number,
}

import chooseAudio from "@/assets/music/选择.mp3";

@observer
class GamePage extends React.Component {

  state: IGamePageState = {
    compositeCard: null,
    completeCount: 0,
  }

  gameCanvas: HTMLCanvasElement = null;
  app: Application = null;

  cardData = [
    null, null, null,
    null, null, null
  ];

  cardPool: TCardInfo[] = null;

  chooseCard: Card[] = [];

  async componentDidMount() {
    await initBundle();

    this.initEvent();

    await this.initStage();
  }

  initEvent() {
    globalMsg.on(GameEvent.ClickCard, this.onClickCard, this);
    globalMsg.on(GameEvent.PosterClose, this.onPosterClose, this);
  }

  async onClickCard(event: GameEvent, card: Card) {
    if (this.chooseCard.length >= 2) return;

    if (card.select) {
      this.chooseCard.splice(this.chooseCard.indexOf(card), 1);
      card.select = false;
      return;
    }

    musicStore.playSound(chooseAudio);

    this.chooseCard.push(card);
    card.select = true;

    if (this.chooseCard.length === 2) {
      await waitTime(1000);

      const [card1, card2] = this.chooseCard;
      if (card1.cardName === card2.cardName) {
        card1.removeFromParent();
        card2.removeFromParent();
        this.cardData[this.cardData.indexOf(card1)] = null;
        this.cardData[this.cardData.indexOf(card2)] = null;
        this.setState({
          compositeCard: card1.cardName,
          completeCount: this.state.completeCount + 1
        });
        gameStore.poster(card1.cardName);
      } else {
        Toast.show("选错啦");
        card1.select = false;
        card2.select = false;
      }

      this.chooseCard.length = 0;
    }

  }

  onPosterClose = () => {
    this.setState({compositeCard: null,});
    this.dealCard();
    this.check();
  }

  check = () => {
    const death = this.checkDeath();
    const win = this.checkWin();

    if (death || win) {
      gameStore.submit(win, this.state.completeCount);
    }
  }

  checkDeath() {
    const cardMap = {};
    for (let i = 0; i < this.cardData.length; i++) {
      const card = this.cardData[i];
      if (!card) continue;
      if (cardMap[card.cardName]) {
        return false;
      } else {
        cardMap[card.cardName] = true;
      }
    }
    return true;
  }

  checkWin() {
    const haveCard = this.cardData.filter(Boolean);
    return !haveCard.length && !this.chooseCard.length;
  }

  componentWillUnmount() {
    globalMsg.off(GameEvent.ClickCard, this.onClickCard, this);
    globalMsg.off(GameEvent.PosterClose, this.onPosterClose, this);
    this.app?.destroy();
    window["__app"] = null;
  }

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

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

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

    app.renderer.accessibility.destroy();

    await Assets.loadBundle("Game");

    app.ticker.add(this.onUpdate);

    const bg = new Sprite();
    Assets.load(bgImg).then((texture) => bg.texture = texture);
    app.stage.addChild(bg);

  }

  onUpdate = (time: Ticker) => {
    Tween.flush();
  };

  initCardPool = () => {
    const cardArr = Object.values(ECard);
    shuffle(cardArr);

    const pre = cardArr.splice(0, 2);

    const poolHead: TCardInfo[] = [];
    pre.forEach((card) => {
      poolHead.push(
        {cardName: card, type: ECardType.A,},
        {cardName: card, type: ECardType.B,}
      );
    })

    const poolTail = [];
    cardArr.forEach((card) => {
      poolTail.push(
        {cardName: card, type: ECardType.A,},
        {cardName: card, type: ECardType.B,}
      );
    })

    this.cardPool = [
      ...shuffle(poolHead),
      ...shuffle(poolTail),
    ];
  }

  dealCard() {
    if (!this.cardPool) this.initCardPool();

    if (!this.cardPool.length) return;

    let dealCount = 0;
    this.cardData.forEach((card, index) => {
      if (!card) {
        const cardInfo = this.cardPool.shift();
        card = new Card(cardInfo);
        this.app.stage.addChild(card);
        this.cardData[index] = card;
        Tween.get(card)
          .set({x: 500, y: 1300, scale: 0.1})
          .wait(66 * dealCount++)
          .to({
            x: cardSlot[index].x,
            y: cardSlot[index].y,
            scale: 1,
          }, 666, Ease.quadInOut);
      }
    });
  }

  /**
   * 点击海报
   */
  clickPoster = () => {
    Toast.show("游戏结束后可在“活动首页”进行查看");
  }

  /**
   * 点击发牌
   */
  clickDealCard = () => {
    if (this.cardPool && !this.cardPool.length) {
      return Toast.show("全部卡牌已发完～");
    }

    const haveCard = this.cardData.filter(Boolean);

    if (haveCard.length >= 6) {
      return Toast.show("当前无空余卡槽位置～");
    }

    this.dealCard();
  }

  /**
   * 点击返回
   */
  clickBack = () => {
    store.changePage(PAGE_MAP.HOME_PAGE);
  }

  render() {
    const {compositeCard, completeCount} = this.state;
    return <div className="GamePage">
      <div className="gameBg"/>

      <canvas
        className="gameCanvas"
        ref={(el) => this.gameCanvas = el}
      />

      <div className="progressTitle"/>
      <div className="progressTxt">({completeCount}/8)</div>
      <div className="progressBar">
        <div className="progressFill"
             style={{
               width: `${completeCount / 8 * 648 / 100}rem`
             }}
        />
      </div>

      <MusicBtn className="musicBtn md10"/>
      <Button className="posterBtn md9" onClick={this.clickPoster}/>
      <Button className="dealCardBtn md8" onClick={this.clickDealCard}/>
      <Button className="backBtn md7" onClick={this.clickBack}/>

      {compositeCard && <CompositePanel count={completeCount} cardName={compositeCard}/>}
    </div>;
  }
}

export default GamePage;
