///|
/// Item-based scroller - simpler concept for scrolling through items
///
/// Concepts:
/// - total_items: number of items in the list
/// - visible_count: maximum number of items to display at once
/// - offset: index of the first visible item (0 = top)

///|
/// Simple item scroller state
pub(all) struct ItemScroller {
  /// Current offset (index of first visible item)
  offset : @signals.Signal[Int]
  /// Auto-scroll to bottom when new items added
  auto_scroll : @signals.Signal[Bool]
}

///|
pub fn ItemScroller::new() -> ItemScroller {
  { offset: @signals.signal(0), auto_scroll: @signals.signal(true) }
}

///|
/// Calculate max offset
/// total_items: number of items
/// visible_count: number of items that can be displayed
fn calc_max_offset(total_items : Int, visible_count : Int) -> Int {
  if total_items > visible_count {
    total_items - visible_count
  } else {
    0
  }
}

///|
/// Scroll up by n items
pub fn ItemScroller::up(self : ItemScroller, n : Int) -> Bool {
  let current = self.offset.get()
  if current > 0 {
    let new_offset = if current >= n { current - n } else { 0 }
    self.offset.set(new_offset)
    self.auto_scroll.set(false)
    true
  } else {
    false
  }
}

///|
/// Scroll down by n items
pub fn ItemScroller::down(
  self : ItemScroller,
  n : Int,
  total_items : Int,
  visible_count : Int,
) -> Bool {
  let max = calc_max_offset(total_items, visible_count)
  let current = self.offset.get()
  if current < max {
    let new_offset = if current + n > max { max } else { current + n }
    self.offset.set(new_offset)
    if new_offset >= max {
      self.auto_scroll.set(true)
    }
    true
  } else {
    false
  }
}

///|
/// Jump to bottom
pub fn ItemScroller::to_bottom(
  self : ItemScroller,
  total_items : Int,
  visible_count : Int,
) -> Unit {
  let max = calc_max_offset(total_items, visible_count)
  self.offset.set(max)
  self.auto_scroll.set(true)
}

///|
/// Auto-scroll to bottom if enabled
pub fn ItemScroller::follow_bottom(
  self : ItemScroller,
  total_items : Int,
  visible_count : Int,
) -> Unit {
  if self.auto_scroll.get() {
    self.to_bottom(total_items, visible_count)
  }
}

///|
/// Check if can scroll up
pub fn ItemScroller::can_scroll_up(self : ItemScroller) -> Bool {
  self.offset.get() > 0
}

///|
/// Check if can scroll down
pub fn ItemScroller::can_scroll_down(
  self : ItemScroller,
  total_items : Int,
  visible_count : Int,
) -> Bool {
  self.offset.get() < calc_max_offset(total_items, visible_count)
}

///|
/// Get visible slice of items
pub fn[T] ItemScroller::slice(
  self : ItemScroller,
  items : Array[T],
  visible_count : Int,
) -> Array[T] {
  let offset = self.offset.get()
  let result : Array[T] = []
  for i, item in items {
    if i >= offset && result.length() < visible_count {
      result.push(item)
    }
  }
  result
}

///|
/// Scroll indicator for item scroller
pub fn ItemScroller::indicator(
  self : ItemScroller,
  total_items : Int,
  visible_count : Int,
) -> ScrollIndicator {
  let can_up = self.can_scroll_up()
  let can_down = self.can_scroll_down(total_items, visible_count)
  if can_up && can_down {
    ScrollIndicator::Both
  } else if can_up {
    ScrollIndicator::Up
  } else if can_down {
    ScrollIndicator::Down
  } else {
    ScrollIndicator::None
  }
}