use vga::{colors::Color16, writers::GraphicsWriter};

use crate::{
    hardware::{MOUSE, _MOUSE},
    vga_e::VGAE,
};
const TERM_MINUS_ONE_LINE: usize = 4720;
const CURSOR_COLOR: Color16 = Color16::Cyan;

#[derive(Debug)]
pub struct Term {
    dirty: bool,
    term: [char; 80 * 60],
    x: usize,
}
impl Term {
    pub fn new() -> Self {
        Self {
            dirty: false,
            x: 0,
            term: ['\0'; 80 * 60],
        }
    }
    pub fn is_dirty(&self) -> bool {
        self.dirty
    }

    pub fn set_dirty(&mut self, dirty: bool) {
        self.dirty = dirty
    }

    pub fn print(&mut self, data: String) {
        for c in data.chars() {
            if self.x == 79 || c == '\n' {
                self.move_up();
                self.x = 0;
            } else {
                self.term[TERM_MINUS_ONE_LINE + self.x] = c;
                self.x += 1;
            }
        }
    }
    pub fn move_up(&mut self) {
        self.term.rotate_left(80);
        for x in 0..80 {
            self.term[TERM_MINUS_ONE_LINE + x] = '\0';
        }
    }
    pub fn initialize(&self) {
        let mode = VGAE.lock();
        mode.set_mode();
        drop(mode);
    }

    pub fn draw_term(&mut self) {
        if self.is_dirty() {
            trace!("Redrawing");
            let mode = VGAE.lock();
            mode.clear_screen(Color16::Black);

            let mouse_coord = x86_64::instructions::interrupts::without_interrupts(|| {
                let cursor = MOUSE.lock();

                (cursor.get_x() as usize, cursor.get_y() as usize)
            });

            mode.draw_line(
                (mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 0),
                (mouse_coord.0 as isize + 10, mouse_coord.1 as isize + 10),
                CURSOR_COLOR,
            );
            mode.draw_line(
                (mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 0),
                (mouse_coord.0 as isize + 5, mouse_coord.1 as isize + 0),
                CURSOR_COLOR,
            );
            mode.draw_line(
                (mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 0),
                (mouse_coord.0 as isize + 0, mouse_coord.1 as isize + 5),
                CURSOR_COLOR,
            );

            let mut x = 0;
            let mut y = 0;

            for c in self.term {
                mode.draw_character(x * 8, y * 8, c, Color16::White);

                if x == 79 {
                    y += 1;
                    x = 0;
                } else {
                    x += 1
                }
            }
            self.set_dirty(true);
            trace!("Finished drawing");
        }
    }
}
