import { audioBuffer, audioFileName } from "../input.ts";
import { output, OutputFormat } from "../output.ts";
import {
  VisualizerName,
  VisualizerOptions,
  visualizers,
} from "../visualizers/index.ts";
import {
  Quality,
  QUALITY_HIGH,
  QUALITY_LOW,
  QUALITY_MEDIUM,
  QUALITY_VERY_LOW,
} from "mediabunny";

const qualityMap: Record<string, Quality> = {
  "verylow": QUALITY_VERY_LOW,
  "low": QUALITY_LOW,
  "medium": QUALITY_MEDIUM,
  "high": QUALITY_HIGH,
};

function getOutputFilename(format: OutputFormat): string {
  const ext = format === "mp4" ? ".mp4" : ".webm";
  if (audioFileName) {
    const dot = audioFileName.lastIndexOf(".");
    const base = dot > 0 ? audioFileName.slice(0, dot) : audioFileName;
    return `${base}${ext}`;
  }
  return `output${ext}`;
}

type ShowSaveFilePicker = (
  options?: {
    suggestedName?: string;
    types?: Array<{
      description?: string;
      accept: Record<string, string[]>;
    }>;
  },
) => Promise<FileSystemFileHandle>;

function createOverlay(): HTMLDivElement {
  const overlay = document.createElement("div");
  overlay.className = "render-overlay";
  overlay.textContent = "0%";
  document.querySelector(".main-content")!.appendChild(overlay);
  return overlay;
}

export async function handleRender(
  canvas: HTMLCanvasElement,
  fpsSelect: HTMLSelectElement,
  qualitySelect: HTMLSelectElement,
  select: HTMLSelectElement,
  getOpts: () => VisualizerOptions,
  format: OutputFormat,
) {
  if (!audioBuffer) {
    alert("import audio first before rendering");
    return;
  }

  const btnId = format === "mp4" ? "#render-mp4" : "#render-webm";
  const renderBtn = document.querySelector<HTMLButtonElement>(btnId)!;
  renderBtn.disabled = true;
  const overlay = createOverlay();

  try {
    if ("showSaveFilePicker" in globalThis) {
      const mime = format === "mp4" ? "video/mp4" : "video/webm";
      const ext = format === "mp4" ? ".mp4" : ".webm";
      const desc = format === "mp4" ? "MP4 Video" : "WebM Video";
      let handle: FileSystemFileHandle;
      try {
        handle = await (
          globalThis as unknown as { showSaveFilePicker: ShowSaveFilePicker }
        ).showSaveFilePicker({
          suggestedName: getOutputFilename(format),
          types: [
            { description: desc, accept: { [mime]: [ext] } },
          ],
        });
      } catch {
        return;
      }

      const fps = Number(fpsSelect.value);
      const quality = qualityMap[qualitySelect.value];
      const def = visualizers[select.value as VisualizerName];
      const blob = await output(
        canvas,
        audioBuffer,
        def.draw,
        fps,
        quality,
        getOpts(),
        def.audioReactive,
        format,
        (current, total) => {
          overlay.textContent = `${Math.round((current / total) * 100)}%`;
        },
      );

      const writable = await handle.createWritable();
      await writable.write(blob);
      await writable.close();
      console.log("render done");
      return;
    }

    const fps = Number(fpsSelect.value);
    const quality = qualityMap[qualitySelect.value];
    const def = visualizers[select.value as VisualizerName];
    const blob = await output(
      canvas,
      audioBuffer,
      def.draw,
      fps,
      quality,
      getOpts(),
      def.audioReactive,
      format,
      (current, total) => {
        overlay.textContent = `${Math.round((current / total) * 100)}%`;
      },
    );

    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = getOutputFilename(format);
    a.click();
    URL.revokeObjectURL(url);
    console.log("render done");
  } finally {
    overlay.remove();
    renderBtn.disabled = false;
  }
}
