import { applet, reactive } from "@scripts/applets/common";

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

////////////////////////////////////////////
// 🗂️ Applets
////////////////////////////////////////////
import type * as AudioEngine from "@applets/engine/audio/types.d.ts";
import type * as QueueEngine from "@applets/engine/queue/types.d.ts";

import type * as AudioUI from "@applets/constituents/pilot/audio/types.d.ts";

const engine = {
  audio: await applet<AudioEngine.State>("../../engine/audio"),
  queue: await applet<QueueEngine.State>("../../engine/queue"),
};

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

const ui = {
  audio: await applet<AudioUI.State>("../../constituents/pilot/audio/", { setHeight: true }),
};

////////////////////////////////////////////
// ⚙️ [Connections → Engines]
// 🔉 AUDIO
////////////////////////////////////////////

// NOTE:
// These could probably be optimised, but it works.

reactive(
  engine.audio,
  (data) => data.items[engine.queue.data.now?.id ?? Infinity]?.isPlaying ?? false,
  (isPlaying) => ui.audio.sendAction("modifyIsPlaying", isPlaying),
);

reactive(
  engine.audio,
  (data) => data.items[engine.queue.data.now?.id ?? Infinity]?.progress ?? 0,
  (progress: number) => ui.audio.sendAction("modifyProgress", progress),
);

////////////////////////////////////////////
// 🌅 [Connections → UI]
// 🔉 AUDIO
////////////////////////////////////////////

reactive(
  ui.audio,
  (data) => data.isPlaying,
  async (isPlaying, setter) => {
    const audioId = engine.queue.data.now?.id;
    const volume = engine.audio.data.volume;

    // Automatically start playing something if nothing is playing yet.
    if (!audioId) {
      if (isPlaying) {
        const now = await engine.queue.sendAction("shift");
        if (!now) {
          console.warn("No tracks available yet, try again later.");
          await ui.audio.sendAction("modifyIsPlaying", false);
          setter(false);
        }
      }
      return;
    }

    // Otherwise just control the audio
    if (isPlaying) {
      engine.audio.sendAction("play", { audioId, volume });
    } else {
      engine.audio.sendAction("pause", { audioId });
    }
  },
);

reactive(
  ui.audio,
  (data: AudioUI.State) => data.seekPosition,
  (seekPosition) => {
    if (seekPosition !== undefined && engine.queue.data.now?.id) {
      engine.audio.sendAction("seek", {
        percentage: seekPosition,
        audioId: engine.queue.data.now.id,
      });
    }
  },
);
