///|
/// DNAcopy demo: Circular Binary Segmentation (CBS) of copy-number data,
/// ported from Bioconductor DNAcopy::segment(). Shows profile construction,
/// segmentation with default and merged options, and multi-chromosome input.
///
/// Run: moon run examples/dnacopy_demo
fn main {
  println("=== DNAcopy Demo (CBS copy-number segmentation) ===\n")

  // 1. A synthetic copy-number profile: 60 probes on chr1 with
  //    normal(0) x15 -> gain(+1) x15 -> loss(-1) x15 -> normal(0) x15,
  //    plus a little deterministic wiggle.
  println("1. Four-level synthetic profile (60 probes, 1 kb apart)")
  let vals : Array[Double] = []
  let wiggle = [0.1, -0.1, 0.05, -0.05, 0.0]
  let mut i = 0
  while i < 60 {
    let level = if i < 15 {
      0.0
    } else if i < 30 {
      1.0
    } else if i < 45 {
      -1.0
    } else {
      0.0
    }
    vals.push(level + wiggle[i % wiggle.length()])
    i = i + 1
  }
  let maploc : Array[Int32] = []
  let chrom : Array[String] = Array::make(60, "chr1")
  let mut k = 0
  while k < 60 {
    maploc.push((k + 1) * 1000)
    k = k + 1
  }
  let cna = @bio.Cna::new(chrom, maploc, vals) catch { _ => abort("bad CNA") }
  let res = @bio.segment(cna, options=@bio.DnaCopyOptions::of(nperm=1000)) catch {
    _ => abort("segment failed")
  }
  println("   \{res.segments.length()} segments found:")
  for s in res.segments {
    println(
      "   \{s.chrom} \{s.start}-\{s.end} num.mark=\{s.num_mark} seg.mean=\{s.seg_mean}",
    )
  }

  // 2. sdundo: merge adjacent segments with nearly equal levels
  println("\n2. undo.splits=\"sdundo\" merges similar levels")
  // 30 probes: 0 x10, +0.2 x10, +1 x10 - with a generous undo_sd the small
  // 0.2 step is merged back into the 0 level
  let vals2 : Array[Double] = []
  let mut j = 0
  while j < 30 {
    vals2.push(if j < 10 { 0.0 } else if j < 20 { 0.2 } else { 1.0 })
    j = j + 1
  }
  let maploc2 : Array[Int32] = []
  let mut k2 = 0
  while k2 < 30 {
    maploc2.push((k2 + 1) * 1000)
    k2 = k2 + 1
  }
  let cna2 = @bio.Cna::new(Array::make(30, "chr2"), maploc2, vals2) catch {
    _ => abort("bad CNA")
  }
  let plain = @bio.segment(cna2, options=@bio.DnaCopyOptions::of(nperm=1000)) catch {
    _ => abort("segment failed")
  }
  let merged = @bio.segment(
    cna2,
    options=@bio.DnaCopyOptions::of(
      nperm=1000,
      undo_splits="sdundo",
      undo_sd=10.0,
    ),
  ) catch {
    _ => abort("segment failed")
  }
  println("   without undo: \{plain.segments.length()} segments")
  for s in plain.segments {
    println("     \{s.start}-\{s.end} mean=\{s.seg_mean} (n=\{s.num_mark})")
  }
  println("   with sdundo:   \{merged.segments.length()} segments")
  for s in merged.segments {
    println("     \{s.start}-\{s.end} mean=\{s.seg_mean} (n=\{s.num_mark})")
  }

  // 3. Two chromosomes are segmented independently
  println("\n3. Multi-chromosome input")
  let chrom3 : Array[String] = []
  let maploc3 : Array[Int32] = []
  let vals3 : Array[Double] = []
  // chrA: flat 0
  let mut m = 0
  while m < 20 {
    chrom3.push("chrA")
    maploc3.push((m + 1) * 1000)
    vals3.push(0.0)
    m = m + 1
  }
  // chrB: gain in the middle
  let mut m2 = 0
  while m2 < 20 {
    chrom3.push("chrB")
    maploc3.push((m2 + 1) * 1000)
    vals3.push(if m2 >= 8 && m2 < 14 { 1.0 } else { 0.0 })
    m2 = m2 + 1
  }
  let cna3 = @bio.Cna::new(chrom3, maploc3, vals3) catch {
    _ => abort("bad CNA")
  }
  let res3 = @bio.segment(cna3, options=@bio.DnaCopyOptions::of(nperm=1000)) catch {
    _ => abort("segment failed")
  }
  println("   \{res3.segments.length()} segments:")
  for s in res3.segments {
    println(
      "   \{s.chrom} \{s.start}-\{s.end} num.mark=\{s.num_mark} seg.mean=\{s.seg_mean}",
    )
  }

  println("\nDone.")
}