use super::render::RenderError;
use crate::arch::x86_64::drivers::framebuffer::colour::Colour;
use crate::arch::x86_64::drivers::framebuffer::display::FRAMEBUFFER_WRITER;
use crate::std::maths::geometry::Vec2;
use alloc::string::String;

pub struct Window {
    dimensions: Vec2<usize>,
    position: Vec2<usize>,
    bordered: bool,
    opened: bool,
    title: String,
}

impl Window {
    pub const fn new() -> Self {
        Self {
            dimensions: Vec2::new(0, 0),
            position: Vec2::new(0, 0),
            bordered: true,
            opened: false,
            title: String::new(),
        }
    }

    pub fn render(&self, _data: &[&[Colour]]) -> Result<(), RenderError> {
        // TODO: error handling!! the kernel should return an error in some
        // cases
        if let Some(fb) = FRAMEBUFFER_WRITER.lock().as_mut() {
            fb.render_frame(_data);
        }
        Ok(())
    }

    pub const fn is_bordered(&self) -> bool {
        self.bordered
    }

    pub const fn is_open(&self) -> bool {
        self.opened
    }

    pub const fn open(&mut self) {
        self.opened = true;
    }

    pub const fn close(&mut self) {
        self.opened = false;
    }

    // some basic getters and setters for utility.
    pub fn title(&'static self) -> &'static str {
        self.title.as_str()
    }

    pub const fn dimensions(&self) -> Vec2<usize> {
        self.dimensions
    }

    pub const fn position(&self) -> Vec2<usize> {
        self.position
    }

    pub fn set_title(&mut self, title: String) {
        self.title = title;
    }

    pub fn move_window(&mut self, offset: Vec2<usize>) {
        self.position += offset;
    }

    pub const fn set_position(&mut self, position: Vec2<usize>) {
        self.position = position;
    }

    pub const fn set_dimensions(&mut self, dimensions: Vec2<usize>) {
        self.dimensions = dimensions;
    }
}

impl Default for Window {
    fn default() -> Self {
        Self::new()
    }
}

impl Drop for Window {
    fn drop(&mut self) {
        if self.opened {
            self.close();
        }
    }
}
