#!/usr/bin/env python3
"""
Non-Blocking 3D Chromatic Visualization
8 dimensions projected into 3D space
"""

import re
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from collections import deque
import time

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

class Monitor:
    def __init__(self):
        self.positions = deque(maxlen=800)
        self.last_pos = 0
        self.omega = 0
        self.evol = 0

    def update(self):
        try:
            with open(LOG_FILE, 'r', encoding='utf-8', errors='ignore') as f:
                f.seek(self.last_pos)
                lines = f.readlines()
                self.last_pos = f.tell()

                dims = {}
                for line in lines:
                    if 'Ω:' in line:
                        try:
                            self.omega = float(line.split('Ω:')[1].split()[0])
                            self.evol = int(line.split('Evolution:')[1].split('│')[0].strip())
                        except:
                            pass

                    # Parse all 8 dimensions
                    for i in range(1, 9):
                        if f'  D{i}:' in line:
                            try:
                                val = float(line.split(':')[1].split('[')[0].strip())
                                dims[i-1] = val
                            except:
                                pass

                    if len(dims) == 8:
                        self.positions.append(tuple(dims[i] for i in range(8)))
                        dims = {}
        except:
            pass

def main():
    print("\n" + "="*70)
    print("  🌈 LIVE 3D CHROMATIC VISUALIZATION")
    print("  8 Dimensions → 3D Musical Harmony Projection")
    print("="*70 + "\n")

    monitor = Monitor()

    # Interactive mode
    plt.ion()

    # Create 3D figure
    fig = plt.figure(figsize=(14, 10))
    ax = fig.add_subplot(111, projection='3d')
    fig.patch.set_facecolor('#050510')

    fig.suptitle('8D Chromatic Attractor - Live View',
                 fontsize=14, fontweight='bold', color='cyan')

    ax.set_xlabel('Fundamental + Octave (D1+D8)', fontsize=10, color='white')
    ax.set_ylabel('Harmony (D3+D6)', fontsize=10, color='white')
    ax.set_zlabel('Resonance (D4+D5)', fontsize=10, color='white')
    ax.set_xlim(0, 1)
    ax.set_ylim(0, 1)
    ax.set_zlim(0, 1)
    ax.set_facecolor('#0a0a1a')
    ax.tick_params(colors='cyan', labelsize=8)
    ax.grid(True, alpha=0.15, color='cyan')

    # Create empty scatter
    scatter = ax.scatter([], [], [], s=4, alpha=0.7, c=[], cmap='plasma', vmin=0, vmax=1)

    # Show immediately
    plt.show(block=False)
    plt.pause(0.1)

    print("✅ 3D Window visible!")
    print("   Auto-rotating view")
    print("   Press Ctrl+C to stop\n")

    frame = 0
    try:
        while True:
            monitor.update()

            if len(monitor.positions) >= 10:
                # Convert to array
                arr = np.array(list(monitor.positions), dtype=np.float32)

                # Log normalize
                arr = np.log10(np.abs(arr) + 1e-50)

                # Normalize each dimension
                for i in range(8):
                    col = arr[:, i]
                    arr[:, i] = (col - col.min()) / (col.max() - col.min() + 1e-10)

                # Musical projection
                x = arr[:, 0] * 0.6 + arr[:, 7] * 0.4  # Fundamental + Octave
                y = arr[:, 2] * 0.5 + arr[:, 5] * 0.5  # Thirds + Sixths
                z = arr[:, 4] * 0.5 + arr[:, 3] * 0.5  # Fifths + Fourths

                # Color by time
                colors = np.linspace(0, 1, len(x))

                # Update scatter
                scatter._offsets3d = (x, y, z)
                scatter.set_array(colors)

                # Rotate view
                ax.view_init(elev=25, azim=frame * 0.5)

                # Update title
                omega_icon = "🔴" if monitor.omega >= 999 else "🟢"
                fig.suptitle(f'{omega_icon} 8D Chromatic Attractor | Ω={monitor.omega:.0f} | E={monitor.evol//1000000}M | Pts={len(monitor.positions)}',
                            fontsize=13, fontweight='bold', color='cyan')

                # Redraw
                fig.canvas.draw_idle()
                fig.canvas.flush_events()

            time.sleep(0.2)
            frame += 1

            if frame % 15 == 0:
                print(f"Frame {frame}: {len(monitor.positions)} points, Ω={monitor.omega:.0f}, Azim={frame*0.5 % 360:.0f}°")

    except KeyboardInterrupt:
        print("\n\n✅ Visualization stopped.")
        plt.close()

if __name__ == "__main__":
    main()
