import {
  audio,
  wait,
  defineVQTimeline,
  say,
  still,
  standeeDefaultImage,
  standeeFacingDirection,
  standeeImage,
  standeeShake,
  standeeVerticalOffset,
  type VQCustomTimelineEvent,
  type VQStandeeFacingDirectionEvent,
  type VQStandeeImageEvent,
  type VQStandeeShakeEvent,
  type VQStandeeVerticalOffsetEvent,
  type VQSpeechEvent,
  type VQTimelineEvent,
  type VQTimelineInputEvent,
} from "../../lib/VQRemotionLib/timeline";
import type {CharacterId, VoicevoxVoice} from "./characters";

export {characters, initialVisibleCharacters} from "./characters";
export type {CharacterDefinition, CharacterId, VoicevoxVoice} from "./characters";

export const compositionTitle = "ずんだもんの持論";

export type ShowOptions = Readonly<{
  caption?: string;
  durationSeconds?: number;
}>;

export type SpeechEvent = VQSpeechEvent<CharacterId, VoicevoxVoice>;

export type ShowEvent = VQCustomTimelineEvent<
  "show",
  {
    character: CharacterId;
    caption?: string;
    durationSeconds?: number;
  }
>;

export type HideTitleEvent = VQCustomTimelineEvent<
  "hideTitle",
  {
    id: string;
  }
>;

export type TimelineEvent = VQTimelineEvent<
  CharacterId,
  VoicevoxVoice,
  | ShowEvent
  | HideTitleEvent
  | VQStandeeFacingDirectionEvent<CharacterId>
  | VQStandeeImageEvent<CharacterId>
  | VQStandeeShakeEvent<CharacterId>
  | VQStandeeVerticalOffsetEvent<CharacterId>
>;
export type TimelineInputEvent = VQTimelineInputEvent<
  CharacterId,
  VoicevoxVoice,
  | ShowEvent
  | HideTitleEvent
  | VQStandeeFacingDirectionEvent<CharacterId>
  | VQStandeeImageEvent<CharacterId>
  | VQStandeeShakeEvent<CharacterId>
  | VQStandeeVerticalOffsetEvent<CharacterId>
>;

// 用途: キャラクターを画面に登場させ、任意の説明字幕を表示する。
// 使用方法: timeline 内で show("sayo", {caption: "小夜が登場！"}) のように呼び出す。
// オプションや引数詳細: durationSeconds を省略すると timing.ts の既定秒数で表示する。
export const show = (
  character: CharacterId,
  options: ShowOptions = {}
): ShowEvent => ({
  type: "show",
  character,
  ...options,
});

export const hideTitle = (id: string): HideTitleEvent => ({
  type: "hideTitle",
  id,
});

