/// ScrollView — scrollable container.
///
/// Wraps content that may exceed the available space. Scrolling axis can be
/// vertical (default), horizontal, or both. On platforms with native scroll
/// behaviors (iOS, Android), the backend translates this to a native scroll
/// container — you get momentum, overscroll, pull-to-refresh for free.

use el_style::modifier::{StyleModifier, StyleSet};

/// Which axis (or axes) can scroll.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScrollAxis {
    /// Vertical scrolling only (default). Most content views.
    Vertical,
    /// Horizontal scrolling only. Carousels, horizontal lists.
    Horizontal,
    /// Free scrolling in both directions. Maps, canvases.
    Both,
}

/// Scroll indicator visibility.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScrollIndicator {
    /// Show when scrolling, hide otherwise (platform default).
    Automatic,
    /// Always show.
    Always,
    /// Never show.
    Never,
}

/// A scrollable container.
#[derive(Debug, Clone)]
pub struct ScrollView {
    pub axis: ScrollAxis,
    pub indicator: ScrollIndicator,
    /// Whether the user can zoom (pinch-to-zoom). Default: false.
    pub zoomable: bool,
    /// Minimum zoom scale (only relevant when zoomable = true).
    pub min_zoom: f32,
    /// Maximum zoom scale (only relevant when zoomable = true).
    pub max_zoom: f32,
    /// Whether to clip content to the scroll view bounds. Default: true.
    pub clips_to_bounds: bool,
    pub style: StyleSet,
}

impl Default for ScrollView {
    fn default() -> Self {
        Self {
            axis: ScrollAxis::Vertical,
            indicator: ScrollIndicator::Automatic,
            zoomable: false,
            min_zoom: 1.0,
            max_zoom: 3.0,
            clips_to_bounds: true,
            style: StyleSet::default(),
        }
    }
}

impl ScrollView {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn horizontal() -> Self {
        Self {
            axis: ScrollAxis::Horizontal,
            ..Self::default()
        }
    }

    pub fn both_axes() -> Self {
        Self {
            axis: ScrollAxis::Both,
            ..Self::default()
        }
    }

    pub fn indicator(mut self, indicator: ScrollIndicator) -> Self {
        self.indicator = indicator;
        self
    }

    pub fn zoomable(mut self, min: f32, max: f32) -> Self {
        self.zoomable = true;
        self.min_zoom = min;
        self.max_zoom = max;
        self
    }
}

impl StyleModifier for ScrollView {
    fn style_mut(&mut self) -> &mut StyleSet {
        &mut self.style
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn scroll_default_is_vertical() {
        let sv = ScrollView::new();
        assert_eq!(sv.axis, ScrollAxis::Vertical);
    }

    #[test]
    fn scroll_horizontal_constructor() {
        let sv = ScrollView::horizontal();
        assert_eq!(sv.axis, ScrollAxis::Horizontal);
    }

    #[test]
    fn scroll_both_axes() {
        let sv = ScrollView::both_axes();
        assert_eq!(sv.axis, ScrollAxis::Both);
    }

    #[test]
    fn scroll_zoomable() {
        let sv = ScrollView::new().zoomable(0.5, 4.0);
        assert!(sv.zoomable);
        assert_eq!(sv.min_zoom, 0.5);
        assert_eq!(sv.max_zoom, 4.0);
    }

    #[test]
    fn scroll_clips_by_default() {
        let sv = ScrollView::new();
        assert!(sv.clips_to_bounds);
    }

    #[test]
    fn scroll_indicator_setting() {
        let sv = ScrollView::new().indicator(ScrollIndicator::Never);
        assert_eq!(sv.indicator, ScrollIndicator::Never);
    }
}
