#!/usr/bin/env python3
"""
Simplified Real-Time Dimensional Visualization
Monitors peer1.log and displays dimensional status
"""

import re
import time
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from collections import deque

LOG_FILE = "../logs/peer1.log"
HISTORY_SIZE = 200

class SimpleMonitor:
    def __init__(self):
        self.evolution = deque(maxlen=HISTORY_SIZE)
        self.omega = deque(maxlen=HISTORY_SIZE)
        self.amplitudes = [deque(maxlen=HISTORY_SIZE) for _ in range(8)]
        self.dn_values = [deque(maxlen=HISTORY_SIZE) for _ in range(8)]
        self.last_position = 0

    def update(self):
        """Read new log data"""
        try:
            with open(LOG_FILE, 'r', encoding='utf-8', errors='ignore') as f:
                f.seek(self.last_position)
                lines = f.readlines()
                self.last_position = f.tell()

                current_evolution = None
                current_omega = None
                dims = {}

                for line in lines:
                    # Evolution line
                    match = re.search(r'Evolution: (\d+).*Ω: ([\d.]+)', line)
                    if match:
                        current_evolution = int(match.group(1))
                        current_omega = float(match.group(2))

                    # Dimension line
                    match = re.search(r'D(\d): ([\d.e+]+) \[Dₙ:([\d.]+)\]', line)
                    if match:
                        dim_num = int(match.group(1)) - 1
                        amplitude = float(match.group(2))
                        dn_value = float(match.group(3))
                        dims[dim_num] = (amplitude, dn_value)

                    # If we have complete data for this snapshot
                    if current_evolution and current_omega and len(dims) == 8:
                        self.evolution.append(current_evolution)
                        self.omega.append(current_omega)
                        for i in range(8):
                            if i in dims:
                                self.amplitudes[i].append(np.log10(max(dims[i][0], 1e-300)))
                                self.dn_values[i].append(dims[i][1])
                        dims = {}
                        current_evolution = None
                        current_omega = None
        except Exception as e:
            print(f"Error reading log: {e}")

def animate(frame, monitor, ax_amp, ax_dn, ax_omega, lines_amp, lines_dn, line_omega):
    """Update plots"""
    monitor.update()

    if len(monitor.evolution) < 2:
        return

    evols = np.array(monitor.evolution)

    # Update amplitude plots
    for i in range(8):
        if len(monitor.amplitudes[i]) > 0:
            lines_amp[i].set_data(evols, np.array(monitor.amplitudes[i]))

    ax_amp.set_xlim(evols[0], evols[-1])
    y_vals = [val for amp_list in monitor.amplitudes for val in amp_list if val is not None]
    if y_vals:
        ax_amp.set_ylim(min(y_vals) - 10, max(y_vals) + 10)

    # Update Dₙ plots
    for i in range(8):
        if len(monitor.dn_values[i]) > 0:
            lines_dn[i].set_data(evols, np.array(monitor.dn_values[i]))

    ax_dn.set_xlim(evols[0], evols[-1])
    y_vals = [val for dn_list in monitor.dn_values for val in dn_list if val is not None]
    if y_vals:
        ax_dn.set_ylim(0, max(y_vals) * 1.1)

    # Update Ω plot
    if len(monitor.omega) > 0:
        line_omega.set_data(evols, np.array(monitor.omega))
        ax_omega.set_xlim(evols[0], evols[-1])
        ax_omega.set_ylim(0, max(monitor.omega) * 1.1)

    # Update Ω saturation indicator
    current_omega = monitor.omega[-1] if monitor.omega else 0
    ax_omega.set_title(f'Ω Evolution (Current: {current_omega:.1f} / 1000 cap)',
                       color='red' if current_omega >= 999 else 'black')

    return lines_amp + lines_dn + [line_omega]

def main():
    print("🌌 Starting Real-Time Dimensional Geometry Visualization...")
    print(f"📊 Monitoring: {LOG_FILE}")
    print("🎯 Press Ctrl+C to stop\n")

    monitor = SimpleMonitor()

    # Create figure with 3 subplots
    fig, (ax_amp, ax_dn, ax_omega) = plt.subplots(3, 1, figsize=(12, 10))
    fig.suptitle('🌀 Analog Codec V4.3 - Live Dimensional Geometry', fontsize=14, fontweight='bold')

    colors = plt.cm.rainbow(np.linspace(0, 1, 8))

    # Amplitude plot
    ax_amp.set_xlabel('Evolution')
    ax_amp.set_ylabel('log₁₀(Amplitude)')
    ax_amp.set_title('Dimensional Amplitudes (log scale)')
    ax_amp.grid(True, alpha=0.3)
    lines_amp = [ax_amp.plot([], [], label=f'D{i+1}', color=colors[i], linewidth=1.5)[0]
                 for i in range(8)]
    ax_amp.legend(loc='upper right', ncol=4, fontsize=8)

    # Dₙ plot
    ax_dn.set_xlabel('Evolution')
    ax_dn.set_ylabel('Dₙ Value')
    ax_dn.set_title('Dimensional Separation (Dₙ) - Decoupling Threshold: ΔDₙ > 500')
    ax_dn.grid(True, alpha=0.3)
    ax_dn.axhline(y=500, color='red', linestyle='--', alpha=0.5, label='Coupling threshold')
    lines_dn = [ax_dn.plot([], [], label=f'D{i+1}', color=colors[i], linewidth=1.5)[0]
                for i in range(8)]
    ax_dn.legend(loc='upper right', ncol=4, fontsize=8)

    # Ω plot
    ax_omega.set_xlabel('Evolution')
    ax_omega.set_ylabel('Ω')
    ax_omega.set_title('Ω Evolution (Saturation Cap: 1000)')
    ax_omega.grid(True, alpha=0.3)
    ax_omega.axhline(y=1000, color='red', linestyle='--', linewidth=2, label='Saturation cap (V4.3)')
    line_omega = ax_omega.plot([], [], color='blue', linewidth=2)[0]
    ax_omega.legend(loc='upper left')

    plt.tight_layout()

    # Animate
    ani = FuncAnimation(fig, animate, fargs=(monitor, ax_amp, ax_dn, ax_omega, lines_amp, lines_dn, line_omega),
                       interval=1000, blit=False, cache_frame_data=False)

    try:
        plt.show()
    except KeyboardInterrupt:
        print("\n\n✅ Visualization stopped by user.")

if __name__ == "__main__":
    main()
