#!/usr/bin/env python3
"""
McRogueFace Feature Demo System

Usage:
    Headless (screenshots): ./mcrogueface --headless --exec tests/demo/demo_main.py
    Interactive: ./mcrogueface tests/demo/demo_main.py

In headless mode, generates screenshots for each feature screen.
In interactive mode, provides a menu to navigate between screens.
"""
import mcrfpy
from mcrfpy import automation
import sys
import os

# Add parent to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

# Import screen modules
from demo.screens.caption_demo import CaptionDemo
from demo.screens.frame_demo import FrameDemo
from demo.screens.primitives_demo import PrimitivesDemo
from demo.screens.grid_demo import GridDemo
from demo.screens.animation_demo import AnimationDemo
from demo.screens.color_demo import ColorDemo

# All demo screens in order
DEMO_SCREENS = [
    CaptionDemo,
    FrameDemo,
    PrimitivesDemo,
    GridDemo,
    AnimationDemo,
    ColorDemo,
]

class DemoRunner:
    """Manages the demo system."""

    def __init__(self):
        self.screens = []
        self.menu = None
        self.current_index = 0
        self.headless = self._detect_headless()
        self.screenshot_dir = os.path.join(os.path.dirname(__file__), "screenshots")

    def _detect_headless(self):
        """Detect if running in headless mode."""
        # Check window resolution - headless mode has a default resolution
        try:
            win = mcrfpy.Window.get()
            # In headless mode, Window.get() still returns an object
            # Check if we're in headless by looking for the indicator
            return str(win).find("headless") >= 0
        except:
            return True

    def setup_all_screens(self):
        """Initialize all demo screens."""
        for i, ScreenClass in enumerate(DEMO_SCREENS):
            scene_name = f"demo_{i:02d}_{ScreenClass.name.lower().replace(' ', '_')}"
            screen = ScreenClass(scene_name)
            screen.setup()
            self.screens.append(screen)

    def create_menu(self):
        """Create the main menu screen."""
        # #372: was a local, but run_interactive() referenced `menu` -- NameError on
        # every interactive launch. Keep it on the runner.
        self.menu = mcrfpy.Scene("menu")
        menu = self.menu
        ui = menu.children

        # Title
        title = mcrfpy.Caption(text="McRogueFace Demo", pos=(400, 30))
        title.fill_color = mcrfpy.Color(255, 255, 255)
        title.outline = 2
        title.outline_color = mcrfpy.Color(0, 0, 0)
        ui.append(title)

        subtitle = mcrfpy.Caption(text="Feature Showcase", pos=(400, 70))
        subtitle.fill_color = mcrfpy.Color(180, 180, 180)
        ui.append(subtitle)

        # Menu items
        for i, screen in enumerate(self.screens):
            y = 130 + i * 50

            # Button frame
            btn = mcrfpy.Frame(pos=(250, y), size=(300, 40))
            btn.fill_color = mcrfpy.Color(50, 50, 70)
            btn.outline = 1
            btn.outline_color = mcrfpy.Color(100, 100, 150)
            ui.append(btn)

            # Button text
            label = mcrfpy.Caption(text=f"{i+1}. {screen.name}", pos=(20, 8))
            label.fill_color = mcrfpy.Color(200, 200, 255)
            btn.children.append(label)

            # Store index for click handler
            btn.name = f"menu_{i}"

        # Instructions
        instr = mcrfpy.Caption(text="Press 1-6 to view demos, ESC to return to menu", pos=(200, 500))
        instr.fill_color = mcrfpy.Color(150, 150, 150)
        ui.append(instr)

    def run_headless(self):
        """Run in headless mode - generate all screenshots.

        #372/#350: this used to drive a Timer and wait for render frames. Headless
        timers only advance under mcrfpy.step(), so that loop never fired. It is also
        unnecessary: a screenshot renders the current state synchronously and costs
        zero simulation time, so we can just activate each scene and shoot it.
        """
        print(f"Generating {len(self.screens)} demo screenshots...")
        os.makedirs(self.screenshot_dir, exist_ok=True)

        for i, screen in enumerate(self.screens):
            # #372: was `mcrfpy.current_scene = screen` -- a DemoScreen, not a Scene,
            # which raised TypeError and broke the headless path outright.
            screen.scene.activate()
            filename = os.path.join(self.screenshot_dir, screen.get_screenshot_name())
            automation.screenshot(filename)
            print(f"  [{i+1}/{len(self.screens)}] {filename}")

        print("Done!")

    def run_interactive(self):
        """Run in interactive mode with menu."""
        self.create_menu()
        menu = self.menu

        def handle_key(key, state):
            if state != mcrfpy.InputState.PRESSED:
                return

            # Number keys 1-9 for direct screen access
            _num_key_map = {mcrfpy.Key.NUM_1: 0, mcrfpy.Key.NUM_2: 1, mcrfpy.Key.NUM_3: 2,
                            mcrfpy.Key.NUM_4: 3, mcrfpy.Key.NUM_5: 4, mcrfpy.Key.NUM_6: 5,
                            mcrfpy.Key.NUM_7: 6, mcrfpy.Key.NUM_8: 7, mcrfpy.Key.NUM_9: 8}
            if key in _num_key_map:
                idx = _num_key_map[key]
                if idx < len(self.screens):
                    # #372: mcrfpy.setScene() no longer exists.
                    self.screens[idx].scene.activate()

            # ESC returns to menu
            elif key == mcrfpy.Key.ESCAPE:
                menu.activate()

            # Q quits
            elif key == mcrfpy.Key.Q:
                sys.exit(0)

        # The same handler serves the menu and every demo scene, so ESC always works.
        menu.on_key = handle_key
        for screen in self.screens:
            screen.scene.on_key = handle_key

        # Start on menu
        menu.activate()

def main():
    """Main entry point."""
    runner = DemoRunner()
    runner.setup_all_screens()

    if runner.headless:
        runner.run_headless()
        # #350: a headless --exec script must declare its outcome.
        sys.exit(0)
    else:
        runner.run_interactive()

# Run when executed
main()
