///|
/// NGS quality trimming demo.
///
/// Demonstrates parsing FASTQ data, quality trimming reads, adapter
/// removal, length and GC filtering, batch processing, and
/// trimming statistics computation.
///
/// Run: moon run examples/seq_quality_trim_demo/main.mbt
fn main {
  println("=== NGS Quality Trimming Demo ===")
  println("")

  // Sample FASTQ data with various quality profiles
  let fastq_data = "@read1 high_quality\nACGTACGTACGTACGT\n+\nIIIIIIIIIIIIIIII\n@read2 adapter_contaminated\nACGTACGTAGATCGGAA\n+\nIIIIIIIIIIIIIIIII\n@read3 low_quality_ends\nACGTACGTACGT\n+\nIIIIIIII####\n@read4 poly_A_tail\nACGTACGGGGAAAA\n+\nIIIIIIIIIIIIII\n@read5 short_read\nACGT\n+\nIIII\n@read6 extreme_gc\nGGGGGGGGGGGGCCCC\n+\nIIIIIIIIIIIIIIII\n"

  println("1. Parsing FASTQ data")
  let reads = @bio.sqt_fastq_parse(fastq_data)
  println("   Reads parsed: \{reads.length()}")
  let mut i = 0
  while i < reads.length() {
    let r = reads[i]
    println(
      "     \{r.id}: seq_len=\{r.sequence.length()}, qual_len=\{r.quality.length()}",
    )
    i = i + 1
  }

  println("")
  println("2. Quality trimming (min_quality=20)")
  println("   Trimming low-quality bases from both ends...")
  let seq = "ACGTACGTACGT"
  let qual = "IIIIIIII####"
  let (trimmed_seq, _) = @bio.sqt_quality_trim(seq, qual, min_qual=20)
  println("   Original seq:   \{seq} (len=\{seq.length()})")
  println("   Original qual:  \{qual}")
  println("   Trimmed seq:    \{trimmed_seq} (len=\{trimmed_seq.length()})")

  println("")
  println("3. Adapter removal")
  let seq_adapter = "ACGTACGTAGATCGGAA"
  let qual_adapter = "IIIIIIIIIIIIIIIII"
  let adapter = "AGATCGGAA"
  println("   Adapter: 5'-AGATCGGAA-3' (Illumina TruSeq adapter)")
  println("   Before:   \{seq_adapter}")
  let (clean_seq, _) = @bio.sqt_trim_adapter(
    seq_adapter,
    qual_adapter,
    adapter,
    allowed_mismatches=0,
  )
  println("   After:    \{clean_seq} (adapter removed)")

  println("")
  println("4. Poly-A / Poly-T trimming")
  let seq_polya = "ACGTACGGGGAAAA"
  let qual_polya = "IIIIIIIIIIIIII"
  println("   Before:  \{seq_polya}")
  let (poly_clean_seq, _) = @bio.sqt_trim_poly_a(
    seq_polya,
    qual_polya,
    min_tail=3,
  )
  println("   After:   \{poly_clean_seq} (poly-A tail removed)")

  let seq_polyt = "TTTTACGTACGT"
  println("   Before:  \{seq_polyt}")
  let (polyt_clean_seq, _) = @bio.sqt_trim_poly_a(
    seq_polyt,
    "IIIIIIIIIIII",
    min_tail=3,
  )
  println("   After:   \{polyt_clean_seq} (poly-T tail removed)")

  println("")
  println("5. Filtering by length (min_length=8)")
  let short_seq = "ACGT"
  let short_qual = "IIII"
  let long_seq = "ACGTACGTACGT"
  let long_qual = "IIIIIIIIIIII"

  let short_result = @bio.sqt_trim_by_length(
    short_seq,
    short_qual,
    min_length=8,
  )
  match short_result {
    Some(_) => println("   Short read (len=4): KEPT")
    None => println("   Short read (len=4): DISCARDED (below min_length)")
  }

  let long_result = @bio.sqt_trim_by_length(long_seq, long_qual, min_length=8)
  match long_result {
    Some(_) => println("   Long read (len=12): KEPT")
    None => println("   Long read (len=12): DISCARDED")
  }

  println("")
  println("6. Filtering by GC content (gc_min=0.3, gc_max=0.7)")
  let gc_high_seq = "GGGGGGGGGGGGCCCC"
  let gc_high_qual = "IIIIIIIIIIIIIIII"
  let gc_at_seq = "AAAAAAAAAATTTTTT"
  let gc_at_qual = "IIIIIIIIIIIIIIII"

  let gc_high_result = @bio.sqt_trim_by_gc(
    gc_high_seq,
    gc_high_qual,
    gc_min=0.3,
    gc_max=0.7,
  )
  match gc_high_result {
    Some(_) => println("   GC-high read: KEPT")
    None => println("   GC-high read (83% GC): DISCARDED (above gc_max)")
  }

  let gc_at_result = @bio.sqt_trim_by_gc(
    gc_at_seq,
    gc_at_qual,
    gc_min=0.3,
    gc_max=0.7,
  )
  match gc_at_result {
    Some(_) => println("   AT-rich read: KEPT")
    None => println("   AT-rich read (0% GC): DISCARDED (below gc_min)")
  }

  println("")
  println("7. Batch trimming pipeline")
  println("   Running full trimming pipeline on all reads...")
  let qual_config = @bio.QualityConfig::new(20, 4, 4, 20)
  let adapter_config = @bio.AdapterConfig::new(["AGATCGGAA"], 4, 0)

  let trim_results = @bio.sqt_trim_reads(
    reads,
    qual_config,
    Some(adapter_config),
  )
  println("   Trim results:")
  i = 0
  while i < trim_results.length() {
    let tr = trim_results[i]
    let discard_note = if tr.trimmed_seq.length() == 0 {
      " [DISCARDED]"
    } else {
      ""
    }
    println(
      "     \{tr.read_id}: \{tr.original_seq} -> \{tr.trimmed_seq} (type=\{tr.trim_type})\{discard_note}",
    )
    i = i + 1
  }

  println("")
  println("8. Computing trimming statistics")
  let stats = @bio.sqt_compute_stats(trim_results, reads)
  println("   Total reads:    \{stats.total_reads}")
  println("   Kept reads:     \{stats.kept_reads}")
  println("   Trimmed reads:  \{stats.trimmed_reads}")
  println("   Discarded reads: \{stats.discarded_reads}")
  println("   Total bp before: \{stats.total_bp_before}")
  println("   Total bp after:  \{stats.total_bp_after}")
  println("   GC before:       \{stats.gc_content_before}")
  println("   GC after:        \{stats.gc_content_after}")

  println("")
  println("9. Serializing trimmed reads back to FASTQ")
  let kept_reads : Array[@bio.FastqRead] = []
  i = 0
  while i < trim_results.length() {
    let tr = trim_results[i]
    if tr.trimmed_seq.length() > 0 {
      kept_reads.push(
        @bio.FastqRead::new(tr.read_id, tr.trimmed_seq, tr.trimmed_qual),
      )
    }
    i = i + 1
  }
  let fastq_out = @bio.sqt_fastq_serialize(kept_reads)
  println("   Output FASTQ (\{kept_reads.length()} reads):")
  let out_lines = fastq_out.split("\n").to_array()
  let mut l = 0
  while l < out_lines.length() && l < 12 {
    println("     \{out_lines[l]}")
    l = l + 1
  }
  if out_lines.length() > 12 {
    println("     ... (\{out_lines.length()} total lines)")
  }

  println("")
  println("=== Demo Complete ===")
}