#!/usr/bin/env python3
"""
Timmy's Morrowind Agent — Gameplay loop with perception and action.

Uses:
- Quartz screenshots for visual perception  
- macOS Vision OCR for text reading (limited with Morrowind fonts)
- OpenMW console commands (via ` key) for game state queries
- pynput for keyboard/mouse input
- OpenMW log file for event tracking

The agent runs a perceive → think → act loop.
"""

import sys, time, subprocess, shutil, os, re
sys.path.insert(0, '/Users/apayne/.timmy/morrowind')
from play import *
from pynput.keyboard import Key, KeyCode

OPENMW_LOG = os.path.expanduser("~/Library/Preferences/openmw/openmw.log")
SCREENSHOT_DIR = os.path.expanduser("~/.timmy/morrowind/screenshots")
os.makedirs(SCREENSHOT_DIR, exist_ok=True)

frame = 0

def focus_game():
    subprocess.run(["osascript", "-e",
        'tell application "System Events" to set frontmost of process "openmw" to true'],
        capture_output=True)
    time.sleep(0.5)
    click(3456 // 4, 2234 // 4)
    time.sleep(0.2)

def read_log_tail(n=20):
    """Read last N lines of OpenMW log."""
    try:
        with open(OPENMW_LOG, 'r') as f:
            lines = f.readlines()
            return [l.strip() for l in lines[-n:]]
    except:
        return []

def get_location_from_log():
    """Parse the most recent cell loading from the log."""
    lines = read_log_tail(50)
    cells = []
    for line in reversed(lines):
        m = re.search(r'Loading cell (.+?)(?:\s*\(|$)', line)
        if m:
            cells.append(m.group(1).strip())
    return cells[0] if cells else "unknown"

def open_console():
    """Open the OpenMW console with ` key."""
    press_key(KeyCode.from_char('`'))
    time.sleep(0.3)

def close_console():
    """Close the console."""
    press_key(KeyCode.from_char('`'))
    time.sleep(0.3)

def console_command(cmd):
    """Type a command in the console and read the response."""
    open_console()
    time.sleep(0.2)
    type_text(cmd)
    time.sleep(0.1)
    press_key(Key.enter)
    time.sleep(0.5)
    # Screenshot to read console output
    result = screenshot()
    texts = ocr()
    close_console()
    return " | ".join(t["text"] for t in texts)

def perceive():
    """Gather all available information about the game state."""
    global frame
    frame += 1
    
    # Screenshot
    path_info = screenshot()
    if path_info:
        shutil.copy('/tmp/morrowind_screen.png', 
                     f'{SCREENSHOT_DIR}/frame_{frame:04d}.png')
    
    # Log-based perception
    location = get_location_from_log()
    log_lines = read_log_tail(10)
    
    # OCR (limited but sometimes useful)
    texts = ocr()
    ocr_text = " | ".join(t["text"] for t in texts[:10] if t["confidence"] > 0.3)
    
    return {
        "frame": frame,
        "location": location,
        "ocr": ocr_text,
        "log": log_lines[-5:],
        "screenshot": f'{SCREENSHOT_DIR}/frame_{frame:04d}.png',
    }

def act_explore():
    """Basic exploration behavior: walk forward, look around, interact."""
    # Walk forward
    walk_forward(2.0 + (frame % 3))
    
    # Occasionally look around
    if frame % 3 == 0:
        look_around(30 + (frame % 60) - 30)
    
    # Occasionally try to interact
    if frame % 5 == 0:
        use()
        time.sleep(0.5)

def act_wander():
    """Random wandering with more variety."""
    import random
    action = random.choice(['forward', 'forward', 'forward', 'turn_left', 'turn_right', 'look_up', 'interact'])
    
    if action == 'forward':
        walk_forward(random.uniform(1.0, 4.0))
    elif action == 'turn_left':
        look_around(random.randint(-90, -20))
        time.sleep(0.2)
        walk_forward(random.uniform(1.0, 2.0))
    elif action == 'turn_right':
        look_around(random.randint(20, 90))
        time.sleep(0.2)
        walk_forward(random.uniform(1.0, 2.0))
    elif action == 'look_up':
        look_up(random.randint(10, 30))
        time.sleep(0.5)
        look_down(random.randint(10, 30))
    elif action == 'interact':
        use()
        time.sleep(1.0)

# ═══════════════════════════════════════
# MAIN LOOP
# ═══════════════════════════════════════

if __name__ == "__main__":
    print("=== Timmy's Morrowind Agent ===")
    print("Focusing game...")
    focus_game()
    time.sleep(1)
    
    # Dismiss any menus
    press_key(Key.esc)
    time.sleep(0.3)
    press_key(Key.esc)
    time.sleep(0.3)
    click(3456 // 4, 2234 // 4)
    time.sleep(0.3)
    
    print("Starting gameplay loop...")
    
    NUM_CYCLES = 15
    for i in range(NUM_CYCLES):
        print(f"\n--- Cycle {i+1}/{NUM_CYCLES} ---")
        
        # Perceive
        state = perceive()
        print(f"  Location: {state['location']}")
        print(f"  OCR: {state['ocr'][:100]}")
        
        # Act
        act_wander()
        
        # Brief pause between cycles
        time.sleep(0.5)
    
    # Final perception
    print("\n=== Final State ===")
    state = perceive()
    print(f"Location: {state['location']}")
    print(f"Frames captured: {frame}")
    print(f"Screenshots in: {SCREENSHOT_DIR}")
    
    # Quicksave
    print("Quicksaving...")
    from pynput.keyboard import Key
    press_key(Key.f5)
    time.sleep(1)
    print("Done.")
