#!/usr/bin/env python3
"""Focus System Demo for McRogueFace

Demonstrates a Python-level focus management system using engine primitives.
This shows how game developers can implement keyboard navigation without
requiring C++ engine changes.

Features demonstrated:
- Click-to-focus
- Tab/Shift+Tab cycling
- Visual focus indicators
- Keyboard routing to focused widget
- Modal focus stack
- Three widget types: Grid (WASD), TextInput, MenuIcon

Issue: #143
"""

import mcrfpy
import sys

# =============================================================================
# Modifier Key Tracker (workaround until #160 is implemented)
# =============================================================================

class ModifierTracker:
    """Tracks modifier key state since engine doesn't expose this yet."""

    def __init__(self):
        self.shift = False
        self.ctrl = False
        self.alt = False

    def update(self, key, action):
        """Call this from your key handler to update modifier state."""
        if key in (mcrfpy.Key.LEFT_SHIFT, mcrfpy.Key.RIGHT_SHIFT):
            self.shift = (action == mcrfpy.InputState.PRESSED)
        elif key in (mcrfpy.Key.LEFT_CONTROL, mcrfpy.Key.RIGHT_CONTROL):
            self.ctrl = (action == mcrfpy.InputState.PRESSED)
        elif key in (mcrfpy.Key.LEFT_ALT, mcrfpy.Key.RIGHT_ALT):
            self.alt = (action == mcrfpy.InputState.PRESSED)


# =============================================================================
# Focus Manager
# =============================================================================

class FocusManager:
    """Central focus coordinator for a scene.

    Manages which widget receives keyboard input, handles tab cycling,
    and maintains a modal stack for popup dialogs.
    """

    # Focus indicator colors
    FOCUS_COLOR = mcrfpy.Color(0, 150, 255)      # Blue
    UNFOCUS_COLOR = mcrfpy.Color(80, 80, 80)     # Dark gray
    FOCUS_OUTLINE = 3.0
    UNFOCUS_OUTLINE = 1.0

    def __init__(self):
        self.widgets = []           # List of (widget, focusable: bool)
        self.focus_index = -1       # Currently focused widget index
        self.modal_stack = []       # Stack of (modal_frame, previous_focus_index)
        self.modifiers = ModifierTracker()

    def register(self, widget, focusable: bool = True):
        """Add a widget to the focus order.

        Args:
            widget: Object implementing on_focus(), on_blur(), handle_key()
            focusable: Whether this widget can receive focus via Tab
        """
        self.widgets.append((widget, focusable))
        # Give widget a reference back to us for click-to-focus
        widget._focus_manager = self
        widget._focus_index = len(self.widgets) - 1

    def focus(self, widget_or_index):
        """Set focus to a specific widget."""
        # Resolve to index
        if isinstance(widget_or_index, int):
            new_index = widget_or_index
        else:
            new_index = next(
                (i for i, (w, _) in enumerate(self.widgets) if w is widget_or_index),
                -1
            )

        if new_index < 0 or new_index >= len(self.widgets):
            return

        # Blur old widget
        if 0 <= self.focus_index < len(self.widgets):
            old_widget, _ = self.widgets[self.focus_index]
            if hasattr(old_widget, 'on_blur'):
                old_widget.on_blur()

        # Focus new widget
        self.focus_index = new_index
        new_widget, _ = self.widgets[new_index]
        if hasattr(new_widget, 'on_focus'):
            new_widget.on_focus()

    def cycle(self, direction: int = 1):
        """Cycle focus to next/previous focusable widget.

        Args:
            direction: 1 for next (Tab), -1 for previous (Shift+Tab)
        """
        if not self.widgets:
            return

        start = self.focus_index if self.focus_index >= 0 else 0
        current = start

        for _ in range(len(self.widgets)):
            current = (current + direction) % len(self.widgets)
            widget, focusable = self.widgets[current]
            if focusable:
                self.focus(current)
                return

        # No focusable widget found, stay where we are

    def push_modal(self, modal_frame, first_focus_widget=None):
        """Push a modal onto the focus stack.

        Args:
            modal_frame: The Frame to show as modal
            first_focus_widget: Widget to focus inside modal (optional)
        """
        # Save current focus
        self.modal_stack.append((modal_frame, self.focus_index))

        # Show modal
        modal_frame.visible = True

        # Focus first widget in modal if specified
        if first_focus_widget is not None:
            self.focus(first_focus_widget)

    def pop_modal(self):
        """Pop the top modal and restore previous focus."""
        if not self.modal_stack:
            return False

        modal_frame, previous_focus = self.modal_stack.pop()
        modal_frame.visible = False

        # Restore focus
        if previous_focus >= 0:
            self.focus(previous_focus)

        return True

    def handle_key(self, key: str, action: str) -> bool:
        """Main key handler - route to focused widget or handle global keys.

        Returns True if key was consumed.
        """
        # Always update modifier state
        self.modifiers.update(key, action)

        # Only process on key press, not release (key repeat sends multiple "start")
        if action != mcrfpy.InputState.PRESSED:
            return False

        # Global: Escape closes modals
        if key == mcrfpy.Key.ESCAPE:
            if self.pop_modal():
                return True

        # Global: Tab cycles focus
        if key == mcrfpy.Key.TAB:
            direction = -1 if self.modifiers.shift else 1
            self.cycle(direction)
            return True

        # Route to focused widget
        if 0 <= self.focus_index < len(self.widgets):
            widget, _ = self.widgets[self.focus_index]
            if hasattr(widget, 'handle_key'):
                if widget.handle_key(key, action):
                    return True

        return False


