export type VoicevoxVoice = Readonly<{
  speakerName: string;
  styleName: string;
}>;

export type AvatarDefinition = Readonly<{
  kind: "zundamon" | "sayo";
  accentColor: string;
  imagePath?: string;
}>;

export type CharacterDefinition = Readonly<{
  displayName: string;
  voicevox: VoicevoxVoice;
  avatar: AvatarDefinition;
}>;

export const characters = {
  zundamon: {
    displayName: "ずんだもん",
    voicevox: {
      speakerName: "ずんだもん",
      styleName: "ノーマル",
    },
    avatar: {
      kind: "zundamon",
      accentColor: "#79d36f",
    },
  },
  sayo: {
    displayName: "小夜",
    voicevox: {
      speakerName: "小夜/SAYO",
      styleName: "ノーマル",
    },
    avatar: {
      kind: "sayo",
      accentColor: "#6b5f83",
    },
  },
} as const satisfies Record<string, CharacterDefinition>;

export type CharacterId = keyof typeof characters;

export type SpeechOptions = Readonly<{
  subtitle?: string;
  voicevox?: Partial<VoicevoxVoice>;
}>;

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

export type SpeechEvent = Readonly<{
  type: "say";
  id: string;
  character: CharacterId;
  text: string;
  subtitle?: string;
  voicevox?: Partial<VoicevoxVoice>;
}>;

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

export type TimelineEvent = SpeechEvent | ShowEvent;

export const say = (
  id: string,
  character: CharacterId,
  text: string,
  options: SpeechOptions = {}
): SpeechEvent => ({
  type: "say",
  id,
  character,
  text,
  ...options,
});

export const show = (
  character: CharacterId,
  options: ShowOptions = {}
): ShowEvent => ({
  type: "show",
  character,
  ...options,
});

export const initialVisibleCharacters: CharacterId[] = ["zundamon"];

export const timeline: TimelineEvent[] = [
  say("zunda-001", "zundamon", "みなさんこんにちは、ずんだもんなのだ！"),
  say(
    "zunda-002",
    "zundamon",
    "今日のテーマは「ネコミミはなぜかわいいのか？」なのだ。"
  ),
  say(
    "zunda-003",
    "zundamon",
    "まず大きな理由は、丸みのあるシルエットと動きなのだ。"
  ),
  say(
    "zunda-004",
    "zundamon",
    "そして感情が伝わりやすくて、親近感が増すのだ！"
  ),
  show("sayo", {
    caption: "ネコミミ代表として、小夜が登場！",
  }),
  say(
    "sayo-001",
    "sayo",
    "小夜です。ネコミミ代表として、猫耳のかわいさを証明しに来ました。"
  ),
  say("zunda-005", "zundamon", "それじゃあ、また次回なのだ！"),
];

export const isSpeechEvent = (
  event: TimelineEvent
): event is SpeechEvent => event.type === "say";

export const script = timeline.filter(isSpeechEvent);
