import { BeatmapDecoder } from "osu-parsers";
import { ScoreDecoder } from "../osu-parsers";
import { StandardRuleset, StandardBeatmap } from "osu-standard-stable";

import { IMod, Score } from "osu-classes";
import p5, { Image } from "p5";
import { create } from "zustand";

const ruleset = new StandardRuleset();
const scoreDecoder = new ScoreDecoder();
const beatmapDecoder = new BeatmapDecoder();

export async function getReplay(buffer: ArrayBuffer) {
  const repl = await scoreDecoder.decodeFromBuffer(buffer);
  repl.info.ruleset = ruleset;
  return repl;
}

export async function getBeatmap(mapText: string, scoreBase: Score) {
  const map = beatmapDecoder.decodeFromString(mapText);

  const score = scoreBase.info;
  score.accuracy =
    (score.count300 + score.count100 / 3 + score.count50 / 6) /
    (score.count300 + score.count100 + score.count50 + score.countMiss);

  return ruleset.applyToBeatmap(map);
}

export async function loadImageAsync(image: string): Promise<Image> {
  return new Promise((res) => {
    p.loadImage(image, (img) => {
      res(img);
    });
  });
}

export function clamp(num: number, min: number, max: number) {
  if (num > max) return max;
  if (num < min) return min;
  return num
}

export const state = create<{
  beatmap: StandardBeatmap | null;
  replay: Score | null;
  metadataEditorDialog: boolean;
  openDialog: boolean;
  saveDialog: boolean;
  dataAnalysisDialog: boolean;
  achivementsDialog: boolean;
  aboutDialog: boolean;
  grda: any;
  tool: "cursor" | "brush" | "advanced" | "smoother";
  mods: IMod[] | null;
  playing: boolean;
  time: number;
  speed: number;
}>(() => ({
  metadataEditorDialog: false,
  openDialog: false,
  saveDialog: false,
  aboutDialog: false,
  achivementsDialog: false,
  dataAnalysisDialog: false,
  beatmap: null,
  replay: null,
  grda: null,
  tool: "cursor",
  mods: null,
  playing: false,
  time: 0,
  speed: 1
}));

export let p: p5;

export function setEnv(_p: p5) {
  p = _p;
}
