///|
/// Integer-grid normalization helpers for terminal layout coordinates.
/// Converts floating-point layout output into stable monospace cell rects.

///|
pub struct GridRect {
  x : Int
  y : Int
  width : Int
  height : Int
} derive(Eq, Debug)

///|
pub impl Show for GridRect with fn output(self : GridRect, logger : &Logger) -> Unit {
  self.to_repr().output(logger)
}

///|
/// Snap a floating-point coordinate to the nearest terminal cell.
pub fn snap_to_grid(value : Double) -> Int {
  if value >= 0.0 {
    (value + 0.5).to_int()
  } else {
    (value - 0.5).to_int()
  }
}

///|
/// Normalize a rectangle by snapping both start and end edges.
/// Width/height are derived from snapped edges to keep geometry consistent.
pub fn normalize_grid_rect(
  abs_x : Double,
  abs_y : Double,
  width : Double,
  height : Double,
) -> GridRect {
  let left = snap_to_grid(abs_x)
  let top = snap_to_grid(abs_y)
  let right = snap_to_grid(abs_x + width)
  let bottom = snap_to_grid(abs_y + height)
  {
    x: left,
    y: top,
    width: if right > left {
      right - left
    } else {
      0
    },
    height: if bottom > top {
      bottom - top
    } else {
      0
    },
  }
}

///|
/// Normalize an inner rectangle by applying insets before edge snapping.
pub fn normalize_grid_rect_with_inset(
  abs_x : Double,
  abs_y : Double,
  width : Double,
  height : Double,
  inset_left : Double,
  inset_top : Double,
  inset_right : Double,
  inset_bottom : Double,
) -> GridRect {
  let left = snap_to_grid(abs_x + inset_left)
  let top = snap_to_grid(abs_y + inset_top)
  let right = snap_to_grid(abs_x + width - inset_right)
  let bottom = snap_to_grid(abs_y + height - inset_bottom)
  {
    x: left,
    y: top,
    width: if right > left {
      right - left
    } else {
      0
    },
    height: if bottom > top {
      bottom - top
    } else {
      0
    },
  }
}