import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import time

class TrueLiveHDGL_VM:
    def __init__(self):
        self.D = np.array([1.,2.,3.,4.,5.,6.,7.,8.,1.], dtype=float)
        self.P = np.zeros(8)
        self.P[4:] = [6.8541019662, 11.09016994, 17.94427191, 29.03444654]
        self.void = 0.0
        self.omega = 1.0
        self.upper_phi_phi = 2.6180339887
        self.phi = 1.6180339887
        self.weights = np.ones(8)/8
        self.ip = 0
        self.program = [0,1,2,3,1,0,2,3,1,0]

    def step(self, blend_factor=0.05):
        if self.ip >= len(self.program):
            return False
        D_prev = self.D.copy()
        weighted_sum = np.sum(D_prev[:8] * self.weights)
        for i in range(len(self.D)):
            p_val = self.P[i] if i < len(self.P) else 0
            phi_val = self.phi ** i
            self.D[i] = D_prev[i] + blend_factor * (phi_val * D_prev[i] + self.upper_phi_phi * p_val + weighted_sum + self.omega)
        self.void += np.mean(self.D) * blend_factor
        self.omega += 0.01 * blend_factor
        self.ip += 1
        return True

    def run_live(self):
        fig, (ax1, ax2) = plt.subplots(2,1, figsize=(10,6))
        ax1.set_title("D Registers Evolution")
        ax1.set_xlabel("Step")
        ax1.set_ylabel("D Value")
        ax2.set_title("Void & Omega")
        ax2.set_xlabel("Step")
        ax2.set_ylabel("Value")

        D_lines = [ax1.plot([],[], label=f"D{i+1}")[0] for i in range(len(self.D))]
        void_line, = ax2.plot([], [], label="Void")
        omega_line, = ax2.plot([], [], label="Omega")
        ax1.legend()
        ax2.legend()

        history_D = []
        history_void = []
        history_omega = []

        def update(frame):
            # Step VM one instruction
            cont = self.step()
            history_D.append(self.D.copy())
            history_void.append(self.void)
            history_omega.append(self.omega)

            for i, line in enumerate(D_lines):
                line.set_data(range(len(history_D)), [h[i] for h in history_D])
            void_line.set_data(range(len(history_void)), history_void)
            omega_line.set_data(range(len(history_omega)), history_omega)

            ax1.relim()
            ax1.autoscale_view()
            ax2.relim()
            ax2.autoscale_view()

            return D_lines + [void_line, omega_line]

        anim = FuncAnimation(fig, update, frames=200, interval=100, blit=False)
        plt.show()

# --------------------------
# Example usage
# --------------------------
if __name__ == "__main__":
    vm = TrueLiveHDGL_VM()
    vm.run_live()
