#!/usr/bin/env python3
"""
8-Dimensional Chromatic Attractor Visualization
Musical/Color concept: 8 dimensions = 8 notes/colors in harmony
"""

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

LOG_FILE = "../logs/peer1.log"
TRAIL_LENGTH = 1500  # Reduced for performance

class ChromaticMonitor:
    def __init__(self):
        self.positions = deque(maxlen=TRAIL_LENGTH)
        self.last_position = 0
        self.current_omega = 0
        self.current_evolution = 0
        self.skip_counter = 0  # For performance

    def update(self):
        """Read all 8 dimensional positions"""
        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:
                    match = re.search(r'Evolution: (\d+).*Ω: ([\d.]+)', line)
                    if match:
                        current_evolution = int(match.group(1))
                        current_omega = float(match.group(2))

                    # Parse all 8 dimensions
                    for i in range(1, 9):
                        match = re.search(rf'D{i}: ([\d.e+]+)', line)
                        if match:
                            dims[i-1] = float(match.group(1))

                    # Complete snapshot - sample every 5th for performance
                    if len(dims) == 8:
                        self.skip_counter += 1
                        if self.skip_counter % 5 == 0:
                            self.positions.append(tuple(dims[i] for i in range(8)))
                            self.current_evolution = current_evolution
                            self.current_omega = current_omega
                        dims = {}
        except Exception as e:
            print(f"Error: {e}")

def normalize_chromatic(data):
    """Normalize with log scaling for huge dynamic range"""
    if len(data) < 2:
        return data
    data = np.log10(np.abs(data) + 1e-100)
    min_val, max_val = data.min(), data.max()
    if max_val > min_val:
        return (data - min_val) / (max_val - min_val)
    return data

def get_chromatic_color(dim_index):
    """
    Map 8 dimensions to musical/color spectrum
    Like an octave: C D E F G A B C
    Or rainbow: Red Orange Yellow Green Cyan Blue Indigo Violet
    """
    colors = [
        '#FF0000',  # D1: Red (Root/Fundamental - C)
        '#FF8800',  # D2: Orange (Major 2nd - D)
        '#FFFF00',  # D3: Yellow (Major 3rd - E)
        '#00FF00',  # D4: Green (Perfect 4th - F)
        '#00FFFF',  # D5: Cyan (Perfect 5th - G)
        '#0088FF',  # D6: Blue (Major 6th - A)
        '#8800FF',  # D7: Indigo (Major 7th - B)
        '#FF00FF',  # D8: Violet (Octave - C')
    ]
    return colors[dim_index]

def animate(frame, monitor, ax, scatters, lines, text_info):
    """Update chromatic 3D visualization"""
    monitor.update()

    if len(monitor.positions) < 2:
        return scatters + lines + [text_info]

    arr = np.array(monitor.positions)
    n_points = len(arr)

    # Normalize all 8 dimensions
    for i in range(8):
        arr[:, i] = normalize_chromatic(arr[:, i])

    # Project 8D -> 3D using musical harmonics
    # X: Fundamental (D1) + Octave (D8) - the bass/treble
    # Y: Thirds (D3) + Sixths (D6) - the harmony
    # Z: Fifths (D5) + Fourths (D4) - the resonance
    x = arr[:, 0] * 0.6 + arr[:, 7] * 0.4  # Root + 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 dimensional dominance (which dimension has highest amplitude)
    dim_dominance = np.argmax(arr, axis=1)
    colors = [get_chromatic_color(d) for d in dim_dominance]

    # Update main scatter (colored by dominant dimension)
    scatters[0]._offsets3d = (x, y, z)
    scatters[0].set_color(colors)

    # Draw 8 individual dimensional traces (thin lines)
    projections = [
        (0, 1, 2),  # D1-D2-D3 (fundamental triad)
        (3, 4, 5),  # D4-D5-D6 (harmonic triad)
        (6, 7, 0),  # D7-D8-D1 (octave bridge)
    ]

    for idx, (i, j, k) in enumerate(projections):
        xi = arr[:, i]
        yi = arr[:, j]
        zi = arr[:, k]
        lines[idx].set_data(xi, yi)
        lines[idx].set_3d_properties(zi)

    # Update info
    omega_status = "SATURATED" if monitor.current_omega >= 999 else "GROWING"
    dim_names = ['C', 'D', 'E', 'F', 'G', 'A', 'B', "C'"]
    info_text = (f"Evolution: {monitor.current_evolution:,}\n"
                f"Omega: {monitor.current_omega:.1f} {omega_status}\n"
                f"Points: {n_points}\n"
                f"8D Musical Harmony")
    text_info.set_text(info_text)

    # Rotate view
    ax.view_init(elev=20 + 10*np.sin(frame/20), azim=frame % 360)

    return scatters + lines + [text_info]

