import { v4 as v4uuid } from "uuid";

import { fetchCard, ygopro } from "@/api";
import { playerStore, store, cardStore, CardType } from "@/stores";

import { flatten } from "lodash-es";
import { proxy } from "valtio";
import { subscribeKey } from "valtio/utils";
const { matStore } = store;

export default (start: ygopro.StocGameMessage.MsgStart) => {
  matStore.selfType = start.playerType;
  const opponent =
    start.playerType == ygopro.StocGameMessage.MsgStart.PlayerType.FirstStrike
      ? 1
      : 0;

  const meName = playerStore.getMePlayer().name;
  const opName = playerStore.getOpPlayer().name;

  matStore.initInfo.set(0, {
    life: start.life1,
    name: opponent == 0 ? opName : meName,
    deckSize: start.deckSize1,
    extraSize: start.extraSize1,
  });
  matStore.initInfo.set(1, {
    life: start.life2,
    name: opponent == 1 ? opName : meName,
    deckSize: start.deckSize2,
    extraSize: start.extraSize2,
  });

  matStore.monsters.of(0).forEach((x) => (x.location.controler = 0));
  matStore.monsters.of(1).forEach((x) => (x.location.controler = 1));
  matStore.magics.of(0).forEach((x) => (x.location.controler = 0));
  matStore.magics.of(1).forEach((x) => (x.location.controler = 1));

  for (let i = 0; i < start.deckSize1; i++) {
    matStore.decks.of(0).push({
      uuid: v4uuid(),
      occupant: {
        id: 0,
        data: {},
        text: {},
      },
      location: {
        controler: 0,
        zone: ygopro.CardZone.DECK,
      },
      focus: false,
      chaining: false,
      directAttack: false,
      counters: {},
      idleInteractivities: [],
    });
  }
  for (let i = 0; i < start.deckSize2; i++) {
    matStore.decks.of(1).push({
      uuid: v4uuid(),
      occupant: {
        id: 0,
        data: {},
        text: {},
      },
      location: {
        controler: 1,
        zone: ygopro.CardZone.DECK,
      },
      focus: false,
      chaining: false,
      directAttack: false,
      counters: {},
      idleInteractivities: [],
    });
  }
  // 初始化对手的额外卡组
  for (let i = 0; i < start.extraSize2; i++) {
    matStore.extraDecks.op.push({
      uuid: v4uuid(),
      occupant: {
        id: 0,
        data: {},
        text: {},
      },
      location: {
        controler: opponent,
        zone: ygopro.CardZone.EXTRA,
      },
      focus: false,
      chaining: false,
      directAttack: false,
      counters: {},
      idleInteractivities: [],
    });
  }

  // 在`WaitRoom`页面会设置自己的额外卡组，但那时候拿不到正确的`controller`值，因为不知道自己是先攻还是后手，因此这里需要重新为自己的额外卡组设置`controller`值
  matStore
    .in(ygopro.CardZone.EXTRA)
    .me.forEach((state) => (state.location.controler = 1 - opponent));

  /** 自动从code推断出occupant */
  const genCard = (o: CardType) => {
    // FIXME 还没处理超量
    const t = proxy(o);
    subscribeKey(t, "code", async (code) => {
      const { text, data } = await fetchCard(code ?? 0);
      t.text = text;
      t.data = data;
    });
    return t;
  };

  const cards = flatten(
    [start.deckSize1, start.extraSize1, start.deckSize2, start.extraSize2].map(
      (length, i) =>
        Array.from({ length }).map((_, sequence) =>
          genCard({
            uuid: v4uuid(),
            code: 0,
            controller: i < 2 ? 1 - opponent : opponent, // 前两个是自己的卡组，后两个是对手的卡组
            zone: i % 2 ? ygopro.CardZone.EXTRA : ygopro.CardZone.DECK,
            counters: {},
            idleInteractivities: [],
            sequence,
            data: {},
            text: {},
          })
        )
    )
  );

  cardStore.inner.push(...cards);
  // 设置自己的额外卡组，信息是在waitroom之中拿到的
  cardStore
    .at(ygopro.CardZone.EXTRA, 1 - opponent)
    .forEach((card) => (card.code = myExtraDeckCodes.shift()!));
};
