// SPDX-License-Identifier: LCL-1.0
// Copyright (c) 2026 Markus Maiwald
// Stewardship: Self Sovereign Society Foundation
//
// This file is part of the Nexus Commonwealth.
// See legal/LICENSE_COMMONWEALTH.md for license terms.

//! Rumpk HAL ABI: The Contract between L0 (Zig) and L1 (Nim)
//!
//! This struct defines the function pointer table for platform abstraction.
//! All function pointers use C calling convention for Nim FFI compatibility.

// NOTE(Build): Zig 0.15.x requires explicit callconv on extern struct fn pointers
pub const HAL = extern struct {
    /// Write to console/serial
    console_write: *const fn ([*]const u8, usize) callconv(.c) void,

    /// Allocate physical pages
    palloc: *const fn (usize) callconv(.c) ?*anyopaque,

    /// Free physical pages
    pfree: *const fn (*anyopaque) callconv(.c) void,

    /// Register interrupt handler
    irq_register: *const fn (u8, *const fn () callconv(.c) void) callconv(.c) void,

    /// Get current time in nanoseconds
    timer_now_ns: *const fn () callconv(.c) u64,

    /// Halt the CPU
    halt: *const fn () callconv(.c) noreturn,
};

// SAFETY(HAL): Global instance initialized by init() before any access.
// SAFETY(HAL): Global HAL instance is populated by `init()` during the early boot phase.
pub var hal: HAL = undefined;

/// Initialize the HAL with platform-specific implementations
pub fn init(console: anytype, allocator: anytype) void {
    hal = HAL{
        .console_write = console.write,
        .palloc = allocator.alloc,
        .pfree = allocator.free,
        // SAFETY(HAL): Placeholders for future implementation.
        // These function pointers are not called until implemented.
        .irq_register = undefined, // TODO(HAL): Implement IRQ registration
        .timer_now_ns = undefined, // TODO(HAL): Implement timer
        .halt = halt_impl,
    };
}

fn halt_impl() callconv(.c) noreturn {
    while (true) {
        asm volatile ("wfi");
    }
}

// =========================================================
// Exports for Nim FFI
// =========================================================

export fn rumpk_console_write(ptr: [*]const u8, len: usize) void {
    hal.console_write(ptr, len);
}

export fn rumpk_palloc(pages: usize) ?*anyopaque {
    return hal.palloc(pages);
}

export fn rumpk_pfree(ptr: *anyopaque) void {
    hal.pfree(ptr);
}

export fn rumpk_halt() noreturn {
    hal.halt();
}

var mock_ticks: u64 = 0;

export fn rumpk_timer_now_ns() u64 {
    // Phase 1 Mock: Incrementing counter to simulate time passage per call
    mock_ticks += 100000; // 100us per call
    return mock_ticks;
}

// =========================================================
// Ground Zero Phase 1: CSpace Integration (SPEC-020)
// =========================================================

pub const cspace = @import("cspace.zig");

// Re-export CSpace functions for Nim FFI
pub const cspace_init = cspace.cspace_init;
pub const cspace_get = cspace.cspace_get;
pub const cspace_grant_cap = cspace.cspace_grant_cap;
pub const cspace_lookup = cspace.cspace_lookup;
pub const cspace_revoke = cspace.cspace_revoke;
pub const cspace_check_perm = cspace.cspace_check_perm;
