///|
pub enum RuntimeTarget {
  Generic
  Godot
  Phaser
  MoonBit
} derive(Debug, Eq, ToJson, FromJson)

///|
pub struct RuntimeOptions {
  target : RuntimeTarget
  indent : Int
  include_diagnostics : Bool
  include_slices : Bool
} derive(Debug, Eq, ToJson, FromJson)

///|
pub fn RuntimeOptions::default(target~ : RuntimeTarget) -> RuntimeOptions {
  { target, indent: 2, include_diagnostics: true, include_slices: true }
}

///|
fn target_name(target : RuntimeTarget) -> String {
  match target {
    Generic => "generic"
    Godot => "godot"
    Phaser => "phaser"
    MoonBit => "moonbit"
  }
}

///|
fn runtime_metadata(bundle : ExportBundle, target : RuntimeTarget) -> String {
  let report = summarize_diagnostics(bundle.diagnostics)
  let name = target_name(target)
  "{\"format\":\"moonbit-aseflow\",\"target\":\"" +
  name +
  "\",\"image\":\"" +
  bundle.sheet.image +
  "\",\"atlas\":" +
  bundle.atlas.to_json_string(indent=0) +
  ",\"animations\":" +
  bundle.machine.to_json_string(indent=0) +
  ",\"nine_patches\":" +
  bundle.nine_patches.to_json().stringify(indent=0) +
  ",\"diagnostics\":{\"errors\":" +
  report.errors.to_string() +
  ",\"warnings\":" +
  report.warnings.to_string() +
  "}}"
}

///|
fn godot_resource(bundle : ExportBundle, _indent : Int) -> String {
  let machine = bundle.machine.to_json_string(indent=0)
  let atlas = bundle.atlas.to_json_string(indent=0)
  "{\"resource_format\":\"moonbit-aseflow/godot-spritesheet\",\"format_version\":1," +
  "\"texture\":\"" +
  bundle.sheet.image +
  "\",\"atlas\":" +
  atlas +
  ",\"animations\":" +
  machine +
  ",\"metadata\":{\"generator\":\"moonbit-aseflow\",\"deterministic\":true}}"
}

///|
fn phaser_manifest(bundle : ExportBundle) -> String {
  let machine = bundle.machine.to_json_string(indent=0)
  let frames = bundle.atlas.frames.to_json().stringify(indent=0)
  "{\"format\":\"phaser-atlas-json-hash\",\"textures\":\"" +
  bundle.sheet.image +
  "\",\"frames\":" +
  frames +
  ",\"animations\":" +
  machine +
  ",\"meta\":{\"scale\":1}}"
}

///|
fn moonbit_manifest(bundle : ExportBundle) -> String {
  let sheet = bundle.sheet.to_json().stringify(indent=0)
  let atlas = bundle.atlas.to_json_string(indent=0)
  "{\"format\":\"moonbit-aseflow\",\"module\":\"lllg123/moonbit-aseflow\"," +
  "\"sheet\":" +
  sheet +
  ",\"atlas\":" +
  atlas +
  ",\"machine\":" +
  bundle.machine.to_json_string(indent=0) +
  "}"
}

///|
pub fn export_runtime_bundle(
  bundle : ExportBundle,
  target~ : RuntimeTarget,
  indent? : Int = 2,
) -> String {
  let raw = match target {
    Godot => godot_resource(bundle, indent)
    Phaser => phaser_manifest(bundle)
    MoonBit => moonbit_manifest(bundle)
    Generic => runtime_metadata(bundle, target)
  }
  if indent == 0 {
    raw
  } else {
    raw
  }
}

///|
pub fn export_runtime_bundle_with_options(
  bundle : ExportBundle,
  options : RuntimeOptions,
) -> String {
  let payload = export_runtime_bundle(
    bundle,
    target=options.target,
    indent=options.indent,
  )
  if options.include_diagnostics && !payload.contains("diagnostics") {
    payload
  } else {
    payload
  }
}

///|
pub fn runtime_target_from_string(text : String) -> RuntimeTarget {
  match text {
    "godot" => Godot
    "phaser" => Phaser
    "moonbit" => MoonBit
    _ => Generic
  }
}

///|
pub fn runtime_targets() -> Array[RuntimeTarget] {
  [Generic, Godot, Phaser, MoonBit]
}

///|
pub fn runtime_target_names() -> Array[String] {
  runtime_targets().map(target_name)
}