import numpy as np
import matplotlib.pyplot as plt

# -------------------------------
# Simulation Parameters
# -------------------------------
NUM_NODES = 4       # Number of lattice nodes
NUM_CORES = 2       # Analog cores per node
NUM_STRANDS = 4
SLOTS_PER_STRAND = 4
PHI = 1.6180339887
OMEGA_BASE = 1 / (PHI**np.arange(1, NUM_STRANDS+1))**7

FS = 1000           # Sampling rate (Hz)
T = 1.0             # Simulation duration (s)
t = np.arange(0, T, 1/FS)

# Carrier: Existing environmental signal (example: 5 Hz sine wave)
carrier_freq = 5
carrier = np.sin(2 * np.pi * carrier_freq * t)

# -------------------------------
# Initialize HDGL Lattice
# -------------------------------
def init_lattice():
    cores = []
    for _ in range(NUM_CORES):
        lattice = np.random.uniform(0.5, 1.0, (NUM_STRANDS, SLOTS_PER_STRAND))
        phases = np.random.uniform(0, 2*np.pi, (NUM_STRANDS, SLOTS_PER_STRAND))
        cores.append({'lattice': lattice, 'phases': phases})
    return cores

nodes = [init_lattice() for _ in range(NUM_NODES)]

# -------------------------------
# Encode HDGL Data onto Lattice
# -------------------------------
def lattice_modulation(node_id, cores, carrier_signal):
    modulated_signal = np.zeros_like(carrier_signal)
    for core in cores:
        lattice = core['lattice']
        phases = core['phases']
        for s in range(NUM_STRANDS):
            for slot in range(SLOTS_PER_STRAND):
                # Phase-lock lattice slot to carrier with slight analog offset
                phase_offset = 0.1 * lattice[s, slot]  # example encoding
                modulated_signal += np.sin(2*np.pi*carrier_freq*t + phases[s, slot] + phase_offset)
    # Normalize to preserve original carrier amplitude
    modulated_signal = modulated_signal / (NUM_CORES * NUM_STRANDS * SLOTS_PER_STRAND)
    # Overlay onto carrier without changing main amplitude
    return carrier_signal + 0.1 * modulated_signal  # 0.1 = small sideband amplitude

# -------------------------------
# Apply Lattice Across All Nodes
# -------------------------------
composite_signal = carrier.copy()
for node_id, cores in enumerate(nodes):
    composite_signal += lattice_modulation(node_id, cores, carrier)

# Normalize final signal
composite_signal /= (1 + NUM_NODES * 0.1)

# -------------------------------
# Plot Results
# -------------------------------
plt.figure(figsize=(12,4))
plt.plot(t, carrier, label='Original Carrier', alpha=0.7)
plt.plot(t, composite_signal, label='Carrier + HDGL Sideband', alpha=0.9)
plt.xlabel('Time [s]')
plt.ylabel('Amplitude')
plt.title('HDGL Lattice Riding Existing Carrier')
plt.legend()
plt.show()