def main():
    print("=" * 70)
    print("  8-DIMENSIONAL CHROMATIC ATTRACTOR VISUALIZATION")
    print("  Musical Mapping: 8 Dimensions = 8 Notes (Octave)")
    print("=" * 70)
    print("\n  Color/Note Mapping:")
    print("    D1: RED      - C  (Fundamental/Root)")
    print("    D2: ORANGE   - D  (Major 2nd)")
    print("    D3: YELLOW   - E  (Major 3rd)")
    print("    D4: GREEN    - F  (Perfect 4th)")
    print("    D5: CYAN     - G  (Perfect 5th)")
    print("    D6: BLUE     - A  (Major 6th)")
    print("    D7: INDIGO   - B  (Major 7th)")
    print("    D8: VIOLET   - C' (Octave)")
    print(f"\n  Monitoring: {LOG_FILE}")
    print("  Press Ctrl+C to stop\n")

    monitor = ChromaticMonitor()

    # Create 3D plot
    fig = plt.figure(figsize=(16, 12))
    ax = fig.add_subplot(111, projection='3d')

    fig.suptitle('8D Chromatic Strange Attractor | Musical/Color Harmony Visualization',
                 fontsize=14, fontweight='bold', color='white')

    ax.set_xlabel('Fundamental + Octave (D1+D8)', fontsize=11, color='white')
    ax.set_ylabel('Harmony (D3+D6)', fontsize=11, color='white')
    ax.set_zlabel('Resonance (D4+D5)', fontsize=11, color='white')
    ax.set_xlim(0, 1)
    ax.set_ylim(0, 1)
    ax.set_zlim(0, 1)

    # Main scatter (colored by dominant dimension)
    scatter_main = ax.scatter([], [], [], s=8, alpha=0.7, edgecolors='white', linewidths=0.2)

    # Three harmonic traces
    line1, = ax.plot([], [], [], color='red', alpha=0.2, linewidth=0.8, label='Fundamental Triad (D1-D2-D3)')
    line2, = ax.plot([], [], [], color='cyan', alpha=0.2, linewidth=0.8, label='Harmonic Triad (D4-D5-D6)')
    line3, = ax.plot([], [], [], color='magenta', alpha=0.2, linewidth=0.8, label='Octave Bridge (D7-D8-D1)')

    # Info text
    text_info = ax.text2D(0.02, 0.98, "", transform=ax.transAxes,
                         fontsize=10, verticalalignment='top', color='white',
                         bbox=dict(boxstyle='round', facecolor='black', alpha=0.7))

    ax.legend(loc='lower right', fontsize=9, facecolor='black', edgecolor='white', labelcolor='white')
    ax.grid(True, alpha=0.15, color='gray')

    # Dark cosmic background
    ax.set_facecolor('#0a0a1a')
    fig.patch.set_facecolor('#050510')
    ax.tick_params(colors='white')
    ax.xaxis.pane.fill = False
    ax.yaxis.pane.fill = False
    ax.zaxis.pane.fill = False

    # Animate
    ani = FuncAnimation(fig, animate,
                       fargs=(monitor, ax, [scatter_main], [line1, line2, line3], text_info),
                       interval=150,  # Slower for performance
                       blit=False,
                       cache_frame_data=False)

    try:
        plt.show()
    except KeyboardInterrupt:
        print("\n\nVisualization stopped.")

if __name__ == "__main__":
    main()
