import { RunOutput } from "@p-stream/providers";
import DOMPurify from "dompurify";
import { convert, detect, parse } from "subsrt-ts";
import { ContentCaption } from "subsrt-ts/dist/types/handler";

import { CaptionListItem } from "@/stores/player/slices/source";

export type CaptionCueType = ContentCaption;
export const sanitize = DOMPurify.sanitize;

export function captionIsVisible(
  start: number,
  end: number,
  delay: number,
  currentTime: number,
) {
  const delayedStart = start / 1000 + delay;
  const delayedEnd = end / 1000 + delay;
  return (
    Math.max(0, delayedStart) <= currentTime &&
    Math.max(0, delayedEnd) >= currentTime
  );
}

export function makeQueId(index: number, start: number, end: number): string {
  return `${index}-${start}-${end}`;
}

export function convertSubtitlesToVtt(text: string): string {
  const textTrimmed = text.trim();
  if (textTrimmed === "") {
    throw new Error("Given text is empty");
  }
  const vtt = convert(textTrimmed, "vtt");
  if (detect(vtt) === "") {
    throw new Error("Invalid subtitle format");
  }
  return vtt;
}

export function convertSubtitlesToSrt(text: string): string {
  const textTrimmed = text.trim();
  if (textTrimmed === "") {
    throw new Error("Given text is empty");
  }
  const srt = convert(textTrimmed, "srt");
  if (detect(srt) === "") {
    throw new Error("Invalid subtitle format");
  }
  return srt;
}

export function filterDuplicateCaptionCues(cues: ContentCaption[]) {
  return cues.reduce((acc: ContentCaption[], cap: ContentCaption) => {
    const lastCap = acc[acc.length - 1];
    const isSameAsLast =
      lastCap?.start === cap.start &&
      lastCap?.end === cap.end &&
      lastCap?.content === cap.content;
    if (lastCap === undefined || !isSameAsLast) {
      acc.push(cap);
    }
    return acc;
  }, []);
}

export function parseVttSubtitles(vtt: string) {
  return parse(vtt).filter((cue) => cue.type === "caption") as CaptionCueType[];
}

export function parseSubtitles(
  text: string,
  _language?: string,
): CaptionCueType[] {
  const vtt = convertSubtitlesToVtt(text);
  return parseVttSubtitles(vtt);
}

function stringToBase64(input: string): string {
  return btoa(String.fromCodePoint(...new TextEncoder().encode(input)));
}

export function convertSubtitlesToSrtDataurl(text: string): string {
  return `data:application/x-subrip;base64,${stringToBase64(
    convertSubtitlesToSrt(text),
  )}`;
}

export function convertSubtitlesToObjectUrl(text: string): string {
  return URL.createObjectURL(
    new Blob([convertSubtitlesToVtt(text)], {
      type: "text/vtt",
    }),
  );
}

export function convertProviderCaption(
  captions: RunOutput["stream"]["captions"],
): CaptionListItem[] {
  return captions.map((v) => ({
    id: v.id,
    language: v.language,
    url: v.url,
    type: (v as any).type,
    needsProxy: v.hasCorsRestrictions,
    opensubtitles: v.opensubtitles,
    // subtitle details from wyzie
    display: (v as any).display,
    media: (v as any).media,
    isHearingImpaired: (v as any).isHearingImpaired,
    source: (v as any).source,
    encoding: (v as any).encoding,
  }));
}
