#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "limine.h"
#include "drivers/tty.h"
#include "drivers/io.h"
#include "drivers/keyboard.h" 

// --- DELAY FUNCTION ---
// This handles the 5-second "Ourple" splash screen
void delay(uint64_t counts) {
    for (volatile uint64_t i = 0; i < counts; i++) {
        __asm__("nop");
    }
}

// --- LIMINE REQUESTS ---
static volatile struct limine_framebuffer_request framebuffer_request = {
    .id = LIMINE_FRAMEBUFFER_REQUEST,
    .revision = 0
};

// --- MATERIAL 3 COLOR PALETTE ---
#define M3_SURFACE         0x1C1B1F
#define M3_PRIMARY         0xD0BCFF
#define M3_PURPLE_ACCENT   0x381E72

// --- GRAPHICS STRUCTURE ---
struct framebuffer {
    uint32_t *address;
    uint64_t width;
    uint64_t height;
    uint64_t pitch;
};

// Function to draw a single pixel
void put_pixel(struct framebuffer *fb, uint32_t x, uint32_t y, uint32_t color) {
    if (x >= fb->width || y >= fb->height) return;
    fb->address[y * (fb->pitch / 4) + x] = color;
}

// Function to draw a rectangle
void draw_rect(struct framebuffer *fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color) {
    for (uint32_t i = 0; i < w; i++) {
        for (uint32_t j = 0; j < h; j++) {
            put_pixel(fb, x + i, y + j, color);
        }
    }
}

// --- SYSTEM TABLES (GDT) ---
struct gdt_entry {
    uint16_t limit_low;
    uint16_t base_low;
    uint8_t  base_middle;
    uint8_t  access;
    uint8_t  granularity;
    uint8_t  base_high;
} __attribute__((packed));

struct gdt_ptr {
    uint16_t limit;
    uint64_t base;
} __attribute__((packed));

struct gdt_entry gdt[3];
struct gdt_ptr gdt_p;

void init_gdt() {
    gdt[0] = (struct gdt_entry){0, 0, 0, 0, 0, 0};      // Null
    gdt[1] = (struct gdt_entry){0, 0, 0, 0x9A, 0x20, 0}; // Code
    gdt[2] = (struct gdt_entry){0, 0, 0, 0x92, 0, 0};    // Data

    gdt_p.limit = (sizeof(struct gdt_entry) * 3) - 1;
    gdt_p.base = (uint64_t)&gdt;
    __asm__ volatile("lgdt %0" : : "m"(gdt_p));
}

// --- KERNEL ENTRY POINT ---
void _start(void) {
    // 1. Check if we have a screen
    if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) {
        __asm__("hlt");
    }

    struct limine_framebuffer *fb_info = framebuffer_request.response->framebuffers[0];
    struct framebuffer fb = {
        .address = fb_info->address,
        .width = fb_info->width,
        .height = fb_info->height,
        .pitch = fb_info->pitch
    };

    // 2. Setup CPU state
    init_gdt();

    // 3. THE 5-SECOND OURPLE INTRO
    draw_rect(&fb, 0, 0, fb.width, fb.height, M3_PURPLE_ACCENT);
    delay(800000000); // Wait 5 seconds

    // 4. THE MATERIAL 3 UI
    draw_rect(&fb, 0, 0, fb.width, fb.height, M3_SURFACE); // Dark background
    
    // Draw the Pastel Purple Card
    uint32_t cw = 400; uint32_t ch = 200;
    draw_rect(&fb, (fb.width/2)-(cw/2), (fb.height/2)-(ch/2), cw, ch, M3_PRIMARY);

// ... (Your existing rect drawing code) ...

    // 5. BOOT THE TTY
    // We pass the fb address, White text (0xFFFFFF), and Dark background
    tty_init((struct tty_framebuffer*)&fb, 0xFFFFFF, M3_SURFACE);


    // 6. SAY HELLO!
    tty_print("FLORID OS BOOTED\n");
    tty_print("READY_");

    
    for (;;) {
        // Check Status Register (Port 0x64)
        // Bit 0 (0x01) tells us if a key is waiting
        if (inb(0x64) & 0x01) {
            update_keyboard();
        }
        
        // Give VirtualBox a tiny rest so it doesn't lag the host
        for(volatile int i = 0; i < 1000; i++); 
        __asm__("pause");
    }
}