#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "limine.h"

// --- LIMINE REQUESTS ---
// These tell the bootloader what we want (Framebuffer and Memory Map)
static volatile struct limine_framebuffer_request framebuffer_request = {
    .id = LIMINE_FRAMEBUFFER_REQUEST,
    .revision = 0
};

static volatile struct limine_memmap_request memmap_request = {
    .id = LIMINE_MEMMAP_REQUEST,
    .revision = 0
};

// --- MATERIAL 3 COLOR PALETTE ---
#define M3_SURFACE         0x1C1B1F
#define M3_PRIMARY         0xD0BCFF
#define M3_SECONDARY       0xCCC2DC
#define M3_ERROR           0xF2B8B5
#define M3_ON_SURFACE      0xE6E1E5
#define M3_PURPLE_ACCENT   0x381E72

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

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;
}

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) ---
// This defines how memory segments are handled
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() {
    // Null segment
    gdt[0] = (struct gdt_entry){0, 0, 0, 0, 0, 0};
    // Code segment (Kernel)
    gdt[1] = (struct gdt_entry){0, 0, 0, 0x9A, 0x20, 0};
    // Data segment (Kernel)
    gdt[2] = (struct gdt_entry){0, 0, 0, 0x92, 0, 0};

    gdt_p.limit = (sizeof(struct gdt_entry) * 3) - 1;
    gdt_p.base = (uint64_t)&gdt;
    
    // Inline assembly to load the GDT
    __asm__ volatile("lgdt %0" : : "m"(gdt_p));
}

// --- KERNEL MAIN ---
void _start(void) {
    // 1. Safety Check: Did the bootloader give us 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. Initialize System
    init_gdt();

    // 3. Draw Florid OS Background (Material 3 Surface)
    draw_rect(&fb, 0, 0, fb.width, fb.height, M3_SURFACE);

    // 4. Draw a "Material 3" Card in the center
    uint32_t card_w = 400;
    uint32_t card_h = 200;
    draw_rect(&fb, (fb.width/2)-(card_w/2), (fb.height/2)-(card_h/2), card_w, card_h, M3_PURPLE_ACCENT);

    // Halt the CPU
    for (;;) {
        __asm__("hlt");
    }
}