"""Mode handler for CLI"""

from abc import ABC, abstractmethod
from typing import Optional


class ModeConstants:
    """Constants for mode handlers"""

    MODE_CLIENT = "client"
    MODE_AGENT = "agent"
    MODE_WEB = "web"


class ModeHandler(ABC):
    """Base class for mode handlers"""

    @property
    @abstractmethod
    def name(self) -> str:
        """Mode name"""
        pass

    @property
    @abstractmethod
    def prompt_prefix(self) -> str:
        """Prompt prefix for this mode"""
        pass

    @abstractmethod
    def should_exit(self, user_input: str) -> bool:
        """Check if the input should cause exiting this mode
        
        Args:
            user_input: User input string
            
        Returns:
            True if should exit this mode
        """
        pass

    @abstractmethod
    def on_activate(self):
        """Called when mode is activated"""
        pass

    @abstractmethod
    def on_deactivate(self):
        """Called when mode is deactivated"""
        pass


class ModeManager:
    """Manager for CLI modes"""

    _instance: Optional["ModeManager"] = None

    def __new__(cls) -> "ModeManager":
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance._initialized = False
        return cls._instance

    def __init__(self) -> None:
        if self._initialized:
            return

        self._modes: dict[str, ModeHandler] = {}
        self._current_mode: Optional[ModeHandler] = None
        self._initialized = True

    def register_mode(self, mode: ModeHandler) -> None:
        """Register a mode handler
        
        Args:
            mode: Mode handler to register
        """
        self._modes[mode.name] = mode

    def get_mode(self, name: str) -> Optional[ModeHandler]:
        """Get a mode handler by name
        
        Args:
            name: Mode name
            
        Returns:
            Mode handler or None
        """
        return self._modes.get(name)

    def set_mode(self, name: str) -> bool:
        """Set current mode
        
        Args:
            name: Mode name
            
        Returns:
            True if mode was set successfully
        """
        mode = self._modes.get(name)
        if mode is None:
            return False

        if self._current_mode is not None:
            self._current_mode.on_deactivate()

        self._current_mode = mode
        self._current_mode.on_activate()
        return True

    def exit_mode(self) -> bool:
        """Exit current mode
        
        Returns:
            True if exited successfully
        """
        if self._current_mode is None:
            return False

        self._current_mode.on_deactivate()
        self._current_mode = None
        return True

    @property
    def current_mode(self) -> Optional[ModeHandler]:
        """Get current mode"""
        return self._current_mode

    @property
    def is_default_mode(self) -> bool:
        """Check if in default mode (no mode active or in client mode)"""
        return self._current_mode is None or self._current_mode.name == ModeConstants.MODE_CLIENT


def get_mode_manager() -> ModeManager:
    """Get singleton mode manager
    
    Returns:
        ModeManager instance
    """
    return ModeManager()