# =============================================================================
# Focusable Widgets
# =============================================================================

class FocusableGrid:
    """A grid where WASD keys move a player entity.

    Demonstrates focus on a game-world element.
    """

    def __init__(self, x: float, y: float, grid_w: int, grid_h: int,
                 tile_size: int = 16, zoom: float = 2.0):
        self.grid_w = grid_w
        self.grid_h = grid_h
        self.tile_size = tile_size
        self.zoom = zoom
        self.base_x = x
        self.base_y = y

        # Calculate pixel dimensions
        self.cell_px = tile_size * zoom  # Pixels per cell
        grid_pixel_w = grid_w * self.cell_px
        grid_pixel_h = grid_h * self.cell_px

        # Create the grid background
        self.grid = mcrfpy.Grid(
            pos=(x, y),
            grid_size=(grid_w, grid_h),
            size=(grid_pixel_w, grid_pixel_h)
        )
        self.grid.zoom = zoom
        self.grid.fill_color = mcrfpy.Color(40, 40, 55)

        # Add outline frame for focus indication
        self.outline_frame = mcrfpy.Frame(
            pos=(x - 2, y - 2),
            size=(grid_pixel_w + 4, grid_pixel_h + 4),
            fill_color=mcrfpy.Color(0, 0, 0, 0),
            outline_color=FocusManager.UNFOCUS_COLOR,
            outline=FocusManager.UNFOCUS_OUTLINE
        )

        # Player marker (a bright square overlay)
        self.player_x = grid_w // 2
        self.player_y = grid_h // 2
        marker_size = self.cell_px - 4  # Slightly smaller than cell
        self.player_marker = mcrfpy.Frame(
            pos=(0, 0),  # Will be positioned by _update_player_display
            size=(marker_size, marker_size),
            fill_color=mcrfpy.Color(255, 200, 50),
            outline_color=mcrfpy.Color(255, 150, 0),
            outline=2
        )
        self._update_player_display()

        # Click handler
        self.grid.on_click = self._on_click

        # Focus manager reference (set by FocusManager.register)
        self._focus_manager = None
        self._focus_index = -1

    def _on_click(self, x, y, button, action):
        """Handle click to focus this grid."""
        if self._focus_manager and action == mcrfpy.InputState.PRESSED:
            self._focus_manager.focus(self._focus_index)

    def _update_player_display(self):
        """Update the visual representation of player position."""
        # Position the player marker
        px = self.base_x + (self.player_x * self.cell_px) + 2
        py = self.base_y + (self.player_y * self.cell_px) + 2
        self.player_marker.x = px
        self.player_marker.y = py

    def on_focus(self):
        """Called when this widget gains focus."""
        self.outline_frame.outline_color = FocusManager.FOCUS_COLOR
        self.outline_frame.outline = FocusManager.FOCUS_OUTLINE

    def on_blur(self):
        """Called when this widget loses focus."""
        self.outline_frame.outline_color = FocusManager.UNFOCUS_COLOR
        self.outline_frame.outline = FocusManager.UNFOCUS_OUTLINE

    def handle_key(self, key, action) -> bool:
        """Handle WASD movement."""
        moves = {
            mcrfpy.Key.W: (0, -1), mcrfpy.Key.UP: (0, -1),
            mcrfpy.Key.A: (-1, 0), mcrfpy.Key.LEFT: (-1, 0),
            mcrfpy.Key.S: (0, 1),  mcrfpy.Key.DOWN: (0, 1),
            mcrfpy.Key.D: (1, 0),  mcrfpy.Key.RIGHT: (1, 0),
        }

        if key in moves:
            dx, dy = moves[key]
            new_x = self.player_x + dx
            new_y = self.player_y + dy

            # Bounds check
            if 0 <= new_x < self.grid_w and 0 <= new_y < self.grid_h:
                self.player_x = new_x
                self.player_y = new_y
                self._update_player_display()
            return True

        return False

    def add_to_scene(self, ui):
        """Add all components to a scene's UI collection."""
        ui.append(self.outline_frame)
        ui.append(self.grid)
        ui.append(self.player_marker)


