///|
/// CDAO (Comparative Data Analysis Ontology) format demo.
///
/// Demonstrates the CDAO RDF/XML format for phylogenetic data:
///   - CDAO document structure (trees, nodes, TUs)
///   - Parsing CDAO RDF/XML
///   - Writing trees to CDAO format
///   - Converting between CDAO and BioSeqs Tree
///
/// Inspired by Biopython's Bio.Phylo.CDAO and Bio.Phylo.CDAOIO.
/// Run: moon run examples/phylo_cdao_demo
fn main {
  println("=== CDAO Module Demo ===")
  println("Comparative Data Analysis Ontology format")
  println("Reference: Biopython Bio.Phylo.CDAO / CDAOIO")
  println("")

  // ------------------------------------------------------------------
  // 1. Namespace constants
  // ------------------------------------------------------------------
  println("=== 1. CDAO Namespace Constants ===")
  println("CDAO namespace: " + @bio.cdao_namespace())
  println("RDF namespace:  " + @bio.cdao_rdf_namespace())
  println("RDFS namespace: " + @bio.cdao_rdfs_namespace())
  println("")

  // ------------------------------------------------------------------
  // 2. Sample CDAO document
  // ------------------------------------------------------------------
  println("=== 2. Sample CDAO Document ===")
  let doc = @bio.cdao_sample_document()
  println(@bio.cdao_document_summary(doc))
  println("")

  // Show node relationships
  println("Node relationships:")
  let node_keys = doc.nodes.keys()
  let node_arr : Array[String] = node_keys.collect()
  let mut i = 0
  while i < node_arr.length() {
    let node_id = node_arr[i]
    let node = doc.nodes[node_id]
    let parent_str = match node.parent_id {
      Some(p) => p
      None => "(root)"
    }
    let tu_str = match node.tu_id {
      Some(t) => " TU=" + t
      None => ""
    }
    let bl_str = match node.branch_length {
      Some(bl) => " bl=" + bl.to_string()
      None => ""
    }
    let child_count = node.children.length()
    println(
      "  " +
      node_id +
      " parent=" +
      parent_str +
      " children=" +
      child_count.to_string() +
      tu_str +
      bl_str,
    )
    i = i + 1
  }
  println("")

  // ------------------------------------------------------------------
  // 3. Parse CDAO XML
  // ------------------------------------------------------------------
  println("=== 3. Parse CDAO RDF/XML ===")
  let xml = @bio.cdao_sample_xml()
  println("Parsing sample CDAO XML...")
  let parsed_doc = @bio.cdao_parse(xml)
  println("Parsed document summary:")
  println(@bio.cdao_document_summary(parsed_doc))
  println("")

  // ------------------------------------------------------------------
  // 4. Convert CDAO to BioSeqs Tree
  // ------------------------------------------------------------------
  println("=== 4. Convert CDAO to Tree ===")
  let trees = @bio.cdao_to_trees(doc)
  println(
    "Converted " + trees.length().to_string() + " tree(s) from CDAO document",
  )
  if trees.length() > 0 {
    let tree = trees[0]
    println("Tree rooted: " + tree.rooted.to_string())
    println("Root children: " + tree.root.clades.length().to_string())
    // Print leaf names
    let terminals = tree.root.get_terminals()
    println("Leaf taxa (" + terminals.length().to_string() + "):")
    let mut t = 0
    while t < terminals.length() {
      let name = match terminals[t].name {
        Some(n) => n
        None => "(unnamed)"
      }
      println("  " + name)
      t = t + 1
    }
  }
  println("")

  // ------------------------------------------------------------------
  // 5. Write tree to CDAO format
  // ------------------------------------------------------------------
  println("=== 5. Write Tree to CDAO Format ===")
  let sample_tree = @bio.parsimony_sample_tree()
  println("Tree topology: ((A, B), (C, D))")
  println("")
  println("Generating CDAO RDF/XML...")
  let cdao_xml = @bio.cdao_write(sample_tree)
  println("Output XML (" + cdao_xml.length().to_string() + " chars):")
  println("---")
  // Print first 500 characters
  let display_len = if cdao_xml.length() > 500 {
    500
  } else {
    cdao_xml.length()
  }
  println(cdao_xml[0:display_len].to_owned())
  if cdao_xml.length() > 500 {
    println("... (truncated)")
  }
  println("---")
  println("")

  // ------------------------------------------------------------------
  // 6. Roundtrip: Write then parse
  // ------------------------------------------------------------------
  println("=== 6. Roundtrip: Write -> Parse ===")
  let roundtrip_doc = @bio.cdao_parse(cdao_xml)
  let roundtrip_trees = @bio.cdao_to_trees(roundtrip_doc)
  println("Roundtrip results:")
  println("  Trees: " + roundtrip_trees.length().to_string())
  if roundtrip_trees.length() > 0 {
    let rt_tree = roundtrip_trees[0]
    let rt_terminals = rt_tree.root.get_terminals()
    println("  Leaf taxa: " + rt_terminals.length().to_string())
    let mut rt = 0
    while rt < rt_terminals.length() {
      let name = match rt_terminals[rt].name {
        Some(n) => n
        None => "(unnamed)"
      }
      println("    " + name)
      rt = rt + 1
    }
  }
  println("")

  // ------------------------------------------------------------------
  // 7. Build custom CDAO document
  // ------------------------------------------------------------------
  println("=== 7. Build Custom CDAO Document ===")
  let custom_doc = @bio.CdaoDocument::new()
  custom_doc.trees.push(
    @bio.Cdaotree::new("#mytree", rooted=true, root_node_id="#n1"),
  )
  // Simple tree: ((X, Y), Z)
  custom_doc.nodes["#n1"] = @bio.CdaoNode::new("#n1", children=["#n2", "#n3"])
  custom_doc.nodes["#n2"] = @bio.CdaoNode::new(
    "#n2",
    children=["#n4", "#n5"],
    parent_id=Some("#n1"),
  )
  custom_doc.nodes["#n3"] = @bio.CdaoNode::new(
    "#n3",
    parent_id=Some("#n1"),
    tu_id=Some("#tu3"),
    branch_length=Some(0.5),
  )
  custom_doc.nodes["#n4"] = @bio.CdaoNode::new(
    "#n4",
    parent_id=Some("#n2"),
    tu_id=Some("#tu1"),
    branch_length=Some(1.0),
  )
  custom_doc.nodes["#n5"] = @bio.CdaoNode::new(
    "#n5",
    parent_id=Some("#n2"),
    tu_id=Some("#tu2"),
    branch_length=Some(1.0),
  )
  custom_doc.tus["#tu1"] = @bio.CdaoTU::new("#tu1", label=Some("X"))
  custom_doc.tus["#tu2"] = @bio.CdaoTU::new("#tu2", label=Some("Y"))
  custom_doc.tus["#tu3"] = @bio.CdaoTU::new("#tu3", label=Some("Z"))
  println("Custom document summary:")
  println(@bio.cdao_document_summary(custom_doc))
  let custom_trees = @bio.cdao_to_trees(custom_doc)
  println("Converted to " + custom_trees.length().to_string() + " tree(s)")
  if custom_trees.length() > 0 {
    let ct = custom_trees[0]
    let ct_terminals = ct.root.get_terminals()
    println("Leaf taxa:")
    let mut ci = 0
    while ci < ct_terminals.length() {
      let name = match ct_terminals[ci].name {
        Some(n) => n
        None => "(unnamed)"
      }
      println("  " + name)
      ci = ci + 1
    }
  }
  println("")

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