#!/usr/bin/env python3
"""
br-palette
Interactive TUI palette viewer with arrow key navigation and live semantic preview.
Enhanced with BR shape grammar integration.
"""

import sys
import tty
import termios

RESET = "\x1b[0m"
CLEAR = "\x1b[2J\x1b[H"
BOLD = "\x1b[1m"
DIM = "\x1b[2m"

# Zone definitions from BR_COLOR_SPEC.md
ZONES = {
    "OS_LAYER": (0, 15, "Core system primitives", "█"),
    "PERCEPTION": (16, 51, "Input, sensors, listeners", "▓"),
    "EXECUTION": (52, 87, "Actions, mutations, writes", "▶"),
    "MEMORY": (88, 123, "State, cache, persistence", "●"),
    "AUTONOMY": (124, 159, "Agents, decision, delegation", "◆"),
    "TENSION": (160, 195, "Warnings, drift, uncertainty", "▲"),
    "PARADOX": (196, 231, "Errors, contradiction, halt", "✖"),
    "META": (232, 255, "Null, silence, void, escape", "◌"),
}

# Extended token definitions
TOKENS = {
    0: "NULL", 1: "ERROR", 2: "SUCCESS", 3: "WARN", 4: "INFO", 5: "DEBUG",
    6: "SYSCALL", 7: "NEUTRAL",
    16: "RAW_SENSOR", 28: "VALID_INPUT", 40: "STREAM_LIVE",
    64: "EXEC_HIGH", 76: "EXEC_ATOMIC", 202: "EXEC_FORCE",
    88: "MEM_VOLATILE", 100: "MEM_PERSIST", 118: "MEM_ARCHIVE",
    130: "AGENT_THINK", 136: "AGENT_EXEC", 154: "AGENT_META",
    166: "WARN_MEMORY", 178: "WARN_DRIFT", 190: "WARN_DEGRADE",
    196: "ERROR_FATAL", 208: "ERROR_DATA", 226: "ERROR_CASCADE",
    232: "META_NULL", 244: "META_ESCAPE", 255: "META_BRIGHT",
}

# Canonical BR shape mapping
ZONE_SHAPES = {
    range(0, 16): "█", range(16, 52): "▓", range(52, 88): "▶",
    range(88, 124): "●", range(124, 160): "◆", range(160, 196): "▲",
    range(196, 232): "✖", range(232, 256): "◌",
}

# Special semantic glyphs
SPECIAL_SHAPES = {
    0: "∅", 1: "✗", 2: "✓", 3: "⚠", 4: "ⓘ",
    196: "✗", 202: "⚡", 226: "★", 232: "∅", 255: "◉",
}

def get_zone_info(color):
    """Get zone name, description, and default shape for a color."""
    for zone_name, (start, end, desc, shape) in ZONES.items():
        if start <= color <= end:
            return zone_name, desc, shape
    return "UNKNOWN", "", "?"

def get_shape(color):
    """Get semantic shape glyph for a color."""
    if color in SPECIAL_SHAPES:
        return SPECIAL_SHAPES[color]
    for color_range, shape in ZONE_SHAPES.items():
        if color in color_range:
            return shape
    return "?"

def get_key():
    """Get single keypress."""
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(fd)
        ch = sys.stdin.read(1)
        if ch == '\x1b':  # Escape sequence
            ch2 = sys.stdin.read(1)
            if ch2 == '[':
                ch3 = sys.stdin.read(1)
                return f'[{ch3}'
        return ch
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)

def render_palette(current_color, mode="full"):
    """Render full palette with current selection highlighted."""
    print(CLEAR)
    
    # Header with mode indicator
    print("═" * 78)
    print(f"{BOLD}BR COLOR PALETTE{RESET} — {DIM}Visual Programming Language{RESET}")
    print("─" * 78)
    print("Controls: ↑↓←→ Navigate | Z: Zone | F: Full | S: Shape | Q: Quit | ?: Help")
    print("═" * 78)
    
    if mode == "zone":
        # Show only current zone
        zone_name, _, _ = get_zone_info(current_color)
        for zn, (start, end, desc, zone_shape) in ZONES.items():
            if zn == zone_name:
                print(f"\n{BOLD}{zone_name}{RESET} ({start}–{end}): {desc}")
                print(f"Zone shape: {zone_shape}\n")
                
                for i in range(start, end + 1):
                    render_color_cell(i, current_color)
                    if (i - start + 1) % 6 == 0:
                        print()
                print()
                break
    elif mode == "shape":
        # Show all zones with shapes prominently
        for zone_name, (start, end, desc, zone_shape) in ZONES.items():
            in_zone = start <= current_color <= end
            marker = "▶ " if in_zone else "  "
            print(f"\n{marker}{BOLD if in_zone else ''}{zone_name:12}{RESET} {zone_shape}  {desc}")
    else:
        # Full view
        for zone_name, (start, end, desc, zone_shape) in ZONES.items():
            in_zone = start <= current_color <= end
            zone_display = f"{BOLD}{zone_name}{RESET}" if in_zone else zone_name
            print(f"\n{zone_display} ({start}–{end}): {desc} {DIM}[{zone_shape}]{RESET}")
            print()
            
            for i in range(start, end + 1):
                render_color_cell(i, current_color)
                if (i - start + 1) % 6 == 0:
                    print()
            print()
    
    # Enhanced current color detail panel
    render_detail_panel(current_color)

