import os
import sys
import zipfile
import urllib.request
from pathlib import Path
import numpy as np
from rtlsdr import RtlSdr
from scipy.io import wavfile

# -----------------------------
# Config
# -----------------------------
DLL_DIR = Path.home() / "Documents" / "Turing-Complete" / "hdgl_sdr_dlls"
RTL_SDR_URL = "https://osmocom.org/attachments/download/1557/Release-RTL-SDR.zip"

CARRIER_FREQ = 100e6  # Carrier for modulation
SAMPLE_RATE = 2.048e6
GAIN = 'auto'
TICKS = 64
STRANDS = 8
SLOTS_PER_STRAND = 4
ENV_SIGNAL_PATH = None  # Path to WAV file or None

# -----------------------------
# Ensure DLLs
# -----------------------------
DLL_DIR.mkdir(parents=True, exist_ok=True)
zip_path = DLL_DIR / "rtl_sdr.zip"
if not zip_path.exists():
    print("[+] Downloading RTL-SDR binaries...")
    urllib.request.urlretrieve(RTL_SDR_URL, zip_path)

with zipfile.ZipFile(zip_path, 'r') as zip_ref:
    zip_ref.extractall(DLL_DIR)

for dll_name in ["librtlsdr.dll", "libusb-1.0.dll"]:
    dll_path = DLL_DIR / "bin" / dll_name
    if dll_path.exists():
        dest = DLL_DIR / dll_name
        dest.write_bytes(dll_path.read_bytes())

os.environ["PATH"] = f"{DLL_DIR};{os.environ['PATH']}"

# -----------------------------
# Initialize SDR
# -----------------------------
try:
    sdr = RtlSdr()
    sdr.sample_rate = SAMPLE_RATE
    sdr.center_freq = CARRIER_FREQ
    sdr.gain = GAIN
    print(f"[+] SDR detected: Vendor={sdr.vendor}, Product={sdr.product}")
except Exception as e:
    print("[!] SDR init failed:", e)
    sys.exit(1)

# -----------------------------
# Initialize HDGL lattice
# -----------------------------
lattice = np.zeros((STRANDS, SLOTS_PER_STRAND))
binary_lattice = np.zeros_like(lattice, dtype=int)

# Recursive evolution function
def evolve_lattice(lattice, tick):
    for s in range(STRANDS):
        for slot in range(SLOTS_PER_STRAND):
            # Multi-analog recursive growth + noise
            delta = 0.02 * (1 + np.sin(2*np.pi*(slot+1)/SLOTS_PER_STRAND))
            lattice[s, slot] += delta + np.random.normal(0,0.01)
    # Threshold for binary
    binary = (lattice > 1.0).astype(int)
    return lattice, binary

# -----------------------------
# Environmental/foreign signal
# -----------------------------
if ENV_SIGNAL_PATH and Path(ENV_SIGNAL_PATH).exists():
    fs, env_signal = wavfile.read(ENV_SIGNAL_PATH)
    env_signal = env_signal.astype(np.float32)
    env_signal /= np.max(np.abs(env_signal))
    print("[+] Loaded environmental signal")
else:
    # Generate placeholder ambient carrier
    t = np.arange(0, 1024) / SAMPLE_RATE
    env_signal = np.sin(2*np.pi*1e3*t)

# -----------------------------
# Convert lattice to composite signal
# -----------------------------
def lattice_to_signal(lattice, env):
    t = np.arange(len(env)) / SAMPLE_RATE
    composite = np.copy(env)
    for s in range(STRANDS):
        weight = np.mean(lattice[s])
        composite += weight * np.sin(2*np.pi*1e3*(s+1)*t)
    composite /= np.max(np.abs(composite))
    return composite

# -----------------------------
# Main Tick Loop
# -----------------------------
for tick in range(TICKS):
    lattice, binary_lattice = evolve_lattice(lattice, tick)
    print(f"=== Tick {tick+1} ===")
    for s in range(STRANDS):
        print(f"Strand {chr(65+s)}: Analog {np.round(lattice[s],3)} | Binary {binary_lattice[s].tolist()}")
    signal = lattice_to_signal(lattice, env_signal)
    iq_signal = signal.astype(np.complex64)  # Ready for TX SDR
    # sdr.write_samples(iq_signal) # Only if TX-capable SDR
    print(f"Aggregated Lattice Hex: 0x{int(binary_lattice.flatten().dot(1 << np.arange(STRANDS*SLOTS_PER_STRAND))):08x}")

sdr.close()
print("[+] HDGL multi-analog lattice session complete")
