import React from "react";
import {Video} from "@remotion/media";
import {
  AbsoluteFill,
  Sequence,
  staticFile,
  useCurrentFrame,
  useVideoConfig,
} from "remotion";
import {
  audioFileForSpeech,
  durationForSpeech,
  hasAudioForSpeech,
  PIZZA_KILN_GAP_FRAMES,
  PIZZA_KILN_VIDEO_FRAMES,
} from "./data/pizza-kiln/timing";
import {
  characters,
  timeline,
  type SpeechEvent,
} from "./data/pizza-kiln/script";
import {roundedFontFamily} from "./fonts";
import {
  VQSpeechOverlay,
  VQStageCornerStandee,
  VQWarmGradientBackground,
  vqSpeakingAvatarAnimations,
} from "./lib/VQRemotionLib";
import {getMouthForSpeechFrame} from "./lipsync/manifest";

const BACKGROUND_VIDEO_PATH = "video/pizza-kiln-background.mp4";
const pizzaSubtitleOptions = {
  fontFamily: roundedFontFamily,
  fontSize: 34,
  lineHeight: 1.45,
  backgroundColor: "rgba(255, 255, 255, 0.9)",
} as const;

const SayoStandee: React.FC<
  Readonly<{
    mode: "stage" | "corner";
    speaking: boolean;
    localFrame: number;
    fps: number;
    speechId?: string;
  }>
> = ({mode, speaking, localFrame, fps, speechId}) => {
  const {avatar} = characters.sayo;
  const speakingAnimationType = avatar.speakingAnimationType ?? "none";
  const translateY = speaking
    ? vqSpeakingAvatarAnimations[speakingAnimationType]({
        frame: localFrame,
        fps,
        focused: true,
        hasMultipleCharacters: false,
      })
    : 0;
  const mouth =
    speaking && speakingAnimationType === "rhubarbLipSync"
      ? getMouthForSpeechFrame(speechId, localFrame, fps)
      : "rest";
  return (
    <VQStageCornerStandee
      mode={mode}
      imagePath={avatar.imagePath}
      mouthImageDir={avatar.mouthImageDir}
      mouth={mouth}
      translateY={translateY}
      zIndex={3}
    />
  );
};

const SpeechOverlay: React.FC<Readonly<{speech: SpeechEvent}>> = ({speech}) => {
  const character = characters[speech.character];

  return (
    <VQSpeechOverlay
      speech={speech}
      speakerName={character.displayName}
      accentColor={character.avatar.accentColor}
      hasAudio={hasAudioForSpeech}
      getAudioPath={audioFileForSpeech}
      subtitleOptions={pizzaSubtitleOptions}
      containerStyle={{zIndex: 4}}
    />
  );
};

export const PizzaKilnSayoComposition: React.FC = () => {
  const frame = useCurrentFrame();
  const {fps} = useVideoConfig();
  const introSpeech = timeline[0];
  const outroSpeech = timeline[1];
  const introFrames = durationForSpeech(introSpeech, fps);
  const outroFrames = durationForSpeech(outroSpeech, fps);
  const videoFrom = introFrames + PIZZA_KILN_GAP_FRAMES;
  const outroFrom = videoFrom + PIZZA_KILN_VIDEO_FRAMES + PIZZA_KILN_GAP_FRAMES;
  const isVideoVisible =
    frame >= videoFrom && frame < videoFrom + PIZZA_KILN_VIDEO_FRAMES;
  const isOutro = frame >= outroFrom;
  const activeSpeech =
    frame < introFrames ? introSpeech : isOutro ? outroSpeech : undefined;
  const speechLocalFrame = activeSpeech === outroSpeech ? frame - outroFrom : frame;

  return (
    <AbsoluteFill style={{backgroundColor: "#1a1a1a"}}>
      <VQWarmGradientBackground />
      <Sequence
        from={videoFrom}
        durationInFrames={PIZZA_KILN_VIDEO_FRAMES}
        premountFor={Math.min(fps, videoFrom)}
      >
        <Video
          muted
          objectFit="cover"
          src={staticFile(BACKGROUND_VIDEO_PATH)}
          style={{
            width: "100%",
            height: "100%",
          }}
        />
      </Sequence>
      <SayoStandee
        mode={isVideoVisible ? "corner" : "stage"}
        speaking={Boolean(activeSpeech)}
        localFrame={speechLocalFrame}
        fps={fps}
        speechId={activeSpeech?.id}
      />
      <Sequence durationInFrames={introFrames} premountFor={0}>
        <SpeechOverlay speech={introSpeech} />
      </Sequence>
      <Sequence
        from={outroFrom}
        durationInFrames={outroFrames}
        premountFor={Math.min(fps, outroFrom)}
      >
        <SpeechOverlay speech={outroSpeech} />
      </Sequence>
    </AbsoluteFill>
  );
};
