#!/usr/bin/env python3
"""
Skiss Black Hole Accuracy Control Dashboard - Terminal Version
Live metrics, ASCII visualization, real-time tuning.
Run on Raspberry Pi, Google Colab, or any terminal.
"""

import sys
import time
import threading
import math
import os
import termios
import tty

# ---------- Global simulation state ----------
spin = 0.68          # spin lattice alignment (0..1)
resonance = 0.52     # resonance match (0..1)
entanglement = 0.44
comet_coherence = 0.27
skiss_noise = False  # inject random skiss fluctuations

# Derived metrics
accuracy = 0.0
divergence = 0.0
pi_checksum = 0.0
e_checksum = 0.0
skiss_level = 0.0
traceability = 0.0
jet_angle = 0.0
crystal_consensus = 0.82

# Display control
running = True
last_update = 0
frame_count = 0
fps = 60

# Command handling
command = None
command_lock = threading.Lock()

# ---------- Helper functions ----------
def compute_metrics():
    global accuracy, divergence, pi_checksum, e_checksum, skiss_level, traceability, jet_angle, crystal_consensus
    # add skiss noise if enabled (random walk)
    s = spin
    r = resonance
    e = entanglement
    c = comet_coherence
    if skiss_noise:
        s += (threading.get_ident() % 100 / 1000.0 - 0.05) * 0.02
        r += (time.time() % 0.1 - 0.05) * 0.02
        e += (time.time() % 0.07 - 0.035) * 0.02
        c += (time.time() % 0.09 - 0.045) * 0.02
        s = max(0.0, min(1.0, s))
        r = max(0.0, min(1.0, r))
        e = max(0.0, min(1.0, e))
        c = max(0.0, min(1.0, c))

    # accuracy model
    resonance_match = 1.0 - abs(r - 0.618)
    spin_factor = s * (1 + resonance_match) / 2
    accuracy_base = (spin_factor * e) * (1 + c * 0.4)
    accuracy = min(0.98, max(0.02, accuracy_base * 0.9 + 0.05))
    # subtle oscillation
    accuracy = accuracy * (0.97 + 0.06 * math.sin(time.time() * 2.5))
    accuracy = min(0.995, max(0.01, accuracy))

    # Pi-checksum divergence
    pi_checksum = 0.55 + (1 - accuracy) * 0.45 - (resonance_match * 0.2)
    pi_checksum = min(0.98, max(0.12, pi_checksum))
    # e-checksum
    e_checksum = 0.618 + (1 - accuracy) * 0.4 - (entanglement * 0.2)
    e_checksum = min(0.92, max(0.2, e_checksum))

    # Divergence D (threshold 0.37)
    div_pi = abs(pi_checksum - 0.55)
    div_e = abs(e_checksum - 0.618)
    divergence = (div_pi * 0.7 + div_e * 0.3) * 1.2
    divergence = min(0.95, divergence)

    # Skiss erasure and traceability
    if divergence > 0.37:
        skiss_level = min(0.99, skiss_level + 0.005)
    else:
        skiss_level = max(0.05, skiss_level - 0.002)
    traceability = max(0.05, 1.0 - skiss_level * 1.2)

    # Jet angle (based on spin)
    jet_angle = (s * 360 + (resonance_match * 45)) % 360

    # Crystal consensus
    crystal_consensus = min(0.98, max(0.4, 0.65 + accuracy * 0.35 - divergence * 0.5))

def draw_ascii_black_hole():
    """Return a simple ASCII art of the black hole with jet direction."""
    lines = []
    angle_rad = math.radians(jet_angle)
    # jet direction indicators
    jet_char = "⤴" if 45 < jet_angle < 135 else "⤵" if 225 < jet_angle < 315 else "→" if jet_angle < 90 else "←"
    lines.append("                     .-""-.")
    lines.append("                   .'      '.")
    lines.append("                  /   O    O  \\")
    lines.append("                 :   '--'    :")
    lines.append("                 |    .-.    |")
    lines.append("                 :  (     )  :   jet direction: " + jet_char + f" {jet_angle:.0f}°")
    lines.append("                  \\  `---'  /")
    lines.append("                   '._____.'")
    lines.append("                     `---`")
    # add spin arrow
    spin_dir = "↻" if spin > 0.5 else "↺"
    lines.append(f"   Spin vector: {spin_dir}  |  Coherence: {accuracy*100:.1f}%")
    return "\n".join(lines)

def draw_slider(label, value, width=30):
    filled = int(value * width)
    bar = "█" * filled + "░" * (width - filled)
    return f"{label:12} [{bar}] {value:.3f}"

