import type { URLTrack } from "webamp";
import Webamp from "webamp";

import type { ManagedOutput, ResolvedUri, Track } from "@applets/core/types.d.ts";
import { applet, inputUrl, wait } from "@scripts/applet/common";

////////////////////////////////////////////
// 🗂️ Applets
////////////////////////////////////////////
const configurator = {
  input: await applet("/configurator/input"),
  output: await applet<ManagedOutput>("/configurator/output"),
};

const orchestrator = {
  input: await applet("/orchestrator/input-cache"),
};

////////////////////////////////////////////
// ⚡
////////////////////////////////////////////
const amp = new Webamp({
  initialTracks: [],
});

// Override
const loadFromUrl = amp.media.loadFromUrl.bind(amp.media);

async function loadOverride(uri: string, autoPlay: boolean) {
  const resp = await inputUrl(configurator.input, uri);
  if (!resp) throw new Error("Failed to resolve URI");
  return await loadFromUrl(resp.url, autoPlay);
}

amp.media.loadFromUrl = loadOverride.bind(amp.media);

// Render
const ampNode = document.createElement("div");
ampNode.style = "height: 100vh; left: 0; position: absolute; top: 0; width: 100%; z-index: -1000;";
document.body.appendChild(ampNode);
amp.renderWhenReady(ampNode);

// Wait for tracks to load
wait(configurator.output, (d) => d?.tracks.state === "loaded").then(loadAndInsert);
configurator.output.ondata = loadAndInsert;

// Load & insert
let inserting = false;

async function loadAndInsert() {
  if (configurator.output.data.tracks.state !== "loaded") return;
  if (inserting) return;
  inserting = true;
  const tracks = await loadTracks();

  // TODO: This kinda messes up the UI,
  //       but at least the active audio doesn't stop playing.
  amp.store.dispatch({ type: "REMOVE_ALL_TRACKS" });

  // TODO: Webamp blows up if you add too much tracks
  amp.appendTracks(tracks.slice(0, 1000));

  const status = amp.getMediaStatus();
  if (status !== "PLAYING") amp.nextTrack();

  inserting = false;
}

////////////////////////////////////////////
// 🛠️
////////////////////////////////////////////
async function loadTracks(): Promise<URLTrack[]> {
  const tracks = configurator.output.data.tracks.collection;
  return tracks.map((track) => {
    const urlTrack: URLTrack = {
      url: track.uri,
      metaData: {
        title: track.tags?.title || "",
        artist: track.tags?.artist || "",
        album: track.tags?.album,
      },
      duration: track.stats?.duration,
    };

    return urlTrack;
  });
}