class TextInputWidget:
    """A text input field with cursor and editing.

    Demonstrates text entry with focus indication.
    """

    def __init__(self, x: float, y: float, width: float, label: str = "",
                 placeholder: str = ""):
        self.x = x
        self.y = y
        self.width = width
        self.height = 28
        self.label_text = label
        self.placeholder_text = placeholder

        # State
        self.text = ""
        self.cursor_pos = 0
        self.focused = False

        # Create UI elements
        self._create_ui()

        # Focus manager reference
        self._focus_manager = None
        self._focus_index = -1

    def _create_ui(self):
        """Create the visual components."""
        # Label above input
        if self.label_text:
            self.label = mcrfpy.Caption(
                text=self.label_text,
                pos=(self.x, self.y - 20)
            )
            self.label.fill_color = mcrfpy.Color(200, 200, 200)

        # Input background
        self.frame = mcrfpy.Frame(
            pos=(self.x, self.y),
            size=(self.width, self.height),
            fill_color=mcrfpy.Color(40, 40, 50),
            outline_color=FocusManager.UNFOCUS_COLOR,
            outline=FocusManager.UNFOCUS_OUTLINE
        )
        self.frame.on_click = self._on_click

        # Placeholder text
        self.placeholder = mcrfpy.Caption(
            text=self.placeholder_text,
            pos=(self.x + 6, self.y + 5)
        )
        self.placeholder.fill_color = mcrfpy.Color(100, 100, 100)

        # Actual text display
        self.display = mcrfpy.Caption(
            text="",
            pos=(self.x + 6, self.y + 5)
        )
        self.display.fill_color = mcrfpy.Color(255, 255, 255)

        # Cursor (thin frame)
        self.cursor = mcrfpy.Frame(
            pos=(self.x + 6, self.y + 4),
            size=(2, self.height - 8),
            fill_color=mcrfpy.Color(255, 255, 255)
        )
        self.cursor.visible = False

    def _on_click(self, x, y, button, action):
        """Handle click to focus."""
        if self._focus_manager and action == mcrfpy.InputState.PRESSED:
            self._focus_manager.focus(self._focus_index)

    def _update_display(self):
        """Update visual state."""
        self.display.text = self.text
        self.placeholder.visible = (not self.text and not self.focused)
        self._update_cursor()

    def _update_cursor(self):
        """Update cursor position."""
        # Approximate character width (monospace assumption)
        char_width = 10
        self.cursor.x = self.x + 6 + (self.cursor_pos * char_width)

    def on_focus(self):
        """Called when gaining focus."""
        self.focused = True
        self.frame.outline_color = FocusManager.FOCUS_COLOR
        self.frame.outline = FocusManager.FOCUS_OUTLINE
        self.cursor.visible = True
        self._update_display()

    def on_blur(self):
        """Called when losing focus."""
        self.focused = False
        self.frame.outline_color = FocusManager.UNFOCUS_COLOR
        self.frame.outline = FocusManager.UNFOCUS_OUTLINE
        self.cursor.visible = False
        self._update_display()

    def handle_key(self, key, action) -> bool:
        """Handle text input and editing keys."""
        if not self.focused:
            return False

        old_text = self.text
        handled = True

        if key == mcrfpy.Key.BACKSPACE:
            if self.cursor_pos > 0:
                self.text = self.text[:self.cursor_pos-1] + self.text[self.cursor_pos:]
                self.cursor_pos -= 1
        elif key == mcrfpy.Key.DELETE:
            if self.cursor_pos < len(self.text):
                self.text = self.text[:self.cursor_pos] + self.text[self.cursor_pos+1:]
        elif key == mcrfpy.Key.LEFT:
            self.cursor_pos = max(0, self.cursor_pos - 1)
        elif key == mcrfpy.Key.RIGHT:
            self.cursor_pos = min(len(self.text), self.cursor_pos + 1)
        elif key == mcrfpy.Key.HOME:
            self.cursor_pos = 0
        elif key == mcrfpy.Key.END:
            self.cursor_pos = len(self.text)
        elif key in (mcrfpy.Key.ENTER, mcrfpy.Key.TAB):
            # Don't consume - let focus manager handle
            handled = False
        elif len(key.name) == 1 and key.name.isprintable():
            # Insert character (key.name is "A"-"Z" for letter keys)
            self.text = self.text[:self.cursor_pos] + key.name.lower() + self.text[self.cursor_pos:]
            self.cursor_pos += 1
        else:
            handled = False

        self._update_display()
        return handled

    def get_text(self) -> str:
        """Get the current text value."""
        return self.text

    def set_text(self, text: str):
        """Set the text value."""
        self.text = text
        self.cursor_pos = len(text)
        self._update_display()

    def add_to_scene(self, ui):
        """Add all components to the scene."""
        if hasattr(self, 'label'):
            ui.append(self.label)
        ui.append(self.frame)
        ui.append(self.placeholder)
        ui.append(self.display)
        ui.append(self.cursor)


