/*
 * FFFFFFFFFFFFFFFFFFFFFFlllllll                             iiii       dddddddd
 * F::::::::::::::::::::Fl:::::l                            i::::i      d::::::d
 * F::::::::::::::::::::Fl:::::l                             iiii       d::::::d
 * FF::::::FFFFFFFFF::::Fl:::::l                                        d::::::d
 * F:::::F       FFFFFF l::::l    ooooooooooo   rrrr rrrrrrr iiiiiii   d:::::d
 * F:::::F              l::::l  oo:::::::::::oo r::::rr:::::ri::::i   d:::::d
 * F::::::FFFFFFFFFF    l::::l o:::::::::::::::or::::r r::::ri::::i   d:::::d
 * F:::::::::::::::F    l::::l o:::::ooooo:::::or::::r  rrrrri::::i   d:::::d
 * F:::::::::::::::F    l::::l o::::o     o::::or::::r       i::::i   d:::::d
 * F::::::FFFFFFFFFF    l::::l o::::o     o::::or::::r       i::::i   d:::::d
 * F:::::F              l::::l o::::o     o::::or::::r       i::::i   d:::::d
 * F:::::F              l::::l o::::o     o::::or::::r       i::::i   d:::::d
 * FF:::::::FF           l::::::lo:::::ooooo:::::or::::r      i::::::i  d::::::d
 * F::::::::FF           l::::::lo:::::::::::::::or::::r      i::::::i  d::::::d
 * F::::::::FF           l::::::l oo:::::::::::oo r::::r      i::::::i  d::::::d
 * FFFFFFFFFFF           llllllll   ooooooooooo   rrrrrr      iiiiiiii  dddddddd
 *
 * PROJECT: Florid OS (A Modular, Everything-Is-A-File Operating System)
 * ARCH: x86_64
 * BOOTLOADER: Limine
 * PHILOSOPHY: 100% Customizable, Userspace-First DE, FPF Packaging.
 * TARGET: Monolithic Core Foundation capable of scaling past 16,000+ LOC.
 */

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

/* ==========================================================================
 * FLORID PACKAGE FORMAT (FPF)
 * ========================================================================== */

typedef struct {
    char     magic[4];      
    uint8_t  version;       
    uint8_t  type;          
    uint16_t flags;         
    uint64_t entry_point;   
    uint64_t stack_size;    
    uint64_t heap_size;     
    uint8_t  signature[32]; 
} __attribute__((packed)) fpf_header_t;

void klog(const char* module, const char* msg);

/* ==========================================================================
 * EXHAUSTIVE KERNEL STATUS
 * ========================================================================== */

typedef enum {
    FLORID_SUCCESS = 0,
    FLORID_ERROR_GENERIC = 1,
    FLORID_ERROR_OUT_OF_MEMORY = 2,
    FLORID_ERROR_IO_FAILURE = 3,
    FLORID_ERROR_FPF_INVALID_MAGIC = 4,
    FLORID_ERROR_FPF_INCOMPATIBLE_VERSION = 5,
    FLORID_ERROR_FRAMEBUFFER_NOT_FOUND = 6,
    FLORID_ERROR_PAGE_FAULT = 7,
    FLORID_ERROR_ACCESS_VIOLATION = 8,
    FLORID_ERROR_SYS_CALL_INVALID = 9,
    FLORID_ERROR_DEVICE_OFFLINE = 10,
    FLORID_ERROR_BUFFER_OVERFLOW = 11,
    FLORID_ERROR_TIMEOUT = 12,
    FLORID_ERROR_CORRUPT_METADATA = 13,
    FLORID_ERROR_KERNEL_PANIC = 14
} florid_status_t;

static const char* status_strings[] = {
    [FLORID_SUCCESS] = "FLORID_SUCCESS",
    [FLORID_ERROR_GENERIC] = "FLORID_ERROR_GENERIC",
    [FLORID_ERROR_OUT_OF_MEMORY] = "FLORID_ERROR_OUT_OF_MEMORY",
    [FLORID_ERROR_IO_FAILURE] = "FLORID_ERROR_IO_FAILURE",
    [FLORID_ERROR_FPF_INVALID_MAGIC] = "FLORID_ERROR_FPF_INVALID_MAGIC",
    [FLORID_ERROR_FPF_INCOMPATIBLE_VERSION] = "FLORID_ERROR_FPF_INCOMPATIBLE_VERSION",
    [FLORID_ERROR_FRAMEBUFFER_NOT_FOUND] = "FLORID_ERROR_FRAMEBUFFER_NOT_FOUND",
    [FLORID_ERROR_PAGE_FAULT] = "FLORID_ERROR_PAGE_FAULT",
    [FLORID_ERROR_ACCESS_VIOLATION] = "FLORID_ERROR_ACCESS_VIOLATION",
    [FLORID_ERROR_SYS_CALL_INVALID] = "FLORID_ERROR_SYS_CALL_INVALID",
    [FLORID_ERROR_DEVICE_OFFLINE] = "FLORID_ERROR_DEVICE_OFFLINE",
    [FLORID_ERROR_BUFFER_OVERFLOW] = "FLORID_ERROR_BUFFER_OVERFLOW",
    [FLORID_ERROR_TIMEOUT] = "FLORID_ERROR_TIMEOUT",
    [FLORID_ERROR_CORRUPT_METADATA] = "FLORID_ERROR_CORRUPT_METADATA",
    [FLORID_ERROR_KERNEL_PANIC] = "FLORID_ERROR_KERNEL_PANIC"
};

