import tkinter as tk
from tkinter import ttk
import numpy as np
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# Wi-Fi scanning
import pywifi
from pywifi import PyWiFi, const

# --------------------------
# Parameters
# --------------------------
N = 50            # Number of Wi-Fi points to track (top strongest networks)
dt = 0.5          # Animation interval (s)
k_env = 0.1       # Soft-envelope scaling

# --------------------------
# Tkinter setup
# --------------------------
root = tk.Tk()
root.title("HDGL Wi-Fi EMF Lattice Visualizer")

# --------------------------
# Matplotlib figure
# --------------------------
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(111, projection='3d')
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

# --------------------------
# Slider frame
# --------------------------
slider_frame = tk.Frame(root)
slider_frame.pack(side=tk.BOTTOM, fill=tk.X)

def make_slider(label, minv, maxv, default, row):
    tk.Label(slider_frame, text=label).grid(row=row, column=0, sticky='w')
    var = tk.DoubleVar(value=default)
    slider = tk.Scale(slider_frame, from_=minv, to=maxv, resolution=0.01,
                      orient=tk.HORIZONTAL, variable=var)
    slider.grid(row=row, column=1, sticky='we')
    return var

morph_var = make_slider("Morph (Polar→Cartesian)", 0, 1, 0, 0)
ampl_var  = make_slider("Amplitude Scale", 0, 2, 1, 1)

# --------------------------
# Lattice setup (phyllotaxis)
# --------------------------
phi = (1 + np.sqrt(5)) / 2  # Golden ratio
theta = 2 * np.pi / phi
radii = np.sqrt(np.arange(N))
angles = np.arange(N) * theta
zs = np.linspace(-1, 1, N)

def get_lattice(t=0, emf_mod=0):
    """Return 3D coordinates of lattice, modulated by EMF"""
    r = radii + emf_mod
    x_polar = r * np.cos(angles)
    y_polar = r * np.sin(angles)
    z_polar = zs * ampl_var.get()

    # Morph between polar and cartesian
    morph = morph_var.get()
    x_cart = x_polar * (1-morph) + np.linspace(-1,1,N) * morph
    y_cart = y_polar * (1-morph) + np.linspace(-1,1,N) * morph
    z_cart = z_polar * (1-morph) + np.linspace(-1,1,N) * morph

    return x_cart, y_cart, z_cart

# --------------------------
# Wi-Fi EMF feed
# --------------------------
wifi = PyWiFi()
iface = wifi.interfaces()[0]

wifi_signal = np.zeros(N)

def scan_wifi():
    """Scan Wi-Fi networks and normalize signal with soft-envelope"""
    global wifi_signal
    iface.scan()
    results = iface.scan_results()
    # Sort by strongest signal, take top N
    sorted_results = sorted(results, key=lambda x: x.signal, reverse=True)[:N]
    signals = [r.signal for r in sorted_results]
    if len(signals) < N:
        # pad with zeros if fewer networks
        signals += [0]*(N - len(signals))
    # Apply soft-envelope filter
    wifi_signal = np.tanh(k_env * np.array(signals))

# --------------------------
# Animation update
# --------------------------
scat = ax.scatter([], [], [], c=[], cmap='viridis', s=50)
wifi_line, = ax.plot([], [], [], c='r', lw=2, label='Wi-Fi EMF')

def update(frame):
    scan_wifi()
    emf_mod = wifi_signal  # directly use normalized EMF

    # Lattice
    x, y, z = get_lattice(t=frame*dt, emf_mod=emf_mod)
    scat._offsets3d = (x, y, z)
    scat.set_array(z)

    # Wi-Fi overlay (red line)
    wifi_line.set_data(np.arange(N), np.zeros(N))
    wifi_line.set_3d_properties(emf_mod)

    ax.set_xlim(-5,5)
    ax.set_ylim(-5,5)
    ax.set_zlim(-2,2)
    return scat, wifi_line

ani = FuncAnimation(fig, update, interval=dt*1000, blit=False)

# --------------------------
# Start Tkinter loop
# --------------------------
root.mainloop()
