#!/usr/bin/env python3
"""
Timmy's Morrowind Console Bridge.
Sends Lua commands to OpenMW via the in-game console.
Takes screenshots and OCRs them for perception.
"""

import subprocess, time, os, shutil
import Quartz, CoreFoundation

SESSION_DIR = os.path.expanduser(f"~/.timmy/morrowind/session_{time.strftime('%Y%m%d_%H%M')}")
os.makedirs(SESSION_DIR, exist_ok=True)

frame_count = 0

def send_keys_to_openmw(keycode):
    """Send a single key code to OpenMW via System Events."""
    subprocess.run(['osascript', '-e', f'''
        tell application "System Events"
            tell process "openmw"
                key code {keycode}
            end tell
        end tell
    '''], capture_output=True, timeout=3)

def send_char_to_openmw(char):
    """Send a character keystroke to OpenMW."""
    subprocess.run(['osascript', '-e', f'''
        tell application "System Events"
            tell process "openmw"
                keystroke "{char}"
            end tell
        end tell
    '''], capture_output=True, timeout=3)

def send_text_to_openmw(text):
    """Type a string into OpenMW."""
    # Escape special chars for AppleScript
    escaped = text.replace('\\', '\\\\').replace('"', '\\"')
    subprocess.run(['osascript', '-e', f'''
        tell application "System Events"
            tell process "openmw"
                keystroke "{escaped}"
            end tell
        end tell
    '''], capture_output=True, timeout=5)

# Key codes
BACKTICK = 50  # ` to open/close console
RETURN = 36
ESCAPE = 53
SPACE = 49

def open_console():
    send_keys_to_openmw(BACKTICK)
    time.sleep(0.4)

def close_console():
    send_keys_to_openmw(BACKTICK)
    time.sleep(0.3)

def console_command(cmd):
    """Open console, type a command, execute, close console."""
    open_console()
    time.sleep(0.3)
    send_text_to_openmw(cmd)
    time.sleep(0.2)
    send_keys_to_openmw(RETURN)
    time.sleep(0.3)
    close_console()
    time.sleep(0.2)

def lua_player(code):
    """Run Lua code in player context."""
    console_command(f"luap {code}")

def lua_global(code):
    """Run Lua code in global context."""
    console_command(f"luag {code}")

def timmy_event(event_name, data_str="{}"):
    """Send a Timmy event via global script."""
    lua_global(f'core.sendGlobalEvent("{event_name}", {data_str})')

def screenshot(label=""):
    """Take a screenshot and save it to the session directory."""
    global frame_count
    frame_count += 1
    
    image = Quartz.CGDisplayCreateImage(Quartz.CGMainDisplayID())
    if not image:
        return None
    
    fname = f"frame_{frame_count:04d}"
    if label:
        fname += f"_{label}"
    fname += ".png"
    path = os.path.join(SESSION_DIR, fname)
    
    url = CoreFoundation.CFURLCreateWithFileSystemPath(None, path, 0, False)
    dest = Quartz.CGImageDestinationCreateWithURL(url, 'public.png', 1, None)
    Quartz.CGImageDestinationAddImage(dest, image, None)
    Quartz.CGImageDestinationFinalize(dest)
    
    return path

def ocr_screenshot(path):
    """OCR a screenshot using macOS Vision."""
    from Foundation import NSURL
    from Quartz import CIImage
    import Vision
    
    url = NSURL.fileURLWithPath_(path)
    ci = CIImage.imageWithContentsOfURL_(url)
    if not ci:
        return []
    req = Vision.VNRecognizeTextRequest.alloc().init()
    req.setRecognitionLevel_(1)
    handler = Vision.VNImageRequestHandler.alloc().initWithCIImage_options_(ci, None)
    handler.performRequests_error_([req], None)
    return [r.text() for r in (req.results() or [])]

def read_log(n=10):
    """Read last N lines of OpenMW log."""
    log_path = os.path.expanduser("~/Library/Preferences/openmw/openmw.log")
    with open(log_path) as f:
        return f.readlines()[-n:]

# ═══════════════════════════════════════
# HIGH-LEVEL ACTIONS
# ═══════════════════════════════════════

def walk_forward(duration=3, run=False):
    timmy_event("TimmyWalk", f'{{duration={duration}, run={str(run).lower()}}}')

def stop():
    timmy_event("TimmyStop")

def turn(radians=0.5):
    timmy_event("TimmyTurn", f'{{angle={radians}}}')

def jump():
    timmy_event("TimmyJump")

def attack(attack_type="any"):
    timmy_event("TimmyAttack", f'{{type="{attack_type}"}}')

def explore():
    timmy_event("TimmyExplore")

def walk_to(x, y, z):
    timmy_event("TimmyWalkTo", f'{{x={x}, y={y}, z={z}}}')

def perceive():
    timmy_event("TimmyPerceive")

def press_space():
    send_keys_to_openmw(SPACE)

def press_escape():
    send_keys_to_openmw(ESCAPE)


if __name__ == "__main__":
    print(f"Session: {SESSION_DIR}")
    print("Console bridge ready.")
