///|
/// Yoga-compatible API for LayoutNode and LayoutTree
/// Provides a familiar interface for users coming from Yoga/Litho/React Native

// =============================================================================
// LayoutNode Extensions - Style Setters (auto-dirty)
// =============================================================================

///|
/// Set width in pixels
pub fn LayoutNode::set_width(self : LayoutNode, value : Double) -> LayoutNode {
  if !self.style.width.eq_length(value) {
    self.style.width = @types.Length(value)
    self.mark_dirty()
  }
  self
}

///|
/// Set width as percentage (0.0-1.0)
pub fn LayoutNode::set_width_percent(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  if !self.style.width.eq_percent(value) {
    self.style.width = @types.Percent(value)
    self.mark_dirty()
  }
  self
}

///|
/// Set width to auto
pub fn LayoutNode::set_width_auto(self : LayoutNode) -> LayoutNode {
  match self.style.width {
    @types.Auto => ()
    _ => {
      self.style.width = @types.Auto
      self.mark_dirty()
    }
  }
  self
}

///|
/// Set height in pixels
pub fn LayoutNode::set_height(self : LayoutNode, value : Double) -> LayoutNode {
  if !self.style.height.eq_length(value) {
    self.style.height = @types.Length(value)
    self.mark_dirty()
  }
  self
}

///|
/// Set height as percentage (0.0-1.0)
pub fn LayoutNode::set_height_percent(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  if !self.style.height.eq_percent(value) {
    self.style.height = @types.Percent(value)
    self.mark_dirty()
  }
  self
}

///|
/// Set height to auto
pub fn LayoutNode::set_height_auto(self : LayoutNode) -> LayoutNode {
  match self.style.height {
    @types.Auto => ()
    _ => {
      self.style.height = @types.Auto
      self.mark_dirty()
    }
  }
  self
}

///|
/// Set min-width in pixels
pub fn LayoutNode::set_min_width(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  if !self.style.min_width.eq_length(value) {
    self.style.min_width = @types.Length(value)
    self.mark_dirty()
  }
  self
}

///|
/// Set max-width in pixels
pub fn LayoutNode::set_max_width(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  if !self.style.max_width.eq_length(value) {
    self.style.max_width = @types.Length(value)
    self.mark_dirty()
  }
  self
}

///|
/// Set min-height in pixels
pub fn LayoutNode::set_min_height(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  if !self.style.min_height.eq_length(value) {
    self.style.min_height = @types.Length(value)
    self.mark_dirty()
  }
  self
}

///|
/// Set max-height in pixels
pub fn LayoutNode::set_max_height(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  if !self.style.max_height.eq_length(value) {
    self.style.max_height = @types.Length(value)
    self.mark_dirty()
  }
  self
}

///|
/// Set flex direction
pub fn LayoutNode::set_flex_direction(
  self : LayoutNode,
  dir : @types.FlexDirection,
) -> LayoutNode {
  if self.style.flex_direction != dir {
    self.style.flex_direction = dir
    self.mark_dirty()
  }
  self
}

///|
/// Set flex wrap
pub fn LayoutNode::set_flex_wrap(
  self : LayoutNode,
  wrap : @types.FlexWrap,
) -> LayoutNode {
  if self.style.flex_wrap != wrap {
    self.style.flex_wrap = wrap
    self.mark_dirty()
  }
  self
}

///|
/// Set flex grow
pub fn LayoutNode::set_flex_grow(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  if (self.style.flex_grow - value).abs() > 0.0001 {
    self.style.flex_grow = value
    self.mark_dirty()
  }
  self
}

///|
/// Set flex shrink
pub fn LayoutNode::set_flex_shrink(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  if (self.style.flex_shrink - value).abs() > 0.0001 {
    self.style.flex_shrink = value
    self.mark_dirty()
  }
  self
}

///|
/// Set flex basis in pixels
pub fn LayoutNode::set_flex_basis(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  if !self.style.flex_basis.eq_length(value) {
    self.style.flex_basis = @types.Length(value)
    self.mark_dirty()
  }
  self
}

///|
/// Set flex basis to auto
pub fn LayoutNode::set_flex_basis_auto(self : LayoutNode) -> LayoutNode {
  match self.style.flex_basis {
    @types.Auto => ()
    _ => {
      self.style.flex_basis = @types.Auto
      self.mark_dirty()
    }
  }
  self
}