def render_color_cell(color, current_color):
    """Render a single color cell."""
    bg = f"\x1b[48;5;{color}m"
    fg_color = 255 if color < 128 else 0
    fg = f"\x1b[38;5;{fg_color}m"
    
    # Highlight current selection
    if color == current_color:
        marker = "▶"
        highlight = BOLD
    else:
        marker = " "
        highlight = ""
    
    shape = get_shape(color)
    print(f"{marker}{highlight}{bg}{fg} {shape:^3} {RESET}", end=" ")

def render_detail_panel(current_color):
    """Render detailed semantic panel for current color."""
    print("\n" + "═" * 78)
    
    zone, desc, zone_shape = get_zone_info(current_color)
    token = TOKENS.get(current_color, f"COLOR_{current_color}")
    shape = get_shape(current_color)
    
    # Large color swatch
    bg = f"\x1b[48;5;{current_color}m"
    fg_color = 255 if current_color < 128 else 0
    fg = f"\x1b[38;5;{fg_color}m"
    
    print(f"{BOLD}CURRENT SELECTION{RESET}")
    print(f"\n  {bg}{fg}    {shape}  {current_color:>3}    {RESET}\n")
    
    # Semantic details
    print(f"  Color:  {current_color}")
    print(f"  Token:  {BOLD}{token}{RESET}")
    print(f"  Shape:  {shape}  {DIM}(zone default: {zone_shape}){RESET}")
    print(f"  Zone:   {zone}")
    print(f"  Desc:   {desc}")
    
    # Show related colors if special
    if current_color in SPECIAL_SHAPES:
        print(f"  {DIM}Special operator glyph{RESET}")
    
    # Context examples
    print(f"\n{DIM}Use in sequence: br-shape ... {current_color} ...{RESET}")
    
    print("═" * 78)

def show_help():
    """Show help screen."""
    print(CLEAR)
    print("═" * 78)
    print(f"{BOLD}BR COLOR PALETTE — HELP{RESET}")
    print("═" * 78)
    print()
    print(f"{BOLD}NAVIGATION{RESET}")
    print("  ↑/↓         Move up/down by 6 (grid row)")
    print("  ←/→         Move left/right by 1")
    print("  PgUp/PgDn   Move by 36 (large jump)")
    print("  Home        Jump to start (color 0)")
    print("  End         Jump to end (color 255)")
    print()
    print(f"{BOLD}VIEW MODES{RESET}")
    print("  f           Full palette view (default)")
    print("  z           Zone-only view (current zone)")
    print("  s           Shape reference view (all zones)")
    print()
    print(f"{BOLD}COMMANDS{RESET}")
    print("  q           Quit")
    print("  ?           Show this help")
    print("  Enter       Show detailed info")
    print()
    print(f"{BOLD}BR SHAPE GRAMMAR{RESET}")
    print("  █  OS_LAYER    Core system primitives")
    print("  ▓  PERCEPTION  Input, sensors, listeners")
    print("  ▶  EXECUTION   Actions, mutations, writes")
    print("  ●  MEMORY      State, cache, persistence")
    print("  ◆  AUTONOMY    Agents, decision, delegation")
    print("  ▲  TENSION     Warnings, drift, uncertainty")
    print("  ✖  PARADOX     Errors, contradiction, halt")
    print("  ◌  META        Null, silence, void, escape")
    print()
    print(f"{DIM}Special glyphs: ∅ ✗ ✓ ⚠ ⚡ ★ ◉{RESET}")
    print()
    print("Press any key to return...")
    print("═" * 78)
    get_key()

def main():
    current = 0
    mode = "full"  # full, zone, shape
    
    print("\x1b[?25l")  # Hide cursor
    
    try:
        while True:
            render_palette(current, mode=mode)
            
            key = get_key()
            
            if key == 'q' or key == 'Q':
                break
            elif key == '?':
                show_help()
            elif key == 'f' or key == 'F':
                mode = "full"
            elif key == 'z' or key == 'Z':
                mode = "zone"
            elif key == 's' or key == 'S':
                mode = "shape"
            elif key == '[A':  # Up
                current = max(0, current - 6)
            elif key == '[B':  # Down
                current = min(255, current + 6)
            elif key == '[C':  # Right
                current = min(255, current + 1)
            elif key == '[D':  # Left
                current = max(0, current - 1)
            elif key == '[5':  # Page Up
                current = max(0, current - 36)
            elif key == '[6':  # Page Down
                current = min(255, current + 36)
            elif key == '[H':  # Home
                current = 0
            elif key == '[F':  # End
                current = 255
            elif key == '\n':  # Enter - show detail
                pass  # Already showing detail in panel
                
    except KeyboardInterrupt:
        pass
    finally:
        print(CLEAR)
        print("\x1b[?25h")  # Show cursor
        print(f"{BOLD}BR Palette closed.{RESET}\n")
        print(f"{DIM}Use 'br-shape <color>' for CLI queries{RESET}\n")

if __name__ == "__main__":
    main()
