import pyopencl as cl
import numpy as np
import math
import time

# -------------------------------
# Constants
# -------------------------------
PHI = 1.6180339887
SQRT_PHI = math.sqrt(PHI)
INSTANCES = 8
SLOTS_PER_INSTANCE = 32
SUPERVISOR_TICKS = 200

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

# -------------------------------
# OpenCL Kernel for HDGL evolution
# -------------------------------
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];

    // Binary discretization
    lattice[gid] = val >= threshold ? 1.0f : 0.0f;

    // Superposition: cross-instance effect
    if(instance > 0) {
        lattice[gid] = 0.5f * (lattice[gid] + lattice[gid - slots_per_instance]);
    }

    // Simple feedback for next tick
    workspace[gid] = val + 0.01f * (instance + 1);  // incremental evolution
}
"""

program = cl.Program(ctx, kernel_source).build()
kernel = program.lattice_evolve

# -------------------------------
# Allocate buffers
# -------------------------------
total_slots = INSTANCES * SLOTS_PER_INSTANCE
lattice_host = np.zeros(total_slots, dtype=np.float32)
workspace_host = np.random.uniform(
    low=SQRT_PHI, high=2*SQRT_PHI, size=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 loop
# -------------------------------
print("HDGL Supervisor starting... Persistent lattice control enabled.\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)

        # Console visualization: show each instance separately
        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]])
            print(f"[Tick {tick}] Instance {i+1}: {line}")

    # Optional: small delay to visualize progress
    time.sleep(0.01)

# -------------------------------
# Supervisor final report
# -------------------------------
print("\nSupervisor lattice evolution complete. Aggregated per-instance state:\n")
for i in range(INSTANCES):
    slice_start = i * SLOTS_PER_INSTANCE
    slice_end = slice_start + SLOTS_PER_INSTANCE
    hex_repr = hex(int(''.join(['1' if val >= 1 else '0' for val in lattice_host[slice_start:slice_end]]), 2))
    print(f"Instance {i+1} hex: {hex_repr}")

print("\nHDGL Supervisor: Persistent, GPU-native, Debian-compatible bootstrap layer ready.")
