from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Callable, Iterable

from ulauncher.internals.effects import EffectMessage
from ulauncher.internals.query import Query
from ulauncher.internals.result import Result


class Mode(ABC):
    def matches_query_str(self, _query_str: str) -> bool:
        """
        Returns if the input should be handled by the mode (only for dynamic modes without extensions).
        """
        return False

    def handle_backspace(self, _query_str: str) -> Query | None:
        """
        Returns a query if it should override default backspace behavior.
        """
        return None

    @abstractmethod
    def handle_query(self, _query: Query, callback: Callable[[EffectMessage], None]) -> None:
        """
        Handle a query and provide the result list via callback.
        """
        ...

    def get_placeholder_icon(self) -> str | None:
        """
        Returns icon for the placeholder result to show while waiting for async results.
        """
        return None

    def get_triggers(self) -> Iterable[Result]:
        """
        Return keyword triggers provided by this mode.
        """
        return []

    def has_trigger_changes(self) -> bool:
        """
        Returns True if this mode's triggers may need to be reloaded.
        Note that all triggers are reloaded when the Ulauncher window is shown,
        so this is mainly for modes that load trigger asynchronously and won't be ready initially.
        """
        return False

    def get_home_results(self, _limit: int) -> Iterable[Result]:
        """
        Get results to show when there is no query input (on startup or when you delete the query)
        Only implemented for AppMode.
        """
        return []

    def get_fallback_results(self, _query_str: str) -> Iterable[Result]:
        return []

    @abstractmethod
    def activate_result(
        self,
        action_id: str,
        result: Result,
        query: Query,
        callback: Callable[[EffectMessage], None],
    ) -> None:
        """
        Called when a result is activated.

        :param action_id: The ID of the action to perform, or empty string for the default action
        :param result: The result that was activated
        :param query: The current query
        :param callback: Callback to return the action or new results
        """
        ...
