import math
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D

# --- Minimal HDGL Machine ---
class HDGLMachine:
    def __init__(self):
        self.upper_field = {
            "phi": 1.6180339887,
            "phi_power_phi": 2.6180339887,
            "pi": 3.1415926535,
            "P3": 4.2360679775
        }
        self.analog_dims = {
            "dim_switch": 1.0,
            "P7": 29.0344465435
        }
        self.lower_field = {
            "inv_phi": 0.6180339887,
            "inv_P3": 0.2360679775
        }
        self.void = 0.0
        self.current_state = self.void
        self.dimension = self.analog_dims["dim_switch"]
        self.recursion_active = False
        self.seed = 0.0  # calculator input placeholder

    def toggle_recursion(self):
        self.recursion_active = not self.recursion_active

    def compute_harmonic_state(self, t):
        state = self.void
        phi = self.upper_field["phi"]
        phi_phi = self.upper_field["phi_power_phi"]
        pi = self.upper_field["pi"]

        for val in self.upper_field.values():
            state += val * math.sin(t * phi)
        for val in self.lower_field.values():
            state += val * math.cos(t * self.lower_field["inv_phi"])
        for val in self.analog_dims.values():
            state += val * math.sin(t * phi_phi)
        if self.dimension == 1.0:
            state *= math.sin(t * pi)
        else:
            state *= math.cos(t * pi)
        state += self.seed
        return state

    def step(self, t):
        state = self.compute_harmonic_state(t)
        if self.recursion_active:
            state *= self.analog_dims["P7"]/self.lower_field["inv_P3"]
        self.current_state = state
        return state

# --- 3D Analog Waveform Visualizer ---
class HDGL3DVisualizer:
    def __init__(self, machine, dt=0.05, window=200):
        self.machine = machine
        self.dt = dt
        self.t = 0.0
        self.window = window
        self.times, self.values, self.zvals = [], [], []

        self.fig = plt.figure(figsize=(10,6))
        self.ax = self.fig.add_subplot(111, projection='3d')
        self.ax.set_xlabel("Time")
        self.ax.set_ylabel("HDGL State")
        self.ax.set_zlabel("Recursion")
        self.line, = self.ax.plot([],[],[],lw=2)

    def update(self, frame):
        self.t += self.dt
        val = self.machine.step(self.t)
        self.times.append(self.t)
        self.values.append(val)
        self.zvals.append(1 if self.machine.recursion_active else 0)

        if len(self.times) > self.window:
            self.times.pop(0)
            self.values.pop(0)
            self.zvals.pop(0)

        self.ax.clear()
        self.ax.set_xlabel("Time")
        self.ax.set_ylabel("HDGL State")
        self.ax.set_zlabel("Recursion")
        self.ax.set_title("HDGL 3D Analog Waveform")
        self.ax.plot(self.times,self.values,self.zvals,color='b',lw=2)
        return self.line,

    def run(self):
        ani = animation.FuncAnimation(
            self.fig, self.update, blit=True, interval=self.dt*1000
        )
        plt.show()

# --- Run ---
if __name__ == "__main__":
    machine = HDGLMachine()
    vis = HDGL3DVisualizer(machine)
    print("Press 'r' in the console to toggle recursion.")
    vis.run()
