///|
/// NibIO module demo - UCSC nib 2-bit binary sequence format reader/writer.
///
/// Run: moon run examples/nib_io_demo
fn main {
  println("=== NibIO Module Demo ===")
  println("UCSC nib 2-bit binary sequence format")
  println("Reference: BioPython Bio.SeqIO.NibIO")
  println("")

  // ------------------------------------------------------------------
  // 1. Base encoding table (T=0, C=1, A=2, G=3)
  // ------------------------------------------------------------------
  println("=== 1. Base encoding (T=0, C=1, A=2, G=3) ===")
  let bases = ['T', 'C', 'A', 'G']
  for i in 0.. \{code}")
  }
  println("Reverse (code -> base):")
  for c in 0..<4 {
    let base = @bio.nib_code_to_base(c)
    println("  \{c} -> \{base}")
  }
  let bad = @bio.nib_base_to_code('N')
  println("  N -> \{bad} (invalid, returns -1)")
  println("")

  // ------------------------------------------------------------------
  // 2. Create a NibSequence from a DNA string
  // ------------------------------------------------------------------
  println("=== 2. Create a NibSequence ===")
  let dna = "ATGCATGCATGC"
  let nib = @bio.NibSequence::new("demo1", dna)
  println("Sequence: \{dna}")
  println(nib.to_string())
  println("")

  // ------------------------------------------------------------------
  // 3. Display hex encoding of the packed data
  // ------------------------------------------------------------------
  println("=== 3. Hex encoding ===")
  let hex = @bio.nib_to_hex(nib)
  println("Packed hex: \{hex}")
  println("Packed bytes: \{nib.packed_data().length()}")
  let pb = nib.packed_data()
  let pack_sb = StringBuilder()
  pack_sb.write_string("  bytes: ")
  for i in 0.. 0 {
      pack_sb.write_string(", ")
    }
    pack_sb.write_string(pb[i].to_string())
  }
  println(pack_sb.to_string())
  println("")

  // ------------------------------------------------------------------
  // 4. Decode back to a DNA string
  // ------------------------------------------------------------------
  println("=== 4. Decode back ===")
  let decoded = @bio.nib_to_string(nib)
  println("Decoded: \{decoded}")
  println("Round-trip OK: \{decoded == dna}")
  println("")

  // ------------------------------------------------------------------
  // 5. Extract a subsequence
  // ------------------------------------------------------------------
  println("=== 5. Subsequence extraction ===")
  let sub = @bio.nib_subsequence(nib, 2, 6)
  println("Subsequence (start=2, length=6): \{sub}")
  println("Single base at index 5: \{@bio.nib_get_base(nib, 5)}")
  println("")

  // ------------------------------------------------------------------
  // 6. Reverse complement
  // ------------------------------------------------------------------
  println("=== 6. Reverse complement ===")
  let rc = @bio.nib_reverse_complement(nib)
  println("Original:  \{dna}")
  println("Rev-comp:  \{@bio.nib_to_string(rc)}")
  println("Rev-comp id: \{rc.seq_id()}")
  println("")

  // ------------------------------------------------------------------
  // 7. GC content
  // ------------------------------------------------------------------
  println("=== 7. GC content ===")
  let gc = @bio.nib_gc_content(nib)
  println("GC fraction: \{gc}")
  println("GC percentage: \{gc * 100.0}%")
  println("")

  // ------------------------------------------------------------------
  // 8. Compression ratio
  // ------------------------------------------------------------------
  println("=== 8. Compression ratio ===")
  let ratio = @bio.nib_compression_ratio(nib)
  println("Original size: \{@bio.nib_size(nib)} bytes (1 byte/base)")
  println("Packed size: \{@bio.nib_compressed_size(nib)} bytes (4 bases/byte)")
  println("Compression ratio: \{ratio}")
  println("")

  // ------------------------------------------------------------------
  // 9. Hex round-trip
  // ------------------------------------------------------------------
  println("=== 9. Hex round-trip ===")
  let nib2 = @bio.nib_from_hex("from_hex", hex, dna.length())
  println("From hex: \{@bio.nib_to_string(nib2)}")
  println("Hex round-trip OK: \{@bio.nib_to_string(nib2) == dna}")
  println("")

  // ------------------------------------------------------------------
  // 10. Lowercase handling
  // ------------------------------------------------------------------
  println("=== 10. Lowercase handling ===")
  let lower = @bio.NibSequence::new("lower", "atgcatgcatgc")
  println("Lowercase input: atgcatgcatgc")
  println("is_uppercase flag: \{lower.is_uppercase()}")
  println("Decoded: \{@bio.nib_to_string(lower)}")
  println("Hex (same as uppercase): \{@bio.nib_to_hex(lower)}")
  println("")

  // ------------------------------------------------------------------
  // 11. Load sample data
  // ------------------------------------------------------------------
  println("=== 11. Sample data ===")
  let sample = @bio.nib_sample_data()
  println(sample.to_string())
  println("Decoded: \{@bio.nib_to_string(sample)}")
  println("Hex: \{@bio.nib_to_hex(sample)}")
  println("GC content: \{@bio.nib_gc_content(sample) * 100.0}%")
  println("")

  // ------------------------------------------------------------------
  // 12. Summary of odd-length encoding
  // ------------------------------------------------------------------
  println("=== 12. Odd-length encoding ===")
  let odd = @bio.NibSequence::new("odd", "ATGCA")
  println("Sequence 'ATGCA' (5 bases, not a multiple of 4)")
  println("Packed bytes: \{@bio.nib_compressed_size(odd)} (ceil(5/4) = 2)")
  println("Hex: \{@bio.nib_to_hex(odd)}")
  println("Decoded: \{@bio.nib_to_string(odd)}")
  println("Compression ratio: \{@bio.nib_compression_ratio(odd)}")
  println("")

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