///|
/// meme module demo - MEME motif format parsing.
///
/// Demonstrates parsing of MEME Minimal Motif Format files containing
/// position-specific probability matrices (PSPMs) for discovered motifs,
/// including consensus generation and information content calculation.
///
/// Reference: Biopython Bio.motifs.meme
/// Run: moon run examples/meme_demo
fn main {
  println("=== meme Module Demo ===")
  println("MEME motif format parsing")
  println("Reference: Biopython Bio.motifs.meme")
  println("")

  // ------------------------------------------------------------------
  // 1. Parse sample MEME text
  // ------------------------------------------------------------------
  println("=== 1. Parse Sample MEME Text ===")
  let text = @bio.meme_sample_text()
  let record = @bio.meme_parse(text)
  println("MEME version: " + record.version)
  println("Alphabet: " + record.alphabet)
  println("Strands: " + record.strands)
  println("Number of motifs: " + record.num_motifs().to_string())
  println("")

  // ------------------------------------------------------------------
  // 2. Background frequencies
  // ------------------------------------------------------------------
  println("=== 2. Background Letter Frequencies ===")
  let mut bi = 0
  while bi < record.background_frequencies.length() {
    let pair = record.background_frequencies[bi]
    println("  " + pair.0 + ": " + pair.1.to_string())
    bi = bi + 1
  }
  println("")

  // ------------------------------------------------------------------
  // 3. Motif details
  // ------------------------------------------------------------------
  println("=== 3. Motif Details ===")
  let mut i = 0
  while i < record.motifs.length() {
    let m = record.motifs[i]
    println("Motif " + (i + 1).to_string() + ":")
    println("  Name: " + m.name)
    println("  Alt name: " + m.alt_name)
    println("  Width: " + m.width.to_string())
    println("  Nsites: " + m.nsites.to_string())
    println("  E-value: " + m.evalue.to_string())
    println("  Strands: " + m.strands)
    if m.url.length() > 0 {
      println("  URL: " + m.url)
    }
    println("  Consensus: " + m.consensus())
    println(
      "  Information content: " + m.information_content().to_string() + " bits",
    )
    i = i + 1
  }
  println("")

  // ------------------------------------------------------------------
  // 4. Position-Specific Probability Matrix
  // ------------------------------------------------------------------
  println("=== 4. PSPM Matrix (first motif) ===")
  if record.motifs.length() > 0 {
    let m = record.motifs[0]
    let alphabet = m.alphabet_to_array()
    // Header
    let header = StringBuilder()
    header.write_string("  pos  ")
    for a in alphabet {
      header.write_string("   " + a + "   ")
    }
    println(header.to_string())
    // Rows
    let mut pos = 0
    while pos < m.pspm.length() {
      let row = m.pspm[pos]
      let line = StringBuilder()
      line.write_string("  " + pos.to_string() + "   ")
      let mut j = 0
      while j < row.length() {
        let val = row[j]
        let raw = val.to_string()
        let s = if raw.length() > 4 { raw[0:4].to_owned() } else { raw }
        // Pad to 4 chars
        let padded = if s.length() >= 4 {
          s
        } else {
          s + "    "[0:4 - s.length()].to_owned()
        }
        line.write_string(" " + padded + " ")
        j = j + 1
      }
      println(line.to_string())
      pos = pos + 1
    }
  }
  println("")

  // ------------------------------------------------------------------
  // 5. Probability lookup
  // ------------------------------------------------------------------
  println("=== 5. Probability Lookup ===")
  if record.motifs.length() > 0 {
    let m = record.motifs[0]
    println("P(A at pos 0) = " + m.probability("A", 0).to_string())
    println("P(C at pos 0) = " + m.probability("C", 0).to_string())
    println("P(G at pos 0) = " + m.probability("G", 0).to_string())
    println("P(T at pos 0) = " + m.probability("T", 0).to_string())
  }
  println("")

  // ------------------------------------------------------------------
  // 6. Find motif by name
  // ------------------------------------------------------------------
  println("=== 6. Find Motif by Name ===")
  if record.motifs.length() > 0 {
    let name = record.motifs[0].name
    match record.find(name) {
      Some(m) =>
        println("Found motif '" + name + "': width=" + m.width.to_string())
      None => println("Motif '" + name + "' not found")
    }
    match record.find("nonexistent") {
      Some(_) => println("Unexpected: found nonexistent motif")
      None => println("Correctly did not find 'nonexistent'")
    }
  }
  println("")

  // ------------------------------------------------------------------
  // 7. Sample motif and information content
  // ------------------------------------------------------------------
  println("=== 7. Sample Motif ===")
  let sample = @bio.meme_sample_motif()
  println("Created motif: " + sample.name)
  println("  Width: " + sample.width.to_string())
  println("  Consensus: " + sample.consensus())
  println(
    "  Information content: " +
    sample.information_content().to_string() +
    " bits",
  )
  println("")

  // ------------------------------------------------------------------
  // 8. Serialize record to string
  // ------------------------------------------------------------------
  println("=== 8. Serialize Record ===")
  let serialized = @bio.meme_record_to_string(record)
  let lines = serialized.split("\n").to_array()
  println("Serialized record (" + lines.length().to_string() + " lines):")
  let mut l = 0
  while l < 5 && l < lines.length() {
    println("  " + lines[l].to_owned())
    l = l + 1
  }
  println("  ...")
  println("")

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