///|
fn slingshot_demo_coordinates() -> Array[Array[Double]] {
  [
    [-0.1, 0.0],
    [0.0, 0.1],
    [0.1, -0.1],
    [0.9, 0.0],
    [1.0, 0.1],
    [1.1, -0.1],
    [1.9, 0.0],
    [2.0, 0.1],
    [2.1, -0.1],
    [2.9, 0.9],
    [3.0, 1.0],
    [3.1, 1.1],
    [2.9, -0.9],
    [3.0, -1.0],
    [3.1, -1.1],
  ]
}

///|
fn slingshot_demo_labels() -> Array[String] {
  ["A", "A", "A", "B", "B", "B", "C", "C", "C", "D", "D", "D", "E", "E", "E"]
}

///|
fn slingshot_demo_lineage(
  lineage : Array[Int32],
  cluster_names : Array[String],
) -> String {
  lineage.map(fn(index) { cluster_names[index] }).join(" -> ")
}

///|
fn slingshot_demo_doubles(values : Array[Double]) -> String {
  values.map(fn(value) { value.to_string() }).join(", ")
}

///|
fn main {
  println("=== Bioconductor slingshot 2.21.0 Advanced Demo ===")
  let coordinates = slingshot_demo_coordinates()
  let labels = slingshot_demo_labels()
  let config = @bio.SlingshotAdvancedConfig::create(
    start_clusters=["A"],
    end_clusters=["D", "E"],
    distance=@bio.slingshot_scaled_full(),
    extension=@bio.slingshot_extend_line(),
    shrink=1.0,
    reweight=true,
    reassign=true,
    max_iterations=8,
    tolerance=1.0e-4,
    smoother_span=0.4,
    curve_points=30,
  ) catch {
    _ => abort("failed to create the advanced slingshot configuration")
  }
  let result = @bio.slingshot_advanced(coordinates, labels, config) catch {
    _ => abort("advanced slingshot fitting failed")
  }

  println("\n1. Constrained cluster minimum spanning tree")
  for edge in result.lineage_model.edges {
    println(
      "  " +
      result.lineage_model.cluster_names[edge.from] +
      " -> " +
      result.lineage_model.cluster_names[edge.to] +
      ", distance=" +
      edge.distance.to_string(),
    )
  }

  println("\n2. Root-to-leaf lineages and simultaneous curves")
  for index in 0.. abort("new-cell trajectory projection failed")
  }
  println("\n4. New-cell projection")
  for cell in 0.. abort("SingleCellExperiment trajectory integration failed")
  }
  println("\n5. Immutable SingleCellExperiment integration")
  println("  output columns: slingshot.branch, slingshot.pseudotime")
  println(
    "  pseudotime matrix: " +
    sce_output.experiment.reduced_dims["slingshot.pseudotime"]
    .length()
    .to_string() +
    " cells x " +
    sce_output.experiment.reduced_dims["slingshot.pseudotime"][0]
    .length()
    .to_string() +
    " lineages",
  )
  println(
    "  original unchanged: " +
    (!experiment.col_data.contains("slingshot.branch")).to_string(),
  )
  println("\n" + @bio.slingshot_advanced_summary(result))
}