///|
/// Scanline rasterizer for vector path filling
pub struct ScanlineRasterizer {
  width : Int
  height : Int
  pixels : FixedArray[Byte]
}

///|
/// Create a new scanline rasterizer
pub fn ScanlineRasterizer::new(width : Int, height : Int) -> ScanlineRasterizer {
  let size = width * height * 4 // RGBA
  { width, height, pixels: FixedArray::make(size, 0), }
}

///|
/// Get the pixel buffer (RGBA)
pub fn ScanlineRasterizer::get_pixels(
  self : ScanlineRasterizer,
) -> FixedArray[Byte] {
  self.pixels
}

///|
/// Clear the buffer
pub fn ScanlineRasterizer::clear(
  self : ScanlineRasterizer,
  color : Color,
) -> Unit {
  for i in 0..<(self.width * self.height) {
    let idx = i * 4
    self.pixels[idx] = color.r
    self.pixels[idx + 1] = color.g
    self.pixels[idx + 2] = color.b
    self.pixels[idx + 3] = color.a
  }
}

///|
/// Set a pixel
fn ScanlineRasterizer::set_pixel(
  self : ScanlineRasterizer,
  x : Int,
  y : Int,
  color : Color,
) -> Unit {
  guard x >= 0 && x < self.width && y >= 0 && y < self.height else { return }
  let idx = (y * self.width + x) * 4
  self.pixels[idx] = color.r
  self.pixels[idx + 1] = color.g
  self.pixels[idx + 2] = color.b
  self.pixels[idx + 3] = color.a
}

///|
/// Fill a triangle using scanline algorithm
pub fn ScanlineRasterizer::fill_triangle(
  self : ScanlineRasterizer,
  x0 : Double,
  y0 : Double,
  x1 : Double,
  y1 : Double,
  x2 : Double,
  y2 : Double,
  color : Color,
) -> Unit {
  // Sort vertices by y coordinate using local mutable variables
  let mut ax = x0
  let mut ay = y0
  let mut bx = x1
  let mut by = y1
  let mut cx = x2
  let mut cy = y2

  // Sort so that ay <= by <= cy
  if ay > by {
    let tx = ax
    let ty = ay
    ax = bx
    ay = by
    bx = tx
    by = ty
  }
  if ay > cy {
    let tx = ax
    let ty = ay
    ax = cx
    ay = cy
    cx = tx
    cy = ty
  }
  if by > cy {
    let tx = bx
    let ty = by
    bx = cx
    by = cy
    cx = tx
    cy = ty
  }

  let ay_int = ay.to_int()
  let cy_int = cy.to_int()

  // Fill scanlines
  for y in ay_int..<=cy_int {
    let y_double = y.to_double()

    // Find x intersections
    let mut x_left = 0.0
    let mut x_right = 0.0

    if y_double < by {
      // Upper half
      let t1 = if by == ay { 0.0 } else { (y_double - ay) / (by - ay) }
      let t2 = if cy == ay { 0.0 } else { (y_double - ay) / (cy - ay) }
      x_left = ax + t1 * (bx - ax)
      x_right = ax + t2 * (cx - ax)
    } else {
      // Lower half
      let t1 = if cy == by { 0.0 } else { (y_double - by) / (cy - by) }
      let t2 = if cy == ay { 0.0 } else { (y_double - ay) / (cy - ay) }
      x_left = bx + t1 * (cx - bx)
      x_right = ax + t2 * (cx - ax)
    }

    // Ensure x_left <= x_right
    if x_left > x_right {
      let temp = x_left
      x_left = x_right
      x_right = temp
    }

    // Fill the scanline
    let x_start = x_left.to_int()
    let x_end = x_right.to_int()
    for x in x_start..<=x_end {
      self.set_pixel(x, y, color)
    }
  }
}

///|
/// Draw a line using Bresenham's algorithm
pub fn ScanlineRasterizer::draw_line(
  self : ScanlineRasterizer,
  x0 : Int,
  y0 : Int,
  x1 : Int,
  y1 : Int,
  color : Color,
) -> Unit {
  let dx = (x1 - x0).abs()
  let dy = (y1 - y0).abs()
  let sx = if x0 < x1 { 1 } else { -1 }
  let sy = if y0 < y1 { 1 } else { -1 }
  let mut err = dx - dy

  let mut x = x0
  let mut y = y0

  while true {
    self.set_pixel(x, y, color)

    if x == x1 && y == y1 {
      break
    }

    let e2 = 2 * err
    if e2 > -dy {
      err = err - dy
      x = x + sx
    }
    if e2 < dx {
      err = err + dx
      y = y + sy
    }
  }
}

///|
/// Fill a convex polygon (works for any convex shape)
pub fn ScanlineRasterizer::fill_polygon(
  self : ScanlineRasterizer,
  points : Array[(Double, Double)],
  color : Color,
) -> Unit {
  let len = points.length()
  guard len >= 3 else { return }

  // Find bounding box
  let (_, first_y) = points[0]
  let mut min_y = first_y
  let mut max_y = first_y
  for i in 1.. max_y {
      max_y = y
    }
  }

  let y_start = min_y.to_int()
  let y_end = max_y.to_int()

  // Scanline fill
  for y in y_start..<=y_end {
    let y_double = y.to_double()
    let intersections = []

    // Find intersections with polygon edges
    for i in 0.. y_double) || (y2 <= y_double && y1 > y_double) {
        let t = (y_double - y1) / (y2 - y1)
        let x = x1 + t * (x2 - x1)
        intersections.push(x)
      }
    }

    // Sort intersections
    let int_len = intersections.length()
    for i in 0.. intersections[j] {
          let temp = intersections[i]
          intersections[i] = intersections[j]
          intersections[j] = temp
        }
      }
    }

    // Fill between pairs of intersections
    let mut k = 0
    while k + 1 < int_len {
      let x_start = intersections[k].to_int()
      let x_end = intersections[k + 1].to_int()
      for x in x_start..<=x_end {
        self.set_pixel(x, y, color)
      }
      k = k + 2
    }
  }
}