# Generated by sila2.code_generator; sila2.__version__: 0.10.3
from __future__ import annotations

from abc import ABC, abstractmethod
from queue import Queue
from typing import TYPE_CHECKING, List, Optional, Union

from sila2.server import FeatureImplementationBase, MetadataDict

from .pausecontroller_types import UUID, Pause_Responses, Resume_Responses

if TYPE_CHECKING:

    from ...server import Server


class PauseControllerBase(FeatureImplementationBase, ABC):
    parent_server: Server

    _PausedCommands_producer_queue: Queue[Union[List[UUID], Exception]]
    _PausedCommands_current_value: List[UUID]

    def __init__(self, parent_server: Server):
        """
            Allows to pause or resume a currently running Observable Command. Pausing is the act of stopping the
        progress of the desired intent of a Command with the option of continuing the execution when resuming.

        A SiLA Client SHOULD be able to pause or resume the Observable Commands at any time. Not every Observable Command
        might support this Feature. If not, an "OperationNotSupported" Execution Error MUST be thrown.
        """
        super().__init__(parent_server=parent_server)

        self._PausedCommands_producer_queue = Queue()

    def update_PausedCommands(self, PausedCommands: List[UUID], queue: Optional[Queue[List[UUID]]] = None) -> None:
        """
        A List of Command Execution UUID that are in a paused state.

        This method updates the observable property 'PausedCommands'.

        :param queue: The queue to send updates to. If None, the default Queue will be used.
        """
        if queue is None:
            queue = self._PausedCommands_producer_queue
            self._PausedCommands_current_value = PausedCommands
        queue.put(PausedCommands)

    def PausedCommands_on_subscription(self, *, metadata: MetadataDict) -> Optional[Queue[List[UUID]]]:
        """
        A List of Command Execution UUID that are in a paused state.

        This method is called when a client subscribes to the observable property 'PausedCommands'

        :param metadata: The SiLA Client Metadata attached to the call
        :return: Optional `Queue` that should be used for updating this property.
            If None, the default Queue will be used.
        """
        pass

    def abort_PausedCommands_subscriptions(self, error: Exception, queue: Optional[Queue[List[UUID]]] = None) -> None:
        """
        A List of Command Execution UUID that are in a paused state.

        This method aborts subscriptions to the observable property 'PausedCommands'.

        :param error: The Exception to be sent to the subscribing client.
            If it is no DefinedExecutionError or UndefinedExecutionError, it will be wrapped in an UndefinedExecutionError.
        :param queue: The queue to abort. If None, the default Queue will be used.
        """
        if queue is None:
            queue = self._PausedCommands_producer_queue
        queue.put(error)

    @property
    def current_PausedCommands(self) -> List[UUID]:
        try:
            return self._PausedCommands_current_value
        except AttributeError:
            raise AttributeError("Observable property PausedCommands has never been set")

    @abstractmethod
    def Pause(self, CommandExecutionUUID: UUID, *, metadata: MetadataDict) -> Pause_Responses:
        """
          Pause the Command execution. The Command can then be resumed again. The Command Execution Status of the
        Observable Command MUST not be affected.


          :param CommandExecutionUUID: The Command Execution UUID according to the SiLA Standard.

          :param metadata: The SiLA Client Metadata attached to the call

        """
        pass

    @abstractmethod
    def Resume(self, CommandExecutionUUID: UUID, *, metadata: MetadataDict) -> Resume_Responses:
        """
        Resume the Command after it has been paused.


        :param CommandExecutionUUID: The Command Execution UUID according to the SiLA Standard.

        :param metadata: The SiLA Client Metadata attached to the call

        """
        pass
