import math
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np

# --- 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.use_hdgl_base = True
        self.seed = 0.0  # calculator input effect

    def toggle_recursion(self):
        self.recursion_active = not self.recursion_active
        print(f"Recursion mode: {'ON' if self.recursion_active else 'OFF'}")

    def toggle_dimension(self):
        self.dimension = 1.0 if self.dimension != 1.0 else 0.0
        print(f"Dimensionality: {'2D' if self.dimension==1.0 else '1D'}")

    def toggle_base(self):
        self.use_hdgl_base = not self.use_hdgl_base
        print(f"Base: {'HDGL' if self.use_hdgl_base else 'Base-10'}")

    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"]
        P3 = self.upper_field["P3"]

        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)

        state *= math.sin(t*pi) if self.dimension==1.0 else math.cos(t*pi)
        state += self.seed
        return state

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

# --- 3D Waveform + Calculator ---
class HDGLCalculator3D:
    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 = [], [], []

        # --- Tkinter Window ---
        self.root = tk.Tk()
        self.root.title("HDGL 3D Calculator")

        # Display
        self.expression = ""
        self.display = tk.Entry(self.root, width=30, font=("Helvetica",16))
        self.display.grid(row=0,column=0,columnspan=6)

        # Buttons
        buttons = [
            '7','8','9','/','φ','φ^φ',
            '4','5','6','*','π','P3',
            '1','2','3','-','F_n','2^n',
            '0','.','=','+','Rec','Base'
        ]
        row,col=1,0
        for b in buttons:
            tk.Button(self.root,text=b,width=6,height=2,font=("Helvetica",12),
                      command=lambda x=b:self.on_button(x)).grid(row=row,column=col)
            col+=1
            if col>5: row+=1; col=0

        # --- Matplotlib Figure ---
        self.fig = plt.figure(figsize=(8,5))
        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/Base")
        self.ax.set_title("HDGL 3D Waveform")
        self.line, = self.ax.plot([],[],[], lw=2, c='b')

        # Embed figure in Tkinter
        self.canvas = FigureCanvasTkAgg(self.fig, master=self.root)
        self.canvas.get_tk_widget().grid(row=row,column=0,columnspan=6)

        # Animation
        self.ani = animation.FuncAnimation(self.fig, self.update, interval=self.dt*1000, blit=False)

    def on_button(self, char):
        if char=="=":
            try:
                expr = self.expression
                if self.machine.use_hdgl_base:
                    expr = expr.replace("φ^φ", str(self.machine.upper_field["phi_power_phi"]))
                    expr = expr.replace("φ", str(self.machine.upper_field["phi"]))
                    expr = expr.replace("π", str(self.machine.upper_field["pi"]))
                    expr = expr.replace("P3", str(self.machine.upper_field["P3"]))
                    expr = expr.replace("F_n","5")      # placeholder
                    expr = expr.replace("2^n","2**3")  # placeholder
                self.machine.seed = eval(expr)
            except Exception as e:
                print("Error:",e)
            self.expression=""
            self.display.delete(0,tk.END)
        elif char=="Rec":
            self.machine.toggle_recursion()
        elif char=="Base":
            self.machine.toggle_base()
        else:
            self.expression+=char
            self.display.delete(0,tk.END)
            self.display.insert(0,self.expression)

    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/Base")
        self.ax.set_title("HDGL 3D Waveform")
        self.ax.plot(self.times,self.values,self.zvals,color='b',lw=2)

    def run(self):
        print("Controls: Rec = toggle recursion, Base = toggle Base-10/HDGL")
        self.root.mainloop()

# --- Run ---
if __name__=="__main__":
    machine = HDGLMachine()
    app = HDGLCalculator3D(machine)
    app.run()
