#!/usr/bin/env python3
"""
Force-Rendered 3D Chromatic Visualization
Uses explicit window management and forced rendering
"""

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
import sys

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

positions = deque(maxlen=400)
last_pos = 0
omega = 0
evol = 0

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

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

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

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

print("\n" + "="*60)
print("  🌈 FORCE-RENDERED 3D CHROMATIC VISUALIZATION")
print("="*60)

# Force interactive mode BEFORE creating figure
plt.ion()

# Create figure
fig = plt.figure(figsize=(11, 9))
ax = fig.add_subplot(111, projection='3d')
fig.patch.set_facecolor('#0a0a1a')
ax.set_facecolor('#050510')

# Configure axes
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
ax.set_xlabel('X (D1+D8)', color='cyan', fontsize=9)
ax.set_ylabel('Y (D3+D6)', color='cyan', fontsize=9)
ax.set_zlabel('Z (D4+D5)', color='cyan', fontsize=9)
ax.tick_params(colors='cyan', labelsize=7)

# Force window to appear and come to front
fig.canvas.manager.window.attributes('-topmost', 1)  # Bring to front
fig.canvas.manager.window.attributes('-topmost', 0)  # Allow moving
plt.show(block=False)
fig.canvas.draw()
fig.canvas.flush_events()
plt.pause(1.0)  # Give window time to fully appear

print("\n✅ Window should be visible and on top!")
print("   Starting live updates...\n")

frame = 0
azim = 0

try:
    while True:
        # Read new data
        read_log()

        if len(positions) >= 15:
            # Process
            arr = np.array(list(positions), dtype=np.float64)
            arr = np.log10(np.maximum(np.abs(arr), 1e-200))

            # Normalize
            for i in range(8):
                col = arr[:, i]
                vmin, vmax = col.min(), col.max()
                if vmax > vmin:
                    arr[:, i] = (col - vmin) / (vmax - vmin)

            # Musical projection
            x = arr[:, 0] * 0.6 + arr[:, 7] * 0.4
            y = arr[:, 2] * 0.5 + arr[:, 5] * 0.5
            z = arr[:, 4] * 0.5 + arr[:, 3] * 0.5

            # Clear and redraw
            ax.clear()

            # Reapply styling
            ax.set_facecolor('#050510')
            ax.set_xlim(0, 1)
            ax.set_ylim(0, 1)
            ax.set_zlim(0, 1)
            ax.set_xlabel('X (D1+D8)', color='cyan', fontsize=9)
            ax.set_ylabel('Y (D3+D6)', color='cyan', fontsize=9)
            ax.set_zlabel('Z (D4+D5)', color='cyan', fontsize=9)
            ax.tick_params(colors='cyan', labelsize=7)
            ax.grid(True, alpha=0.1, color='cyan')

            # Plot with gradient
            colors = plt.cm.plasma(np.linspace(0, 1, len(x)))
            ax.scatter(x, y, z, c=colors, s=4, alpha=0.8, depthshade=True)

            # Title
            omega_icon = "🔴SAT" if omega >= 999 else "🟢"
            ax.set_title(f'{omega_icon} 8D Chromatic | Ω={omega:.0f} | E={evol//1000000}M | {len(positions)}pts',
                        color='cyan', fontsize=11, pad=8)

            # Rotate
            azim = (azim + 2) % 360
            ax.view_init(elev=22, azim=azim)

            # FORCE rendering - multiple methods
            fig.canvas.draw_idle()
            fig.canvas.start_event_loop(0.001)  # Process events
            fig.canvas.flush_events()
            plt.pause(0.001)

            # Progress
            if frame % 15 == 0:
                print(f"▶ Frame {frame}: {len(positions)} pts | Ω={omega:.0f} | Azim={azim}°")
                sys.stdout.flush()
        else:
            # Waiting
            if frame % 20 == 0:
                print(f"⏳ Collecting data... {len(positions)}/15 pts")
                sys.stdout.flush()

        frame += 1
        time.sleep(0.18)  # ~5.5 FPS

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