///|
/// abi module demo - ABI Sanger sequencing trace file parsing.
///
/// Demonstrates parsing of Applied Biosystems (ABIF) binary trace files
/// containing called bases, quality values, peak positions, and raw
/// chromatogram traces from Sanger sequencing.
///
/// Reference: Biopython Bio.SeqIO.AbiIO
/// Run: moon run examples/abi_demo
fn main {
  println("=== abi Module Demo ===")
  println("ABI Sanger sequencing trace file parsing")
  println("Reference: Biopython Bio.SeqIO.AbiIO")
  println("")

  // ------------------------------------------------------------------
  // 1. Sample trace creation and basic fields
  // ------------------------------------------------------------------
  println("=== 1. Sample Trace Creation ===")
  let trace = @bio.abi_sample_trace()
  println("Sample name: " + trace.sample_name)
  println("Capillary ID: " + trace.capillary_id)
  println("Run name: " + trace.run_name)
  println("Base order (FWO_): " + trace.base_order)
  println("Called bases: " + trace.bases)
  println("Number of bases: " + trace.num_bases.to_string())
  println("Number of trace points: " + trace.num_points.to_string())
  println("")

  // ------------------------------------------------------------------
  // 2. Run date and time
  // ------------------------------------------------------------------
  println("=== 2. Run Date and Time ===")
  println("Run date: " + trace.run_date.to_string())
  println("Run time: " + trace.run_time.to_string())
  println("")

  // ------------------------------------------------------------------
  // 3. Quality values
  // ------------------------------------------------------------------
  println("=== 3. Quality Values (Phred) ===")
  let mut i = 0
  while i < trace.qualities.length() {
    let q = trace.quality_at(i)
    let base = trace.bases[i:i + 1].to_owned()
    let label = if q >= 40 {
      "high"
    } else if q >= 20 {
      "medium"
    } else {
      "low"
    }
    println(
      "  pos " +
      i.to_string() +
      ": base=" +
      base +
      " Q=" +
      q.to_string() +
      " (" +
      label +
      ")",
    )
    i = i + 1
  }
  println("")

  // ------------------------------------------------------------------
  // 4. Peak positions
  // ------------------------------------------------------------------
  println("=== 4. Peak Positions ===")
  let mut p = 0
  let parts = StringBuilder()
  while p < trace.base_positions.length() {
    if p > 0 {
      parts.write_string(", ")
    }
    parts.write_string(trace.base_positions[p].to_string())
    p = p + 1
  }
  println("Base positions: [" + parts.to_string() + "]")
  println("")

  // ------------------------------------------------------------------
  // 5. Trace channels
  // ------------------------------------------------------------------
  println("=== 5. Trace Channels ===")
  let mut ch = 0
  while ch < trace.traces.length() {
    let channel = trace.traces[ch]
    let name = if ch < trace.trace_names.length() {
      trace.trace_names[ch]
    } else {
      "ch" + ch.to_string()
    }
    // Find max value in channel
    let mut max_val = 0
    let mut k = 0
    while k < channel.length() {
      if channel[k] > max_val {
        max_val = channel[k]
      }
      k = k + 1
    }
    println(
      "  " +
      name +
      ": " +
      channel.length().to_string() +
      " points, max=" +
      max_val.to_string(),
    )
    ch = ch + 1
  }
  println("")

  // ------------------------------------------------------------------
  // 6. Trace for specific base
  // ------------------------------------------------------------------
  println("=== 6. Trace for Specific Base ===")
  let g_trace = trace.trace_for_base("G")
  println("G trace length: " + g_trace.length().to_string())
  // Find peak positions in G trace
  println("G trace peaks (>500):")
  let mut peak_idx = 0
  while peak_idx < g_trace.length() {
    if g_trace[peak_idx] > 500 {
      println(
        "  point " + peak_idx.to_string() + ": " + g_trace[peak_idx].to_string(),
      )
    }
    peak_idx = peak_idx + 1
  }
  println("")

  // ------------------------------------------------------------------
  // 7. Binary encoding/decoding round trip
  // ------------------------------------------------------------------
  println("=== 7. Binary Encode/Decode ===")
  let bytes = @bio.abi_encode(trace)
  println("Encoded bytes: " + bytes.length().to_string() + " bytes")
  println(
    "Magic (first 4 bytes): " +
    bytes[0].to_string() +
    " " +
    bytes[1].to_string() +
    " " +
    bytes[2].to_string() +
    " " +
    bytes[3].to_string() +
    " (ABIF)",
  )
  let parsed = @bio.abi_parse(@bio.abi_sample_bytes())
  println(
    "Parsed from sample bytes: bases=" +
    parsed.bases +
    ", order=" +
    parsed.base_order,
  )
  println("")

  // ------------------------------------------------------------------
  // 8. Sequence length and statistics
  // ------------------------------------------------------------------
  println("=== 8. Sequence Statistics ===")
  println("Sequence length: " + trace.seq_length().to_string())
  let mut q_sum = 0
  for q in trace.qualities {
    q_sum = q_sum + q
  }
  let avg_q = if trace.qualities.length() > 0 {
    q_sum / trace.qualities.length()
  } else {
    0
  }
  println("Average quality: " + avg_q.to_string())
  println("")

  println("=== Demo complete ===")
}