export const timeline = defineVQTimeline([
  still("zundamon-jiron-background-001", "image/still/nc238325_living_day.jpg", {
    fit: "cover",
  }),
  audio("zundamon-jiron-bgm-001", "audio/common_bgm/saturn-3-music-rockabye-baby-music-box-lullaby-loopable-527146.mp3", {
    playback: "loop",
    volume: 0.2,
  }),
  say("zundamon-jiron-zunda-001", "zundamon", "ふー、着替えて落ち着いたのだ。"),
  say("zundamon-jiron-zunda-002", "zundamon", "やっぱり寮ではこのスタイルが一番なのだ。"),
  hideTitle("zundamon-jiron-hide-title-001"),
  standeeVerticalOffset("zundamon-jiron-zunda-y-001", "zundamon", -20),
  audio("zundamon-jiron-sound-effect-001", "audio/common_soundeffect/Door 6_5 Open.wav",
    {
      playback: "once",
      durationSeconds: 1.5,
    }
  ),
  show("sayo", { }),
  say("zundamon-jiron-sayo-001", "sayo", "あ、ずんだもんだ。"),
  standeeFacingDirection("zundamon-jiron-zunda-facing-001", "zundamon", "right"),
  say("zundamon-jiron-sayo-002", "sayo", "あったかくなってきたにしても、おむつ一枚はちょっとラフすぎない？"),
  say("zundamon-jiron-zunda-003", "zundamon", "そんなことないのだ！これが夏のベストスタイルなのだ！"),
  say("zundamon-jiron-zunda-004", "zundamon", "小夜もこのスタイルにしてみればいいのだ。たぶん似合うし、快適なのだ！"),
  say("zundamon-jiron-sayo-003", "sayo", "えー、小夜はいいかな。なんか、清潔かどうか気になるし…。"),
  standeeImage("zundamon-jiron-zunda-image-001", "zundamon", "image/zundamon-ohnegus-rework-baby/36-round-eyes-small-a.png", {
    lipSync: false,
  }),
  say("zundamon-jiron-zunda-005", "zundamon", "それは偏見なのだ！"),
  say("zundamon-jiron-zunda-006", "zundamon", "考えてみるのだ。紙おむつは常に新品をあてることになるから、むしろ清潔なのだ！"),
  say("zundamon-jiron-zunda-007", "zundamon", "毎回おろしたての下着を身につけるようなものなのだ。洗濯して使い続ける下着よりも清潔なのは明らかなのだ。"),
  say("zundamon-jiron-sayo-004", "sayo", "うーん、そう言われると確かにそうかも…。"),
  standeeDefaultImage("zundamon-jiron-zunda-image-002", "zundamon"),
  say("zundamon-jiron-zunda-008", "zundamon", "わかったのだ？だからみんなもこのスタイルを試してみるといいのだ！"),
  say("zundamon-jiron-sayo-005", "sayo", "言ってることは、たぶん間違ってないんだけど……。\n清潔なのは「穿いた直後」だけじゃない？",
    {
      readAs: "いってることは、たぶんまちがってないんだけど……。\nせいけつなのは、はいたちょくごだけじゃない？",
    }
  ),
  standeeImage("zundamon-jiron-zunda-image-003", "zundamon", "image/zundamon-ohnegus-rework-baby/45-nnaa-n.png", {
    lipSync: false,
  }),
  say("zundamon-jiron-zunda-009", "zundamon", "うっ…！"),
  audio("zundamon-jiron-sound-effect-002", "audio/common_soundeffect/nc174220_osikko7.mp3",
    {
      playback: "once",
      durationSeconds: 10.0,
    }
  ),
  standeeShake("zundamon-jiron-zunda-shake-001", "zundamon", {
    durationSeconds: 2.0,
    amplitudeX: 9,
    amplitudeY: 6,
    frequencyHz: 16,
  }),
  wait(2.0),
  standeeDefaultImage("zundamon-jiron-zunda-image-004", "zundamon"),
  say("zundamon-jiron-zunda-010", "zundamon", "……ちょうどいま、清潔じゃなくなったのだ。"),
  say("zundamon-jiron-sayo-006", "sayo", "そうだね…。"),
  standeeImage("zundamon-jiron-sayo-image-001", "sayo", "image/sayo_by_sayonaka/variants/sayo_006_embarrassed.png", {
    lipSync: false,
  }),
  say("zundamon-jiron-sayo-007", "sayo", "（……でも、漏らさずに使うなら、ずんだもんが言うこともわかるかも？）"),
  say("zundamon-jiron-zunda-011", "zundamon", "こまめに替えれば大丈夫なのだ！\nなので、小夜もおむつスタイルを試してみるといいのだ！"),
  standeeDefaultImage("zundamon-jiron-sayo-image-002", "sayo"),
  say("zundamon-jiron-sayo-008", "sayo", "考えておくね。\nずんだもんは早くおむつ替えてね。"),
  say("zundamon-jiron-zunda-012", "zundamon", "そうするのだ！"),
  wait(4.0),
] satisfies readonly TimelineInputEvent[]);