///|
/// Set justify content
pub fn LayoutNode::set_justify_content(
  self : LayoutNode,
  value : @types.Alignment,
) -> LayoutNode {
  if self.style.justify_content != value {
    self.style.justify_content = value
    self.mark_dirty()
  }
  self
}

///|
/// Set align items
pub fn LayoutNode::set_align_items(
  self : LayoutNode,
  value : @types.Alignment,
) -> LayoutNode {
  if self.style.align_items != value {
    self.style.align_items = value
    self.mark_dirty()
  }
  self
}

///|
/// Set align self
pub fn LayoutNode::set_align_self(
  self : LayoutNode,
  value : @types.AlignSelf,
) -> LayoutNode {
  if self.style.align_self != value {
    self.style.align_self = value
    self.mark_dirty()
  }
  self
}

///|
/// Set align content
pub fn LayoutNode::set_align_content(
  self : LayoutNode,
  value : @types.Alignment,
) -> LayoutNode {
  if self.style.align_content != value {
    self.style.align_content = value
    self.mark_dirty()
  }
  self
}

///|
/// Set display type
pub fn LayoutNode::set_display(
  self : LayoutNode,
  value : @types.Display,
) -> LayoutNode {
  if self.style.display != value {
    self.style.display = value
    self.mark_dirty()
  }
  self
}

///|
/// Set position type
pub fn LayoutNode::set_position_type(
  self : LayoutNode,
  value : @types.Position,
) -> LayoutNode {
  if self.style.position != value {
    self.style.position = value
    self.mark_dirty()
  }
  self
}

///|
/// Set row gap in pixels
pub fn LayoutNode::set_row_gap(self : LayoutNode, value : Double) -> LayoutNode {
  if !self.style.row_gap.eq_length(value) {
    self.style.row_gap = @types.Length(value)
    self.mark_dirty()
  }
  self
}

///|
/// Set column gap in pixels
pub fn LayoutNode::set_column_gap(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  if !self.style.column_gap.eq_length(value) {
    self.style.column_gap = @types.Length(value)
    self.mark_dirty()
  }
  self
}

///|
/// Set both row and column gap
pub fn LayoutNode::set_gap(self : LayoutNode, value : Double) -> LayoutNode {
  self.set_row_gap(value).set_column_gap(value)
}

// =============================================================================
// Grid Container Setters
// =============================================================================

///|
/// Set grid template columns
pub fn LayoutNode::set_grid_template_columns(
  self : LayoutNode,
  tracks : Array[@types.TrackSizingFunction],
) -> LayoutNode {
  self.style.grid_template_columns = tracks
  self.mark_dirty()
  self
}

///|
/// Set grid template rows
pub fn LayoutNode::set_grid_template_rows(
  self : LayoutNode,
  tracks : Array[@types.TrackSizingFunction],
) -> LayoutNode {
  self.style.grid_template_rows = tracks
  self.mark_dirty()
  self
}

///|
/// Set grid auto columns
pub fn LayoutNode::set_grid_auto_columns(
  self : LayoutNode,
  tracks : Array[@types.TrackSizingFunction],
) -> LayoutNode {
  self.style.grid_auto_columns = tracks
  self.mark_dirty()
  self
}

///|
/// Set grid auto rows
pub fn LayoutNode::set_grid_auto_rows(
  self : LayoutNode,
  tracks : Array[@types.TrackSizingFunction],
) -> LayoutNode {
  self.style.grid_auto_rows = tracks
  self.mark_dirty()
  self
}

///|
/// Set grid auto flow
pub fn LayoutNode::set_grid_auto_flow(
  self : LayoutNode,
  flow : @types.GridAutoFlow,
) -> LayoutNode {
  if self.style.grid_auto_flow != flow {
    self.style.grid_auto_flow = flow
    self.mark_dirty()
  }
  self
}

///|
/// Set grid template areas
pub fn LayoutNode::set_grid_template_areas(
  self : LayoutNode,
  areas : Array[String],
) -> LayoutNode {
  self.style.grid_template_areas = areas
  self.mark_dirty()
  self
}

// =============================================================================
// Grid Item Setters
// =============================================================================

///|
/// Set grid row placement
pub fn LayoutNode::set_grid_row(
  self : LayoutNode,
  start : @types.GridPlacement,
  end : @types.GridPlacement,
) -> LayoutNode {
  self.style.grid_row = { start, end }
  self.mark_dirty()
  self
}

