use std::cell::Cell;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Rect {
    pub x: u32,
    pub y: u32,
    pub w: u32,
    pub h: u32,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Orientation {
    Horizontal,
    Vertical,
}

pub struct NodeLayout {
    pub rect: Cell<(Option<Rect>, bool)>,
}

impl NodeLayout {
    pub fn empty() -> Self {
        Self {
            rect: Cell::new((None, false)),
        }
    }

    pub fn set(&self, new: Rect) {
        let (old, _) = self.rect.get();
        let dirty = old.map_or(true, |old| old != new);
        self.rect.set((Some(new), dirty));
    }

    pub fn get(&self) -> Option<Rect> {
        let (value, _) = self.rect.get();
        value
    }

    pub fn clear(&self) {
        self.rect.set((None, false));
    }

    pub fn clear_dirty(&self) -> bool {
        let (value, dirty) = self.rect.get();
        self.rect.set((value, false));
        dirty && value.is_some()
    }
}

impl Direction {
    pub fn split(&self) -> (Orientation, isize) {
        match self {
            Self::Left => (Orientation::Horizontal, -1),
            Self::Right => (Orientation::Horizontal, 1),
            Self::Up => (Orientation::Vertical, -1),
            Self::Down => (Orientation::Vertical, 1),
        }
    }
}
