///|
/// ebimage demo - Grayscale image processing for cellular imaging.
/// Inspired by Bioconductor {EBImage}.
fn main {
  println("=== ebimage Demo: Image Processing Pipeline ===")
  println("")

  // Step 1: synthetic image with two bright "cells"
  println("--- Step 1: Synthetic Image (two disks) ---")
  let img = @src.ebi_example_image()
  println(@src.ebi_to_ascii(img))
  println(
    "  stats: min=" +
    @src.ebi_min(img).to_string() +
    " max=" +
    @src.ebi_max(img).to_string() +
    " mean=" +
    @src.ebi_mean(img).to_string() +
    " sd=" +
    @src.ebi_sd(img).to_string(),
  )
  println("")

  // Step 2: smoothing and edge detection
  println("--- Step 2: Gaussian Blur + Sobel Edges ---")
  let blurred = @src.ebi_gaussian_blur(img, 1.0)
  let grad = @src.ebi_sobel_gradient(blurred)
  println("  max gradient magnitude: " + @src.ebi_max(grad).to_string())
  println("")

  // Step 3: Otsu thresholding
  println("--- Step 3: Otsu Threshold ---")
  let t = @src.ebi_otsu_threshold(img)
  let binary = @src.ebi_threshold(img, t)
  println("  otsu threshold = " + t.to_string())
  println(@src.ebi_to_ascii(binary))
  println("")

  // Step 4: morphological cleanup
  println("--- Step 4: Morphological Opening ---")
  let opened = @src.ebi_open(binary, @src.ebi_se_cross())
  let mut fg = 0
  for v in opened.data {
    if v > 0.0 {
      fg = fg + 1
    }
  }
  let mut fg0 = 0
  for v in binary.data {
    if v > 0.0 {
      fg0 = fg0 + 1
    }
  }
  println(
    "  foreground pixels: " +
    fg0.to_string() +
    " -> after opening: " +
    fg.to_string(),
  )
  println("")

  // Step 5: connected components
  println("--- Step 5: Connected Components (8-connectivity) ---")
  let (labels, count) = @src.ebi_label(opened, connectivity=8)
  println("  objects found: " + count.to_string())
  let features = @src.ebi_object_features(labels, img.width, img.height, count)
  for obj in features {
    println(
      "  object " +
      obj.label.to_string() +
      ": area=" +
      obj.area.to_string() +
      " centroid=(" +
      obj.cx.to_string() +
      ", " +
      obj.cy.to_string() +
      ")" +
      " bbox=[" +
      obj.min_x.to_string() +
      "," +
      obj.min_y.to_string() +
      "]-[" +
      obj.max_x.to_string() +
      "," +
      obj.max_y.to_string() +
      "]",
    )
  }
  println("")

  // Step 6: marker-based watershed
  println("--- Step 6: Marker-based Watershed ---")
  let ws = @src.ebi_watershed(img, labels)
  let mut max_label = 0
  for l in ws {
    if l > max_label {
      max_label = l
    }
  }
  println("  watershed regions: " + max_label.to_string())
  println("")

  // Step 7: contrast normalisation
  println("--- Step 7: Contrast Normalisation ---")
  let norm = @src.ebi_normalize(grad)
  println(
    "  normalised gradient range: [" +
    @src.ebi_min(norm).to_string() +
    ", " +
    @src.ebi_max(norm).to_string() +
    "]",
  )

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