import { makeAutoObservable } from "mobx";

export const INSTRUMENT_EMOJIS = [
  { name: "guitar", emoji: "🎸" },
  { name: "piano", emoji: "🎹" },
  { name: "trumpet", emoji: "🎺" },
  { name: "trombone", emoji: "🎺" },
  { name: "saxophone", emoji: "🎷" },
  { name: "violin", emoji: "🎻" },
  { name: "cello", emoji: "🎻" },
  { name: "harp", emoji: "🎼" },
  { name: "sitar", emoji: "🎵" },
  { name: "koto", emoji: "🎵" },
  { name: "rhodes", emoji: "🎵" },
  { name: "clarinet", emoji: "🎶" },
  { name: "flute", emoji: "🎶" },
];

export const GENRE_EMOJIS = [
  { name: "bluegrass", emoji: "🎸" },
  { name: "edm", emoji: "🎹" },
  { name: "jazz", emoji: "🎺" },
  { name: "house", emoji: "🎺" },
  { name: "samba", emoji: "🎷" },
  { name: "cumbia", emoji: "🎻" },
  { name: "flamenco", emoji: "🎻" },
  { name: "country", emoji: "🎼" },
  { name: "bossa nova", emoji: "🎼" },
  { name: "j-pop", emoji: "🎼" },
  { name: "k-pop", emoji: "🎼" },
  { name: "trance", emoji: "🎼" },
];

export const MODES = {
  instrument: INSTRUMENT_EMOJIS,
  genre: GENRE_EMOJIS,
};

class MinigamesState {
  queue: any[] = [];
  queuePosition = 0;
  score = 0;
  lastResult: any = null;
  mode: keyof typeof MODES = "instrument";

  constructor() {
    makeAutoObservable(this);
  }

  async load() {
    const dataFetches = await Promise.all(
      MODES[this.mode].map(async ({ name }) => {
        const data = await fetch(`/api/search?query=${name}`, {
          next: {
            revalidate: 120, // 1 hour
          },
        });
        const json = await data.json();

        return json.data.result["tag_song"]["result"];
      })
    );

    // Flatten array of arrays into single array
    const flattened = dataFetches.flat();

    // Fisher-Yates shuffle
    for (let i = flattened.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [flattened[i], flattened[j]] = [flattened[j], flattened[i]];
    }

    this.queue = flattened;
  }

  submitAnswer(answer: string) {
    const tags: string =
      this.queue[this.queuePosition].metadata.tags.toLowerCase();
    if (tags.includes(answer)) {
      this.score++;
    }

    this.lastResult = {
      answer,
      tags: tags,
      correct: tags.includes(answer),
      clip: this.queue[this.queuePosition],
    };

    this.queuePosition++;
  }

  get currentModeList() {
    return MODES[this.mode];
  }

  setMode(mode: keyof typeof MODES) {
    this.mode = mode;
    this.load();
  }
}

export default MinigamesState;
