import * as VAPI from "../artefacts/vapi/index.js";
import { Logger, asyncIter } from "vscript";
import { is_higher_than_3G } from "./video.js";

type VideoDelayParams = {
  delay:
    | { variant: "Time"; value: VAPI.VideoPlayer.TimeSettings }
    | { variant: "Frames"; value: VAPI.VideoPlayer.FramesSettings };
  log: Logger;
  delay_mode: VAPI.VideoRePlay.DelayMode;
};

export async function delay_video(
  src: VAPI.AT1130.Video.Essence | VAPI.AT1101.Video.Essence,
  params?: Partial<VideoDelayParams>,
) {
  const vm = VAPI.VM.adopt(src.raw.backing_store);
  const pars: VideoDelayParams = {
    log: (msg, level) => {
      console.log(`[${level}]: ` + msg);
    },
    delay: { variant: "Frames", value: { frames: 1 } },
    delay_mode: "FrameSync_Freeze",
    ...params,
  };
  const delay = await vm.re_play!.video.delays.create_row();
  await delay.capabilities.command.write({
    delay_mode: "FrameSync_Freeze",
    capacity: pars.delay,
    input_caliber: {
      variant: "Single",
      value: {
        constraints: {
          variant: "Bandwidth",
          value: {
            max_bandwidth: is_higher_than_3G((await src.standard.read()) ?? "HD2160p50")
              ? "b12_0Gb"
              : "b3_0Gb",
          },
        },
        add_blanking: true,
      },
    },
  });
  await asyncIter(await delay.inputs.rows(), async (i) => {
    await i.v_src.command.write(src);
  });
  const genlock =
    vm instanceof VAPI.AT1130.Root
      ? vm.genlock!.instances.row(0).backend.output
      : vm.genlock!.output;
  const out = await delay.outputs.create_row();
  await out.t_src.command.write(genlock);
  await out.deembedded_audio.row(0).group.command.write("Group0");
  await out.deembedded_audio.row(1).group.command.write("Group1");
  await out.delay.offset.command.write(pars.delay);
  return delay;
}

type AudioDelayParams = {
  delay:
    | { variant: "Time"; value: VAPI.AudioRePlay.TimeSettings }
    | { variant: "Samples"; value: VAPI.AudioRePlay.SamplesSettings };
  log: Logger;
  audio_follow_video: boolean;
  dolby_e_aligner: boolean;
  measurement_reference: VAPI.AT1130.Video.Essence | VAPI.AT1101.Video.Essence | null;
};
export async function delay_audio(
  src: VAPI.AT1130.Audio.Essence | VAPI.AT1101.Audio.Essence,
  params?: Partial<AudioDelayParams>,
) {
  const vm = VAPI.VM.adopt(src.raw.backing_store);
  const pars: AudioDelayParams = {
    log: (msg, level) => {
      console.log(`[${level}]: ` + msg);
    },
    delay: { variant: "Samples", value: { samples: 10 } },
    audio_follow_video: false,
    dolby_e_aligner: false,
    measurement_reference: null,
    ...params,
  };
  const delay = await vm.re_play!.audio.delays.create_row();
  await delay.capabilities.capacity.command.write(pars.delay);
  await delay.inputs.a_src.command.write(src);
  const genlock =
    vm instanceof VAPI.AT1130.Root
      ? vm.genlock!.instances.row(0).backend.output
      : vm.genlock!.output;
  const out = delay.outputs.row(0);
  if (out instanceof VAPI.AT1130.AudioRePlay.DelayOutput)
    await out.time.t_src.command.write(genlock);
  await out.delay.offset.command.write(pars.delay);
  await out.delay.measurement_reference.command.write(pars.measurement_reference);
  await out.delay.audio_follow_video.command.write(pars.audio_follow_video);
  await out.delay.auto_dolby_e_aligner.command.write(pars.dolby_e_aligner);
  return delay;
}
