from typing import Any, AnyStr, List, Dict, Iterable, Iterator, Callable, Optional
from logging import Logger
import sandbox.common.types.task as common_task_types

from saas.library.python.common_functions import linear_delay_generator
from saas.library.python.sandbox.resource import SandboxResource

from sandbox.common.rest import Client

TaskInfo = Dict[AnyStr, Any]
ResourceInfo = Dict[AnyStr, Any]

class SandboxTask(object):
    LOGGER: Logger
    FINAL_STATES = common_task_types.Status.Group.BREAK + common_task_types.Status.Group.FINISH

    def __init__(self, sandbox: Client, task_id: int):
        self.sandbox_client: Client = sandbox
        self.id: int = task_id
        self._info: Optional[dict] = ...
        self._resources: List = ...

    def __repr__(self) -> str: ...

    @classmethod
    def from_task_info(cls, sandbox: Client, task_info: TaskInfo) -> SandboxTask: ...

    def update_info(self):
        """Update self from server"""
        ...

    @property
    def status(self) -> str: ...

    def _get_raw_resources(self) -> List[ResourceInfo]: ...

    @property
    def resources(self) -> Iterable[SandboxResource]: ...

    @property
    def ready_resources(self) -> Iterable[SandboxResource]: ...

    def get_single_resource(self, selector_function: Callable[[SandboxResource], bool]) -> SandboxResource:
        """
        Get single resource for witch selector_function is true. If no resources, or more than one resources match raise ValueError
        """

    @property
    def context(self) -> Dict[AnyStr, Any]: ...

    @property
    def finished(self) -> bool: ...

    @property
    def finished_ok(self) -> bool: ...

    def start(self): ...

    def wait(self, delay_generator: Callable[[float], Iterator[float]]=linear_delay_generator(3)) -> SandboxTask:
        """
        Wait for self.finished_ok become true and return self. If self.finished is true and self.finished_ok is false raise SandboxTaskFailure
        """
        ...
