// types.mbt - Shared data structures for mdcourse

///|
/// Slide information
priv struct SlideInfo {
  id : String
  ssml_hash : String
  has_audio : Bool
} derive (
  ToJson(fields(ssml_hash(rename="ssmlHash"), has_audio(rename="hasAudio"))),
  FromJson(fields(ssml_hash(rename="ssmlHash"), has_audio(rename="hasAudio"))),
)

///|
/// Video segment that follows a slide
priv struct VideoSegment {
  after_slide : String
  video_path : String
  ssml_hash : String
  has_audio : Bool
} derive (
  ToJson(
    fields(
      after_slide(rename="afterSlide"),
      video_path(rename="videoPath"),
      ssml_hash(rename="ssmlHash"),
      has_audio(rename="hasAudio"),
    ),
  ),
  FromJson(
    fields(
      after_slide(rename="afterSlide"),
      video_path(rename="videoPath"),
      ssml_hash(rename="ssmlHash"),
      has_audio(rename="hasAudio"),
    ),
  ),
)

///|
/// Manifest file structure
priv struct Manifest {
  slides : Array[SlideInfo]
  videos : Array[VideoSegment]
} derive(ToJson, FromJson)

///|
/// Audio metadata
priv struct AudioMeta {
  duration : Double
  hash : String
} derive(ToJson, FromJson)

///|
/// Segment metadata for caching (slide or video segment)
priv struct SegmentMeta {
  duration : Double
  content_hash : String // Hash of slide image or video file
  audio_hash : String // Hash of audio SSML (empty if no audio)
} derive (
  ToJson(
    fields(content_hash(rename="contentHash"), audio_hash(rename="audioHash")),
  ),
  FromJson(
    fields(content_hash(rename="contentHash"), audio_hash(rename="audioHash")),
  ),
)

///|
/// CLI options
pub struct Options {
  input_file : String
  output_file : String?
  parse_only : Bool
  slides_only : Bool
  audio_only : Bool
  compose_only : Bool
  force_audio : Bool
  keep_temp : Bool
  voice : String
  fps : Int
  resolution : String
  default_duration : Double
  theme : String
  engine : String
}

///|
/// Resolution preset
priv struct Resolution {
  width : Int
  height : Int
}

///|
/// Parse resolution preset to width and height
fn parse_resolution(preset : String) -> Resolution {
  match preset {
    "4k" | "4K" => { width: 3840, height: 2160, }
    "1440p" | "1440P" => { width: 2560, height: 1440, }
    "1080p" | "1080P" => { width: 1920, height: 1080, }
    "720p" | "720P" => { width: 1280, height: 720, }
    "480p" | "480P" => { width: 854, height: 480, }
    _ => { width: 1920, height: 1080, } // default to 1080p
  }
}

///|
/// Get resource directory (either MDCOURSE_DIR env var or current directory)
fn get_resource_dir() -> String {
  match @env.get_env_vars().get("MDCOURSE_DIR") {
    Some(dir) => dir
    None => "."
  }
}

///|
/// Create Options from parsed CLI arguments
pub fn Options::new(
  voice : String,
  fps : Int,
  resolution : String,
  force_audio : Bool,
  keep_temp : Bool,
  default_duration : Double,
  output_file : String?,
) -> Options {
  let resource_dir = get_resource_dir()
  let theme_path = if resource_dir == "." {
    "custom.css"
  } else {
    resource_dir + "/custom.css"
  }
  let engine_path = if resource_dir == "." {
    "engine.mjs"
  } else {
    resource_dir + "/engine.mjs"
  }
  {
    input_file: "",
    output_file,
    parse_only: false,
    slides_only: false,
    audio_only: false,
    compose_only: false,
    force_audio,
    keep_temp,
    voice,
    fps,
    resolution,
    default_duration,
    theme: theme_path,
    engine: engine_path,
  }
}