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

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

////////////////////////////////////////////
// 🎨 Styles
////////////////////////////////////////////
import "@styles/themes/webamp/index.css";

////////////////////////////////////////////
// 🗂️ 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: [],
});

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(configurator.output, (d) => d?.tracks.state === "loaded").then(loadAndInsert);
configurator.output.ondata = loadAndInsert;

let inserting = false;

async function loadAndInsert() {
  if (configurator.output.data.tracks.state !== "loaded") return;
  if (inserting) return;
  inserting = true;
  const tracks = await loadTracks();
  amp.setTracksToPlay([]);
  amp.appendTracks(tracks);
  amp.nextTrack();
  inserting = false;
}

////////////////////////////////////////////
// 🛠️
////////////////////////////////////////////
async function loadTracks(): Promise<URLTrack[]> {
  return await configurator.output.data.tracks.collection.reduce(
    async (promise: Promise<URLTrack[]>, track: Track) => {
      const acc = await promise;

      // TODO: Ideally the URL should only be resolved when needed,
      //       but webamp doesn't allow for that.
      //       Maybe you could work around it with a service worker.
      const resGet = await configurator.input.sendAction<ResolvedUri>(
        "resolve",
        { method: "GET", uri: track.uri },
        {
          timeoutDuration: 60000 * 5,
        },
      );

      if (!resGet) return acc;

      const urlTrack: URLTrack = {
        url: resGet.url,
        metaData: {
          title: track.tags?.title || "",
          artist: track.tags?.artist || "",
          album: track.tags?.album,
        },
        duration: track.stats?.duration,
      };

      return [...acc, urlTrack];
    },
    Promise.resolve([]),
  );
}
