import numpy as np
import matplotlib.pyplot as plt
import threading
import time

# -----------------------------
# SIMULATION PARAMETERS
# -----------------------------
num_nodes = 16
num_strands = 8
slots_per_strand = 4
lattice_size = (num_strands, slots_per_strand)
duration = 5.0            # seconds
sample_rate = 2.048e6     # simulated sample rate
num_bands = 4
frequency_bands = [88e6, 92.3e6, 96.7e6, 101.1e6]  # simulated FM/AM bands

# -----------------------------
# PHYLLOTAXIS NODE POSITIONS
# -----------------------------
def phyllotaxis_positions(n, c=1.0):
    golden_angle = np.pi * (3 - np.sqrt(5))
    positions = []
    for i in range(n):
        r = c * np.sqrt(i)
        theta = i * golden_angle
        x = r * np.cos(theta)
        y = r * np.sin(theta)
        positions.append((x, y))
    return np.array(positions)

node_positions = phyllotaxis_positions(num_nodes)

# -----------------------------
# NODE LATTICES (HDGL Lattice)
# -----------------------------
node_lattices = [np.random.rand(*lattice_size) for _ in range(num_nodes)]

# -----------------------------
# EVOLVE LATTICE FUNCTION
# -----------------------------
def evolve_lattice(node_lattices, freqs, t):
    """
    Lattice riding multiple bands in superposition with phyllotaxis weighting.
    """
    composite = np.zeros_like(t)
    
    for node_idx, lattice in enumerate(node_lattices):
        # Small random evolution
        lattice += np.random.randn(*lattice.shape) * 0.005
        lattice = np.clip(lattice, 0, 1)
        
        # Phyllotaxis weighting (distance from origin)
        distance_weight = np.exp(-np.linalg.norm(node_positions[node_idx]))
        
        # Multi-band riding
        for band_idx, freq in enumerate(freqs):
            strand_idx = band_idx % lattice.shape[0]
            for slot_idx in range(lattice.shape[1]):
                delta_phase = lattice[strand_idx, slot_idx] * 0.05 * distance_weight
                composite += np.sin(2*np.pi*freq*t + delta_phase)
    
    # Normalize for visualization
    composite /= num_nodes
    return composite

# -----------------------------
# SIMULATION RUNNER
# -----------------------------
def run_phantom_network(duration=duration):
    t_step = 1.0 / sample_rate
    t = np.arange(0, duration, t_step)
    
    print("Simulating multi-band phyllotaxis HDGL network...")
    
    composite_signal = evolve_lattice(node_lattices, frequency_bands, t)
    
    # Visualization of first 5000 samples (~ms-scale)
    plt.figure(figsize=(12,4))
    plt.plot(t[:5000]*1e3, composite_signal[:5000])
    plt.title("Phyllotaxis HDGL Lattice Riding Multi-Band Environment")
    plt.xlabel("Time (ms)")
    plt.ylabel("Amplitude")
    plt.grid(True)
    plt.show()
    
# -----------------------------
# RUN SIMULATION IN THREAD
# -----------------------------
thread = threading.Thread(target=run_phantom_network)
thread.start()