///|
/// Set grid column placement
pub fn LayoutNode::set_grid_column(
  self : LayoutNode,
  start : @types.GridPlacement,
  end : @types.GridPlacement,
) -> LayoutNode {
  self.style.grid_column = { start, end }
  self.mark_dirty()
  self
}

///|
/// Set grid area by name
pub fn LayoutNode::set_grid_area(
  self : LayoutNode,
  area : String?,
) -> LayoutNode {
  self.style.grid_area = area
  self.mark_dirty()
  self
}

///|
/// Set justify items (grid container)
pub fn LayoutNode::set_justify_items(
  self : LayoutNode,
  value : @types.Alignment,
) -> LayoutNode {
  if self.style.justify_items != value {
    self.style.justify_items = value
    self.mark_dirty()
  }
  self
}

///|
/// Set justify self (grid item)
pub fn LayoutNode::set_justify_self(
  self : LayoutNode,
  value : @types.AlignSelf,
) -> LayoutNode {
  if self.style.justify_self != value {
    self.style.justify_self = value
    self.mark_dirty()
  }
  self
}

// =============================================================================
// Margin Setters
// =============================================================================

///|
/// Set all margins
pub fn LayoutNode::set_margin(self : LayoutNode, value : Double) -> LayoutNode {
  self.style.margin = @types.Rect::all(@types.Length(value))
  self.mark_dirty()
  self
}

///|
/// Set margin top
pub fn LayoutNode::set_margin_top(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  let m = self.style.margin
  self.style.margin = {
    top: @types.Length(value),
    right: m.right,
    bottom: m.bottom,
    left: m.left,
  }
  self.mark_dirty()
  self
}

///|
/// Set margin right
pub fn LayoutNode::set_margin_right(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  let m = self.style.margin
  self.style.margin = {
    top: m.top,
    right: @types.Length(value),
    bottom: m.bottom,
    left: m.left,
  }
  self.mark_dirty()
  self
}

///|
/// Set margin bottom
pub fn LayoutNode::set_margin_bottom(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  let m = self.style.margin
  self.style.margin = {
    top: m.top,
    right: m.right,
    bottom: @types.Length(value),
    left: m.left,
  }
  self.mark_dirty()
  self
}

///|
/// Set margin left
pub fn LayoutNode::set_margin_left(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  let m = self.style.margin
  self.style.margin = {
    top: m.top,
    right: m.right,
    bottom: m.bottom,
    left: @types.Length(value),
  }
  self.mark_dirty()
  self
}

// =============================================================================
// Padding Setters
// =============================================================================

///|
/// Set all padding
pub fn LayoutNode::set_padding(self : LayoutNode, value : Double) -> LayoutNode {
  self.style.padding = @types.Rect::all(@types.Length(value))
  self.mark_dirty()
  self
}

///|
/// Set padding top
pub fn LayoutNode::set_padding_top(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  let p = self.style.padding
  self.style.padding = {
    top: @types.Length(value),
    right: p.right,
    bottom: p.bottom,
    left: p.left,
  }
  self.mark_dirty()
  self
}

///|
/// Set padding right
pub fn LayoutNode::set_padding_right(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  let p = self.style.padding
  self.style.padding = {
    top: p.top,
    right: @types.Length(value),
    bottom: p.bottom,
    left: p.left,
  }
  self.mark_dirty()
  self
}

///|
/// Set padding bottom
pub fn LayoutNode::set_padding_bottom(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  let p = self.style.padding
  self.style.padding = {
    top: p.top,
    right: p.right,
    bottom: @types.Length(value),
    left: p.left,
  }
  self.mark_dirty()
  self
}

///|
/// Set padding left
pub fn LayoutNode::set_padding_left(
  self : LayoutNode,
  value : Double,
) -> LayoutNode {
  let p = self.style.padding
  self.style.padding = {
    top: p.top,
    right: p.right,
    bottom: p.bottom,
    left: @types.Length(value),
  }
  self.mark_dirty()
  self
}

// =============================================================================
// Border Setters
// =============================================================================

///|
/// Set all border widths
pub fn LayoutNode::set_border(self : LayoutNode, value : Double) -> LayoutNode {
  self.style.border = @types.Rect::all(@types.Length(value))
  self.mark_dirty()
  self
}

// =============================================================================
// Child Management
// =============================================================================

///|
/// Get number of children
pub fn LayoutNode::get_child_count(self : LayoutNode) -> Int {
  self.children.length()
}

