#include "pit.h"
#include "irq.h"
#include "io.h"
#include <stdint.h>
#include "stdio.h"
#include "e9.h"
#include "limine.h"

__attribute__((used, section(".limine_requests")))
volatile struct limine_date_at_boot_request boot_request = {
    .id = LIMINE_DATE_AT_BOOT_REQUEST_ID,
    .revision = 6,
};

#define PIT_BASE_FREQUENCY 1193182

#define PIT_COMMAND_PORT 0x43
#define PIT_CHANNEL0_PORT 0x40

volatile uint64_t g_Ticks = 0;
volatile uint64_t ticks = 0;
uint64_t g_Unixseconds = 0;

/* ========================= */
/* IRQ0 Handler (Timer Tick) */
/* ========================= */
void PIT_IRQ_Handler(Registers* regs)
{
    (void)regs;
    g_Ticks++;
    ticks++;
    if (ticks >= 1000) {
        g_Unixseconds++;
        ticks = 0;
    }


    // You can add scheduler / time logic here later
}

/* ========================= */
/* Initialize PIT            */
/* ========================= */
void x86_64_PIT_Initialize(uint32_t frequency)
{
    uint16_t divisor = (uint16_t)(PIT_BASE_FREQUENCY / frequency);

    printf("PIT divisor = %u\n", divisor);
    // Send command byte:
    // Channel 0 | lobyte/hibyte | mode 3 (square wave) | binary
    x86_64_outb(PIT_COMMAND_PORT, 0x36);

    // Send divisor (low byte then high byte)
    x86_64_outb(PIT_CHANNEL0_PORT, divisor & 0xFF);
    x86_64_outb(PIT_CHANNEL0_PORT, (divisor >> 8) & 0xFF);

    g_Unixseconds = boot_request.response->timestamp;

    // Register IRQ0 handler (IRQ0 = timer)
    x86_64_IRQ_RegisterHandler(0, PIT_IRQ_Handler);
}

/* ========================= */
/* Get tick count            */
/* ========================= */
uint64_t PIT_GetTicks(void)
{
    return g_Ticks;
}