def draw_metrics():
    """Return formatted text block with all live metrics."""
    lines = []
    lines.append("\033[1;36m" + "═" * 70 + "\033[0m")
    lines.append("\033[1;33m⚫ SKISS BLACK HOLE · ACCURACY CONTROL DASHBOARD\033[0m")
    lines.append("\033[1;36m" + "═" * 70 + "\033[0m")
    lines.append("")
    lines.append(draw_ascii_black_hole())
    lines.append("")
    lines.append("\033[1;32m🎯 REAL-TIME ACCURACY\033[0m")
    lines.append(f"   Accuracy: {accuracy:.4f} bits/Planck area   " + "█" * int(accuracy*40))
    lines.append(f"   π-checksum: {pi_checksum:.4f}   |   e-checksum: {e_checksum:.4f}")
    lines.append(f"   Divergence D: {divergence:.4f}   \033[91m(threshold 0.37)\033[0m")
    if divergence > 0.37:
        lines.append("   \033[41m⚠️  CRITICAL DIVERGENCE → PATH ERASURE ACTIVE\033[0m")
    else:
        lines.append("   \033[92m✅ Below threshold – path traceable\033[0m")
    lines.append("")
    lines.append("\033[1;35m🌀 ATOM PATTERN CONTROLS\033[0m")
    lines.append(draw_slider("Spin Lattice", spin))
    lines.append(draw_slider("Resonance", resonance))
    lines.append(draw_slider("Entanglement", entanglement))
    lines.append(draw_slider("Comet Coherence", comet_coherence))
    lines.append("")
    lines.append("\033[1;34m📊 SYSTEM STATE\033[0m")
    lines.append(f"   Skiss Erasure Level: {skiss_level*100:.1f}%")
    lines.append(f"   Information Traceability: {traceability:.3f}")
    lines.append(f"   Crystal Consensus: {crystal_consensus*100:.1f}%")
    lines.append(f"   Jet Direction: {jet_angle:.0f}°")
    lines.append("")
    lines.append("\033[1;90mCommands:\033[0m")
    lines.append("  spin 0.7  |  res 0.5  |  ent 0.6  |  comet 0.3  |  reset  |  noise  |  quit")
    lines.append("\033[1;36m" + "═" * 70 + "\033[0m")
    return "\n".join(lines)

def update_display():
    """Clear screen and redraw everything."""
    os.system('clear')  # Works on Unix/Linux, Colab terminal, Pi
    print(draw_metrics())

def input_listener():
    """Thread that reads commands from stdin."""
    global spin, resonance, entanglement, comet_coherence, skiss_noise, running
    while running:
        try:
            cmd = sys.stdin.readline().strip().lower()
            if not cmd:
                continue
            parts = cmd.split()
            if parts[0] == "spin" and len(parts) == 2:
                val = float(parts[1])
                spin = max(0.0, min(1.0, val))
            elif parts[0] == "res" and len(parts) == 2:
                val = float(parts[1])
                resonance = max(0.0, min(1.0, val))
            elif parts[0] == "ent" and len(parts) == 2:
                val = float(parts[1])
                entanglement = max(0.0, min(1.0, val))
            elif parts[0] == "comet" and len(parts) == 2:
                val = float(parts[1])
                comet_coherence = max(0.0, min(1.0, val))
            elif parts[0] == "reset":
                spin = 0.82
                resonance = 0.68
                entanglement = 0.71
                comet_coherence = 0.33
                skiss_noise = False
            elif parts[0] == "noise":
                skiss_noise = not skiss_noise
                print(f"\n Noise injection {'ON' if skiss_noise else 'OFF'}\n")
            elif parts[0] == "quit" or parts[0] == "exit":
                running = False
                break
        except Exception:
            pass

def main():
    global running
    # Set stdin to non-blocking (Unix)
    try:
        old_settings = termios.tcgetattr(sys.stdin)
        tty.setcbreak(sys.stdin.fileno())
    except:
        # Fallback for environments where termios not available (e.g., Windows)
        pass

    # Start input thread
    thread = threading.Thread(target=input_listener, daemon=True)
    thread.start()

    # Main display loop
    last_time = time.time()
    frame = 0
    try:
        while running:
            compute_metrics()
            update_display()
            # Throttle to ~30 FPS for readability, but still responsive
            time.sleep(0.033)
            frame += 1
            if time.time() - last_time >= 1.0:
                # optional fps display hidden, keep clean
                last_time = time.time()
                frame = 0
    except KeyboardInterrupt:
        running = False
    finally:
        # Restore terminal settings
        try:
            termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
        except:
            pass
        print("\n\033[1;33mDashboard stopped. Horizon collapsed.\033[0m")

if __name__ == "__main__":
    main()