///|
/// Get child at index
pub fn LayoutNode::get_child(self : LayoutNode, index : Int) -> LayoutNode? {
  if index >= 0 && index < self.children.length() {
    Some(self.children[index])
  } else {
    None
  }
}

///|
/// Insert child at index
pub fn LayoutNode::insert_child(
  self : LayoutNode,
  child : LayoutNode,
  index : Int,
) -> LayoutNode {
  let idx = if index < 0 {
    0
  } else if index > self.children.length() {
    self.children.length()
  } else {
    index
  }
  self.children.insert(idx, child)
  self.mark_dirty()
  self
}

///|
/// Add child at end
pub fn LayoutNode::add_child(
  self : LayoutNode,
  child : LayoutNode,
) -> LayoutNode {
  self.children.push(child)
  self.mark_dirty()
  self
}

///|
/// Remove child at index
pub fn LayoutNode::remove_child_at(
  self : LayoutNode,
  index : Int,
) -> LayoutNode? {
  if index >= 0 && index < self.children.length() {
    let removed = self.children.remove(index)
    self.mark_dirty()
    Some(removed)
  } else {
    None
  }
}

///|
/// Remove all children
pub fn LayoutNode::remove_all_children(self : LayoutNode) -> Unit {
  if self.children.length() > 0 {
    self.children.clear()
    self.mark_dirty()
  }
}

// =============================================================================
// LayoutTree - Yoga-like API
// =============================================================================

///|
/// Calculate layout (Yoga-compatible name)
/// Returns the root layout and stores computed layouts on each node
pub fn LayoutTree::calculate_layout(
  self : LayoutTree,
  width : Double,
  height : Double,
) -> @layout_types.Layout {
  // Update viewport if changed
  if (self.viewport_width - width).abs() > 0.001 ||
    (self.viewport_height - height).abs() > 0.001 {
    self.resize_viewport(width, height)
  }
  // Compute layout
  let layout = self.compute_incremental()
  // Store computed layouts on nodes
  store_computed_layouts(self.root, layout)
  layout
}

///|
/// Store computed layout results on nodes recursively
/// Only sets has_new_layout = true if the layout actually changed
fn store_computed_layouts(
  node : LayoutNode,
  layout : @layout_types.Layout,
) -> Unit {
  // Check if layout changed (with tolerance for floating point comparison)
  let changed = (node.computed_x - layout.x).abs() > 0.001 ||
    (node.computed_y - layout.y).abs() > 0.001 ||
    (node.computed_width - layout.width).abs() > 0.001 ||
    (node.computed_height - layout.height).abs() > 0.001

  // Store this node's computed layout
  node.computed_x = layout.x
  node.computed_y = layout.y
  node.computed_width = layout.width
  node.computed_height = layout.height
  node.has_new_layout = changed

  // Recurse to children
  for i, child in node.children {
    if i < layout.children.length() {
      store_computed_layouts(child, layout.children[i])
    }
  }
}

// =============================================================================
// Layout Result Getters
// =============================================================================

///|
/// Get computed X position (relative to parent)
pub fn LayoutNode::get_layout_x(self : LayoutNode) -> Double {
  self.computed_x
}

///|
/// Get computed Y position (relative to parent)
pub fn LayoutNode::get_layout_y(self : LayoutNode) -> Double {
  self.computed_y
}

///|
/// Get computed width
pub fn LayoutNode::get_layout_width(self : LayoutNode) -> Double {
  self.computed_width
}

///|
/// Get computed height
pub fn LayoutNode::get_layout_height(self : LayoutNode) -> Double {
  self.computed_height
}

///|
/// Check if node has new layout since last mark_layout_seen
pub fn LayoutNode::get_has_new_layout(self : LayoutNode) -> Bool {
  self.has_new_layout
}

///|
/// Mark that layout has been read (for incremental updates)
pub fn LayoutNode::mark_layout_seen(self : LayoutNode) -> Unit {
  self.has_new_layout = false
}

///|
/// Check if node is dirty
pub fn LayoutNode::is_dirty(self : LayoutNode) -> Bool {
  self.dirty
}

// =============================================================================
// Factory Methods
// =============================================================================

///|
/// Create a new node with default style (Yoga-compatible)
pub fn LayoutNode::create() -> LayoutNode {
  LayoutNode::new("", @style.Style::default(), [])
}

///|
/// Create a new node with ID
pub fn LayoutNode::create_with_id(id : String) -> LayoutNode {
  LayoutNode::new(id, @style.Style::default(), [])
}