import pyopencl as cl
import numpy as np
import time

# -------------------------------
# Constants
# -------------------------------
PHI = 1.6180339887
SQRT_PHI = PHI ** 0.5
INSTANCES = 8
SLOTS_PER_INSTANCE = 32
SUPERVISOR_TICKS = 200

# Minimal "Debian tasks" per instance
DEBIAN_TASKS = [
    ["init", "network", "filesystem", "scheduler"],
    ["init", "ssh", "logger", "scheduler"],
    ["init", "cron", "filesystem", "monitor"],
    ["init", "network", "scheduler", "logger"],
    ["init", "scheduler", "monitor", "cron"],
    ["init", "filesystem", "network", "logger"],
    ["init", "monitor", "scheduler", "ssh"],
    ["init", "network", "cron", "monitor"]
]

# -------------------------------
# OpenCL setup
# -------------------------------
platforms = cl.get_platforms()
device = platforms[0].get_devices()[0]
ctx = cl.Context([device])
queue = cl.CommandQueue(ctx)
mf = cl.mem_flags

# Supervisor kernel: evolve lattice
kernel_source = """
__kernel void lattice_evolve(
    __global float *lattice,
    __global float *workspace,
    const float threshold,
    const int slots_per_instance
) {
    int gid = get_global_id(0);
    int instance = gid / slots_per_instance;
    int slot = gid % slots_per_instance;

    float val = workspace[gid];
    lattice[gid] = val >= threshold ? 1.0f : 0.0f;

    if(instance > 0)
        lattice[gid] = 0.5f * (lattice[gid] + lattice[gid - slots_per_instance]);

    workspace[gid] = val + 0.01f * (instance + 1);
}
"""
program = cl.Program(ctx, kernel_source).build()
kernel = program.lattice_evolve

# -------------------------------
# Buffers
# -------------------------------
total_slots = INSTANCES * SLOTS_PER_INSTANCE
lattice_host = np.zeros(total_slots, dtype=np.float32)
workspace_host = np.random.uniform(SQRT_PHI, 2*SQRT_PHI, total_slots).astype(np.float32)

lattice_buf = cl.Buffer(ctx, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=lattice_host)
workspace_buf = cl.Buffer(ctx, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=workspace_host)

kernel.set_args(lattice_buf, workspace_buf, np.float32(SQRT_PHI), np.int32(SLOTS_PER_INSTANCE))

# -------------------------------
# Supervisor + Debian slot loader loop
# -------------------------------
print("HDGL Supervisor: Launching Debian slots...\n")

for tick in range(SUPERVISOR_TICKS):
    cl.enqueue_nd_range_kernel(queue, kernel, (total_slots,), None)

    if tick % 20 == 0:
        cl.enqueue_copy(queue, lattice_host, lattice_buf)

        print(f"[Tick {tick}] Instance lattice state:")
        for i in range(INSTANCES):
            slice_start = i * SLOTS_PER_INSTANCE
            slice_end = slice_start + SLOTS_PER_INSTANCE
            line = ''.join(['#' if val >= 1 else '.' for val in lattice_host[slice_start:slice_end]])
            # Display Debian tasks "activated" according to first 4 slots
            tasks_status = ["OK" if lattice_host[slice_start+j] >= 1 else "--" for j in range(4)]
            print(f"  Instance {i+1}: {line}  Tasks: {dict(zip(DEBIAN_TASKS[i], tasks_status))}")

    time.sleep(0.01)

print("\nDebian slots booted successfully within HDGL lattice supervisor.")
