#![no_std]
#![feature(abi_x86_interrupt)]

extern crate alloc;
extern crate multiboot2;
extern crate rlibc;

mod allocator;
mod gdt;
mod interrupt;
mod vga_buffer;

use core::panic::PanicInfo;
use multiboot2::{BootInformation, BootInformationHeader};

#[unsafe(no_mangle)]
pub extern "C" fn rust_main(multiboot_information_address: usize) {
    println!("Hello World!");
    //    println!(
    //        "This program booted itself from assembly. This println function manipulates individual bytes in a vga buffer. My power is beyond your understanding\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9"
    //    );
    let boot_info = unsafe {
        BootInformation::load(multiboot_information_address as *const BootInformationHeader)
            .unwrap()
    };
    let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required");
    init();
    println!("Got past");
    halt()
}

pub fn init() {
    allocator::init_heap

    println!("got to gdt::init()");
    gdt::init();
    println!("got to interrupt::init_idt();");
    interrupt::init_idt();
    println!("got to PICS.lock()");
    unsafe { interrupt::PICS.lock().initialize() };
    println!("got to enable inst");
    x86_64::instructions::interrupts::enable();
}

#[panic_handler]
pub fn panic(info: &PanicInfo) -> ! {
    println!("Panic happened: {}", info);
    halt()
}

pub fn halt() -> ! {
    println!("we've halted");
    loop {
        x86_64::instructions::hlt();
    }
}