class MenuIcon:
    """An icon that opens a modal dialog when activated.

    Demonstrates activation via Space/Enter and modal focus.
    """

    def __init__(self, x: float, y: float, size: float, icon_char: str,
                 tooltip: str, modal_content_builder=None):
        self.x = x
        self.y = y
        self.size = size
        self.tooltip = tooltip
        self.modal_content_builder = modal_content_builder
        self.modal = None

        # Create icon frame
        self.frame = mcrfpy.Frame(
            pos=(x, y),
            size=(size, size),
            fill_color=mcrfpy.Color(60, 60, 80),
            outline_color=FocusManager.UNFOCUS_COLOR,
            outline=FocusManager.UNFOCUS_OUTLINE
        )
        self.frame.on_click = self._on_click

        # Icon character (centered)
        self.icon = mcrfpy.Caption(
            text=icon_char,
            pos=(x + size//3, y + size//6)
        )
        self.icon.fill_color = mcrfpy.Color(200, 200, 220)

        # Tooltip (shown on hover/focus)
        self.tooltip_caption = mcrfpy.Caption(
            text=tooltip,
            pos=(x, y + size + 4)
        )
        self.tooltip_caption.fill_color = mcrfpy.Color(150, 150, 150)
        self.tooltip_caption.visible = False

        # Focus manager reference
        self._focus_manager = None
        self._focus_index = -1

    def _on_click(self, x, y, button, action):
        """Handle click to focus or activate."""
        if not self._focus_manager:
            return

        if action == mcrfpy.InputState.PRESSED:
            # If already focused, activate; otherwise just focus
            if self._focus_manager.focus_index == self._focus_index:
                self._activate()
            else:
                self._focus_manager.focus(self._focus_index)

    def _activate(self):
        """Open the modal dialog."""
        if self.modal and self._focus_manager:
            self._focus_manager.push_modal(self.modal)

    def on_focus(self):
        """Called when gaining focus."""
        self.frame.outline_color = FocusManager.FOCUS_COLOR
        self.frame.outline = FocusManager.FOCUS_OUTLINE
        self.frame.fill_color = mcrfpy.Color(80, 80, 110)
        self.tooltip_caption.visible = True

    def on_blur(self):
        """Called when losing focus."""
        self.frame.outline_color = FocusManager.UNFOCUS_COLOR
        self.frame.outline = FocusManager.UNFOCUS_OUTLINE
        self.frame.fill_color = mcrfpy.Color(60, 60, 80)
        self.tooltip_caption.visible = False

    def handle_key(self, key, action) -> bool:
        """Handle activation keys."""
        if key in (mcrfpy.Key.SPACE, mcrfpy.Key.ENTER):
            self._activate()
            return True
        return False

    def set_modal(self, modal_frame):
        """Set the modal frame this icon opens."""
        self.modal = modal_frame

    def add_to_scene(self, ui):
        """Add all components to the scene."""
        ui.append(self.frame)
        ui.append(self.icon)
        ui.append(self.tooltip_caption)


# =============================================================================
# Modal Dialog Builder
# =============================================================================

def create_modal(x: float, y: float, width: float, height: float,
                 title: str) -> mcrfpy.Frame:
    """Create a modal dialog frame."""
    # Semi-transparent backdrop
    # Note: This is simplified - real implementation might want fullscreen backdrop

    # Modal frame
    modal = mcrfpy.Frame(
        pos=(x, y),
        size=(width, height),
        fill_color=mcrfpy.Color(40, 40, 50),
        outline_color=mcrfpy.Color(100, 100, 120),
        outline=2
    )
    modal.visible = False

    # Title
    title_caption = mcrfpy.Caption(
        text=title,
        pos=(x + 10, y + 8)
    )
    title_caption.fill_color = mcrfpy.Color(220, 220, 240)
    modal.children.append(title_caption)

    # Close hint
    close_hint = mcrfpy.Caption(
        text="[Esc to close]",
        pos=(x + width - 100, y + 8)
    )
    close_hint.fill_color = mcrfpy.Color(120, 120, 140)
    modal.children.append(close_hint)

    return modal


# =============================================================================
# Demo Scene Setup
# =============================================================================

def create_demo_scene():
    """Create and populate the focus system demo scene."""

    # Create scene
    focus_demo = mcrfpy.Scene("focus_demo")
    ui = focus_demo.children

    # Background
    bg = mcrfpy.Frame(
        pos=(0, 0),
        size=(1024, 768),
        fill_color=mcrfpy.Color(25, 25, 35)
    )
    ui.append(bg)

    # Title
    title = mcrfpy.Caption(
        text="Focus System Demo",
        pos=(20, 15)
    )
    title.fill_color = mcrfpy.Color(255, 255, 255)
    ui.append(title)

    # Instructions
    instructions = mcrfpy.Caption(
        text="Tab: cycle focus | Shift+Tab: reverse | WASD: move in grid | Space/Enter: activate | Esc: close modal",
        pos=(20, 45)
    )
    instructions.fill_color = mcrfpy.Color(150, 150, 170)
    ui.append(instructions)

    # Create focus manager
    focus_mgr = FocusManager()

    # --- Grid Section ---
    grid_label = mcrfpy.Caption(text="Game Grid (WASD to move)", pos=(50, 90))
    grid_label.fill_color = mcrfpy.Color(180, 180, 200)
    ui.append(grid_label)

    grid_widget = FocusableGrid(50, 115, 10, 8, tile_size=16, zoom=2.0)
    grid_widget.add_to_scene(ui)
    focus_mgr.register(grid_widget)

    # --- Text Inputs Section ---
    input_label = mcrfpy.Caption(text="Text Inputs", pos=(400, 90))
    input_label.fill_color = mcrfpy.Color(180, 180, 200)
    ui.append(input_label)

    name_input = TextInputWidget(400, 130, 250, label="Name:", placeholder="Enter your name")
    name_input.add_to_scene(ui)
    focus_mgr.register(name_input)

    class_input = TextInputWidget(400, 200, 250, label="Class:", placeholder="e.g. Warrior, Mage")
    class_input.add_to_scene(ui)
    focus_mgr.register(class_input)

    notes_input = TextInputWidget(400, 270, 350, label="Notes:", placeholder="Additional notes...")
    notes_input.add_to_scene(ui)
    focus_mgr.register(notes_input)

    # --- Menu Icons Section ---
    icons_label = mcrfpy.Caption(text="Menu Icons", pos=(50, 390))
    icons_label.fill_color = mcrfpy.Color(180, 180, 200)
    ui.append(icons_label)

    # Help icon
    help_icon = MenuIcon(50, 420, 48, "?", "Help")
    help_icon.add_to_scene(ui)
    focus_mgr.register(help_icon)

    help_modal = create_modal(200, 150, 400, 300, "Help")
    ui.append(help_modal)
    help_text = mcrfpy.Caption(
        text="This demo shows focus management.\n\nUse Tab to move between widgets.\nWASD moves the player in the grid.\nType in text fields.\nPress Space on icons to open dialogs.",
        pos=(210, 190)
    )
    help_text.fill_color = mcrfpy.Color(200, 200, 200)
    help_modal.children.append(help_text)
    help_icon.set_modal(help_modal)

    # Settings icon
    settings_icon = MenuIcon(110, 420, 48, "S", "Settings")
    settings_icon.add_to_scene(ui)
    focus_mgr.register(settings_icon)

    settings_modal = create_modal(200, 150, 400, 250, "Settings")
    ui.append(settings_modal)
    settings_text = mcrfpy.Caption(
        text="Settings would go here.\n\n(This is a placeholder modal)",
        pos=(210, 190)
    )
    settings_text.fill_color = mcrfpy.Color(200, 200, 200)
    settings_modal.children.append(settings_text)
    settings_icon.set_modal(settings_modal)

    # Inventory icon
    inv_icon = MenuIcon(170, 420, 48, "I", "Inventory")
    inv_icon.add_to_scene(ui)
    focus_mgr.register(inv_icon)

    inv_modal = create_modal(200, 150, 400, 300, "Inventory")
    ui.append(inv_modal)
    inv_text = mcrfpy.Caption(
        text="Your inventory:\n\n- Sword\n- Shield\n- 3x Potions",
        pos=(210, 190)
    )
    inv_text.fill_color = mcrfpy.Color(200, 200, 200)
    inv_modal.children.append(inv_text)
    inv_icon.set_modal(inv_modal)

    # --- Status Display ---
    status_frame = mcrfpy.Frame(
        pos=(50, 520),
        size=(700, 80),
        fill_color=mcrfpy.Color(35, 35, 45),
        outline_color=mcrfpy.Color(60, 60, 70),
        outline=1
    )
    ui.append(status_frame)

    status_label = mcrfpy.Caption(text="Status", pos=(60, 530))
    status_label.fill_color = mcrfpy.Color(150, 150, 170)
    ui.append(status_label)

    status_text = mcrfpy.Caption(text="Click or Tab to focus a widget", pos=(60, 555))
    status_text.fill_color = mcrfpy.Color(200, 200, 200)
    ui.append(status_text)

    # Store references for status updates
    demo_state = {
        'focus_mgr': focus_mgr,
        'status_text': status_text,
        'grid': grid_widget,
        'inputs': [name_input, class_input, notes_input],
        'icons': [help_icon, settings_icon, inv_icon],
    }

    # Key handler that routes to focus manager
    def on_key(key: str, action: str):
        focus_mgr.handle_key(key, action)

        # Update status display
        if focus_mgr.focus_index >= 0:
            widget, _ = focus_mgr.widgets[focus_mgr.focus_index]
            if widget is grid_widget:
                status_text.text = f"Grid focused - Player at ({grid_widget.player_x}, {grid_widget.player_y})"
            elif widget in demo_state['inputs']:
                idx = demo_state['inputs'].index(widget)
                labels = ["Name", "Class", "Notes"]
                status_text.text = f"{labels[idx]} input focused - Text: '{widget.get_text()}'"
            elif widget in demo_state['icons']:
                status_text.text = f"Icon focused: {widget.tooltip}"
        else:
            status_text.text = "No widget focused"

    # Activate scene first (keypressScene sets handler for CURRENT scene)
    focus_demo.activate()

    # Register key handler for the now-current scene
    focus_demo.on_key = on_key

    # Set initial focus
    focus_mgr.focus(0)

    return demo_state


# =============================================================================
# Entry Point
# =============================================================================

def run_demo():
    """Run the focus system demo."""
    print("=== Focus System Demo ===")
    print("Demonstrating Python-level focus management")
    print()
    print("Controls:")
    print("  Tab / Shift+Tab  - Cycle between widgets")
    print("  WASD / Arrows    - Move player in grid (when focused)")
    print("  Type             - Enter text in inputs (when focused)")
    print("  Space / Enter    - Activate icons (when focused)")
    print("  Escape           - Close modal dialogs")
    print("  Click            - Focus clicked widget")
    print()

    demo_state = create_demo_scene()

    # Set up exit timer for headless testing
    def check_exit(timer, dt):
        # In headless mode, exit after a short delay
        # In interactive mode, this won't trigger
        pass

    # check_exit_timer = mcrfpy.Timer("demo_check", check_exit, 100)


# Run if executed directly
if __name__ == "__main__":
    import sys
    from mcrfpy import automation

    run_demo()

    # If --screenshot flag, take a screenshot and exit
    if "--screenshot" in sys.argv or len(sys.argv) > 1:
        def take_screenshot(timer, dt):
            automation.screenshot("focus_demo_screenshot.png")
            print("Screenshot saved: focus_demo_screenshot.png")
            sys.exit(0)
        screenshot_timer = mcrfpy.Timer("screenshot", take_screenshot, 200, once=True)
