// Deterministic image scale-space construction.

///|
pub(all) struct ImagePyramid {
  levels : Array[GrayImage]
  scales : Array[Double]
}

///|
pub fn ImagePyramid::build(img : GrayImage, level_count : Int) -> ImagePyramid {
  let levels : Array[GrayImage] = []
  let scales : Array[Double] = []
  if level_count <= 0 {
    return { levels, scales }
  }
  let mut current = img.clone()
  let mut scale = 1.0
  let mut level = 0
  while level < level_count {
    levels.push(current.clone())
    scales.push(scale)
    if level + 1 < level_count {
      let blurred = box_blur(current, 1)
      let next_width = (current.width + 1) / 2
      let next_height = (current.height + 1) / 2
      current = blurred.resize_nearest(next_width, next_height)
      scale = scale * 0.5
    }
    level = level + 1
  }
  { levels, scales }
}

///|
pub fn ImagePyramid::level_count(self : ImagePyramid) -> Int {
  self.levels.length()
}

///|
pub fn ImagePyramid::level(self : ImagePyramid, index : Int) -> GrayImage {
  if index < 0 || index >= self.levels.length() {
    GrayImage::new(0, 0)
  } else {
    self.levels[index]
  }
}

///|
pub fn ImagePyramid::scale(self : ImagePyramid, index : Int) -> Double {
  if index < 0 || index >= self.scales.length() {
    0.0
  } else {
    self.scales[index]
  }
}

///|
pub fn ImagePyramid::to_level(
  self : ImagePyramid,
  point : FloatPoint2,
  level : Int,
) -> FloatPoint2 {
  let factor = self.scale(level)
  if factor <= 0.0 {
    point
  } else {
    FloatPoint2::new(point.x * factor, point.y * factor)
  }
}

///|
pub fn ImagePyramid::to_original(
  self : ImagePyramid,
  point : FloatPoint2,
  level : Int,
) -> FloatPoint2 {
  let factor = self.scale(level)
  if factor <= 0.0 {
    point
  } else {
    FloatPoint2::new(point.x / factor, point.y / factor)
  }
}