tv 0.1.1

Terminal User Interface library
Documentation
use crate::error::Result;
/// Layer - manages layered surfaces with z-ordering
///
/// Layers provide a way to manage overlapping surfaces with automatic
/// z-order handling and efficient updates.
use crate::surface::Surface;
use std::sync::{Mutex, OnceLock};

static PANEL_STACK: OnceLock<Mutex<Vec<usize>>> = OnceLock::new();

/// A layer wraps a surface and provides z-ordering
pub struct Layer {
    surface: Surface,
    layer_id: usize,
    hidden: bool,
}

impl Layer {
    /// Create a new layer from a surface
    pub fn new(surface: Surface) -> Result<Self> {
        let layer_id = Self::register_layer();

        Ok(Self {
            surface,
            layer_id,
            hidden: false,
        })
    }

    /// Get a reference to the surface
    pub fn surface(&self) -> &Surface {
        &self.surface
    }

    /// Get a mutable reference to the surface
    pub fn surface_mut(&mut self) -> &mut Surface {
        &mut self.surface
    }

    /// Move this layer to the top of the stack
    pub fn top(&mut self) -> Result<()> {
        let stack = PANEL_STACK.get_or_init(|| Mutex::new(Vec::new()));
        let mut guard = stack.lock().unwrap();

        if let Some(pos) = guard.iter().position(|&id| id == self.layer_id) {
            guard.remove(pos);
            guard.push(self.layer_id);
        }

        Ok(())
    }

    /// Move this layer to the bottom of the stack
    pub fn bottom(&mut self) -> Result<()> {
        let stack = PANEL_STACK.get_or_init(|| Mutex::new(Vec::new()));
        let mut guard = stack.lock().unwrap();

        if let Some(pos) = guard.iter().position(|&id| id == self.layer_id) {
            guard.remove(pos);
            guard.insert(0, self.layer_id);
        }

        Ok(())
    }

    /// Hide this layer
    pub fn hide(&mut self) -> Result<()> {
        self.hidden = true;
        Ok(())
    }

    /// Show this layer
    pub fn show(&mut self) -> Result<()> {
        self.hidden = false;
        Ok(())
    }

    /// Check if layer is hidden
    pub fn is_hidden(&self) -> bool {
        self.hidden
    }

    /// Update the layer's surface
    pub fn refresh(&mut self) -> Result<()> {
        if !self.hidden {
            self.surface.refresh()
        } else {
            Ok(())
        }
    }

    /// Update internal buffer without refreshing
    pub fn wnoutrefresh(&mut self) -> Result<()> {
        if !self.hidden {
            self.surface.wnoutrefresh()
        } else {
            Ok(())
        }
    }

    fn register_layer() -> usize {
        let stack = PANEL_STACK.get_or_init(|| Mutex::new(Vec::new()));
        let mut guard = stack.lock().unwrap();

        let id = guard.len();
        guard.push(id);
        id
    }
}

impl Drop for Layer {
    fn drop(&mut self) {
        let stack = PANEL_STACK.get_or_init(|| Mutex::new(Vec::new()));
        let mut guard = stack.lock().unwrap();

        if let Some(pos) = guard.iter().position(|&id| id == self.layer_id) {
            guard.remove(pos);
        }
    }
}

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

    #[test]
    fn test_layer_creation() {
        let win = Surface::new(10, 20, 5, 5).unwrap();
        let layer = Layer::new(win).unwrap();
        assert!(!layer.is_hidden());
    }

    #[test]
    fn test_layer_hide_show() {
        let win = Surface::new(10, 20, 5, 5).unwrap();
        let mut layer = Layer::new(win).unwrap();

        assert!(!layer.is_hidden());

        layer.hide().unwrap();
        assert!(layer.is_hidden());

        layer.show().unwrap();
        assert!(!layer.is_hidden());
    }

    #[test]
    fn test_layer_surface_access() {
        let win = Surface::new(10, 20, 5, 5).unwrap();
        let mut layer = Layer::new(win).unwrap();

        assert_eq!(layer.surface().get_size(), (10, 20));
        assert_eq!(layer.surface().get_position(), (5, 5));

        // Test mutable access
        layer
            .surface_mut()
            .set_foreground(crate::color::Color::RED)
            .unwrap();
    }

    #[test]
    fn test_layer_z_order() {
        let win1 = Surface::new(10, 20, 0, 0).unwrap();
        let win2 = Surface::new(10, 20, 5, 5).unwrap();

        let mut layer1 = Layer::new(win1).unwrap();
        let mut layer2 = Layer::new(win2).unwrap();

        layer1.top().unwrap();
        layer2.bottom().unwrap();

        // Just verify no panics
        assert_eq!(layer1.layer_id, 0);
        assert_eq!(layer2.layer_id, 1);
    }
}