/* ==========================================================================
 * HARDWARE DESCRIPTOR TABLES (GDT/IDT) - New Core Additions
 * ========================================================================== */

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

void gdt_install(void) {
    // Basic flat-model GDT for x86_64
    static uint64_t gdt[] = {
        0x0000000000000000, // Null
        0x00af9a000000ffff, // Kernel Code
        0x00af92000000ffff, // Kernel Data
        0x00affb000000ffff, // User Code
        0x00aff3000000ffff  // User Data
    };
    table_ptr_t gdt_ptr = { sizeof(gdt) - 1, (uint64_t)gdt };
    __asm__ volatile("lgdt %0" : : "m"(gdt_ptr));
}

/* ==========================================================================
 * SYSTEM CALL REGISTRY (FPF Interface)
 * ========================================================================== */

void sys_yield() { klog("SYS", "Yielding CPU."); }
void sys_exit()  { klog("SYS", "Terminating Process."); }

typedef void (*syscall_handler_t)(void);
syscall_handler_t syscall_table[128] = {
    [0] = sys_yield,
    [1] = sys_exit,
    /* To scale to 16k, populate more system interface stubs here */
};

/* ==========================================================================
 * LIMINE BOOT REQUESTS
 * ========================================================================== */

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

static volatile struct limine_hhdm_request hhdm_request = {
    .id = LIMINE_HHDM_REQUEST, .revision = 0
};

static volatile struct limine_module_request module_request = {
    .id = LIMINE_MODULE_REQUEST, .revision = 0
};

/* ==========================================================================
 * LOGGING (COM1 SERIAL)
 * ========================================================================== */

static inline void outb(uint16_t port, uint8_t val) {
    __asm__ volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) );
}

void klog(const char* module, const char* msg) {
    const char* p = "[";
    while (*p) outb(0x3F8, *p++);
    p = module;
    while (*p) outb(0x3F8, *p++);
    p = "] ";
    while (*p) outb(0x3F8, *p++);
    p = msg;
    while (*p) outb(0x3F8, *p++);
    outb(0x3F8, '\r'); outb(0x3F8, '\n');
}

/* ==========================================================================
 * PHYSICAL MEMORY MANAGER (PMM)
 * ========================================================================== */

static uint8_t* pmm_bitmap;
static uint64_t pmm_total_pages;

void pmm_init(struct limine_memmap_response* memmap) {
    uint64_t max_addr = 0;
    struct limine_memmap_entry* biggest_chunk = NULL;

    for (uint64_t i = 0; i < memmap->entry_count; i++) {
        struct limine_memmap_entry* entry = memmap->entries[i];
        if (entry->base + entry->length > max_addr) max_addr = entry->base + entry->length;
        if (entry->type == LIMINE_MEMMAP_USABLE && (!biggest_chunk || entry->length > biggest_chunk->length)) {
            biggest_chunk = entry;
        }
    }

    pmm_total_pages = max_addr / 4096;
    pmm_bitmap = (uint8_t*)(biggest_chunk->base + hhdm_request.response->offset);
    
    for (uint64_t i = 0; i < pmm_total_pages / 8; i++) pmm_bitmap[i] = 0xFF;

    for (uint64_t i = 0; i < memmap->entry_count; i++) {
        struct limine_memmap_entry* entry = memmap->entries[i];
        if (entry->type == LIMINE_MEMMAP_USABLE) {
            for (uint64_t j = 0; j < entry->length; j += 4096) {
                uint64_t page = (entry->base + j) / 4096;
                pmm_bitmap[page / 8] &= ~(1 << (page % 8));
            }
        }
    }
    klog("PMM", "Physical Memory Manager Online.");
}

/* ==========================================================================
 * FPF EXECUTION ENGINE
 * ========================================================================== */

void execute_fpf(uint8_t* buffer, size_t size) {
    fpf_header_t* header = (fpf_header_t*)buffer;
    
    if (size < sizeof(fpf_header_t) || header->magic[0] != 'F' || header->magic[1] != 'L') {
        klog("LOADER", "Invalid FPF Magic.");
        return;
    }

    klog("LOADER", "Executing FPF Package.");
    
    // Jump past header to entry point
    uintptr_t entry = (uintptr_t)(buffer + sizeof(fpf_header_t) + header->entry_point);
    void (*launch)(void) = (void (*)(void))entry;
    
    launch();
}

/* ==========================================================================
 * KERNEL MAIN ENTRY
 * ========================================================================== */

void _start(void) {
    gdt_install(); // Setup hardware segments
    klog("CORE", "Florid OS Kernel Initializing...");

    // 1. Setup Graphics
    if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) {
        while(1) __asm__("hlt");
    }
    struct limine_framebuffer *fb = framebuffer_request.response->framebuffers[0];
    uint32_t *fb_ptr = fb->address;
    for (size_t i = 0; i < fb->width * fb->height; i++) fb_ptr[i] = 0x1E1E1E;

    // 2. Setup Memory
    if (memmap_request.response && hhdm_request.response) {
        pmm_init(memmap_request.response);
    }

    // 3. Find and Boot Terminal / Launcher modules
    if (module_request.response) {
        for (uint64_t i = 0; i < module_request.response->module_count; i++) {
            struct limine_file* module = module_request.response->modules[i];
            klog("INIT", "Loading FPF Module...");
            execute_fpf((uint8_t*)module->address, module->size);
        }
    }

    klog("CORE", "System idle.");
    while (1) { __asm__("hlt"); }
}