/*
 * O vídeo que a pessoa põe na arte: antes de subir, o navegador abre o
 * arquivo para saber a duração e o tamanho e tira a capa (o quadro de 0,1 s,
 * em WebP), que é o que a peça mostra nas fotos, no PDF e no editor parado.
 */

export class VideoQueNaoAbre extends Error {}

/** Até quanto o arquivo pode ter. */
export const LIMITE_DO_VIDEO = 200 * 1024 * 1024;

const NAO_ABRE = "Este vídeo não abre no navegador. Converta para MP4 (H.264) e tente de novo.";

function esperarEvento(alvo: HTMLVideoElement, evento: string, ms: number) {
  return new Promise<void>((ok, falha) => {
    const pronto = () => {
      limpar();
      ok();
    };
    const erro = () => {
      limpar();
      falha(new VideoQueNaoAbre(NAO_ABRE));
    };
    const tempo = window.setTimeout(erro, ms);
    const limpar = () => {
      window.clearTimeout(tempo);
      alvo.removeEventListener(evento, pronto);
      alvo.removeEventListener("error", erro);
    };
    alvo.addEventListener(evento, pronto, { once: true });
    alvo.addEventListener("error", erro, { once: true });
  });
}

export async function lerVideo(arquivo: File): Promise<{ duracao: number; largura: number; altura: number; capa: Blob }> {
  const url = URL.createObjectURL(arquivo);
  const video = document.createElement("video");
  video.muted = true;
  video.playsInline = true;
  video.preload = "auto";
  try {
    const carregou = esperarEvento(video, "loadeddata", 20000);
    video.src = url;
    await carregou;
    const duracao = video.duration;
    if (!Number.isFinite(duracao) || duracao <= 0 || !video.videoWidth || !video.videoHeight) throw new VideoQueNaoAbre(NAO_ABRE);
    const buscou = esperarEvento(video, "seeked", 10000);
    video.currentTime = Math.min(0.1, duracao / 2);
    await buscou;
    const f = Math.min(1, 1280 / Math.max(video.videoWidth, video.videoHeight));
    const tela = document.createElement("canvas");
    tela.width = Math.round(video.videoWidth * f);
    tela.height = Math.round(video.videoHeight * f);
    tela.getContext("2d")!.drawImage(video, 0, 0, tela.width, tela.height);
    const capa = await new Promise<Blob | null>((ok) => tela.toBlob(ok, "image/webp", 0.85));
    if (!capa) throw new VideoQueNaoAbre(NAO_ABRE);
    return { duracao: Math.round(duracao * 100) / 100, largura: video.videoWidth, altura: video.videoHeight, capa };
  } finally {
    video.removeAttribute("src");
    video.load();
    URL.revokeObjectURL(url);
  }
}
