"""
This module defines the Events interface for handling various events in the agent
"""
from typing import Protocol, Callable, Awaitable, Optional, List
from .payload import AgentEventPayload, EventFile
from .context import AgentContext


class AgentEvents(Protocol):
    """
    Interface for handling various events in the agent.
    """

    def emitQueryCreated(self, event: AgentEventPayload, files: Optional[List[EventFile]] = None) -> Awaitable[None]:
        """
        Emits an event when a query is created.

        Args:
            event: An object containing the data related to the created query.
            files: Optional list of files to include with the event.
        """
        ...

    def emitQueryCompleted(self, event: AgentEventPayload, files: Optional[List[EventFile]] = None) -> Awaitable[None]:
        """
        Emits an event when a query is successfully completed.

        Args:
            event: An object containing the data related to the completed query.
            files: Optional list of files to include with the event.
        """
        ...

    def emitQueryFailed(self, event: AgentEventPayload, files: Optional[List[EventFile]] = None) -> Awaitable[None]:
        """
        Emits an event when a query fails.

        Args:
            event: An object containing the data related to the failed query.
            files: Optional list of files to include with the event.
        """
        ...

    def emitEventCreated(self, event: AgentEventPayload, files: Optional[List[EventFile]] = None) -> Awaitable[None]:
        """
        Emits an event when a generic event is created.

        Args:
            event: An object containing the data related to the created event.
            files: Optional list of files to include with the event.
        """
        ...


class AgentEventsImpl:
    """
    Concrete implementation of AgentEvents.
    """

    def __init__(self, context: AgentContext, emit: Callable[[AgentContext, str, AgentEventPayload], Awaitable[None]]):
        self.context = context
        self.emit = emit

    async def emitQueryCreated(self, event: AgentEventPayload, files: Optional[List[EventFile]] = None) -> None:
        await self.emit(self.context, "queryCreated", event, files=files)

    async def emitQueryCompleted(self, event: AgentEventPayload, files: Optional[List[EventFile]] = None) -> None:
        await self.emit(self.context, "queryCompleted", event, files=files)

    async def emitQueryFailed(self, event: AgentEventPayload, files: Optional[List[EventFile]] = None) -> None:
        await self.emit(self.context, "queryFailed", event, files=files)

    async def emitEventCreated(self, event: AgentEventPayload, files: Optional[List[EventFile]] = None) -> None:
        await self.emit(self.context, "eventCreated", event, files=files) 