"""Camera subscriber terminal input handling module.

This module provides terminal input handling functionality for the camera subscriber.
It is part of the subscriber refactoring - see subscriber.py for the main module.
"""

import select
import sys
import termios
import threading
import tty
from typing import Optional


class TerminalInputHandler:
    """Handles non-blocking keyboard input from terminal.

    This class manages terminal raw mode for single-character input
    and provides a thread-safe way to check for keypresses.
    """

    def __init__(self) -> None:
        """Initialize the terminal input handler."""
        self._old_settings: Optional[termios.struct_termios] = None
        self._running = False
        self._input_thread: Optional[threading.Thread] = None
        self._input_queue: list[str] = []
        self._lock = threading.Lock()

    def start(self) -> None:
        """Start the terminal input handler in raw mode."""
        # Save current terminal settings
        self._old_settings = termios.tcgetattr(sys.stdin)

        # Set terminal to raw mode for single character input
        tty.setcbreak(sys.stdin.fileno())

        self._running = True
        self._input_thread = threading.Thread(target=self._read_input, daemon=True)
        self._input_thread.start()

    def _read_input(self) -> None:
        """Read input characters in a separate thread."""
        while self._running:
            try:
                # Use select to check if input is available (with timeout)
                if select.select([sys.stdin], [], [], 0.1)[0]:
                    char = sys.stdin.read(1)
                    if char:
                        with self._lock:
                            self._input_queue.append(char)
            except (OSError, IOError):
                # Terminal might be closed
                break

    def get_key(self) -> Optional[str]:
        """Get a single keypress from the input queue.

        Returns:
            The key character if available, None otherwise.
        """
        with self._lock:
            if self._input_queue:
                return self._input_queue.pop(0)
        return None

    def stop(self) -> None:
        """Stop the input handler and restore terminal settings."""
        self._running = False

        if self._input_thread is not None:
            self._input_thread.join(timeout=0.5)

        # Restore terminal settings
        if self._old_settings is not None:
            termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self._old_settings)
            self._old_settings = None
