# coding: utf-8

from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

import six
import requests
from logging import Logger
from retrying import retry
from cached_property import cached_property, cached_property_with_ttl
from typing import AnyStr, Dict, List, Union, Any, Optional, Pattern, FrozenSet, Hashable

from saas.library.python.singleton import Singleton
from saas.library.python.gencfg import GencfgGroup
from saas.library.python.common_functions import connection_error


class Slot(six.with_metaclass(Singleton)):
    SLOT_ID_REGEXP: Pattern
    RTYSERVER_COMMANDS: FrozenSet[str]
    _RETRY_CONF: Dict[AnyStr: Union[int, bool]]
    LOGGER: Logger

    @classmethod
    def _get_instance_id(cls, args: List, kwargs: Dict) -> Hashable: ...

    @classmethod
    def _extra_actions(cls, instance: Slot, args: List, kwargs: Dict) -> None: ...

    def __init__(
            self,
            host: AnyStr,
            port: int = 80,
            physical_host: Optional[AnyStr] = None,
            control_port_offset: int = 3,
            geo: Optional[AnyStr] = None,
            shards_min: Optional[int] = None,
            shards_max: Optional[int] = None
    ):
        self.host = host
        self.port = int(port)
        self.geo = geo
        self.control_port = self.port + int(control_port_offset)
        self._physical_host = physical_host
        self._info_server = None
        self._shards_min = shards_min
        self._shards_max = shards_max
        self.session = requests.session()

        self._id = '{}:{}'.format(self.host, self.port)

    @classmethod
    def from_id(
            cls,
            slot_id: AnyStr,
            physical_host: Optional[AnyStr] = None,
            control_port_offset: int = 3,
            geo: Optional[AnyStr] = None,
            shards_min: Optional[int] = None,
            shards_max: Optional[int] = None
    ) -> Slot: ...

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

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

    @property
    def instance_topology(self) -> Optional[GencfgGroup]: ...

    @property
    def interval(self) -> Optional[Dict[str, int]]: ...

    @property
    def shards_min(self) -> Optional[int]: ...

    @property
    def shards_max(self) -> Optional[int]: ...

    @interval.setter
    def interval(self, value: Dict[str, int]): ...

    @property
    def physical_host(self) -> Optional[str]: ...

    @cached_property
    def _this_server_commands(self) -> FrozenSet[str]: ...

    def _get_this_server_commands(self) -> FrozenSet[str]: ...

    def __getattr__(self, item: AnyStr) -> Any: ...

    @retry(retry_on_exception=connection_error, **_RETRY_CONF)
    def _make_request(self, path: AnyStr = '/', **kwargs) -> requests.Response: ...

    @retry(**_RETRY_CONF)
    def _request_with_retry(self, path: AnyStr = '/', **kwargs) -> requests.Response: ...

    def make_request(self, path: AnyStr = '/', **kwargs) -> requests.Response: ...

    def send_command(self, command: AnyStr, params: Optional[Dict[AnyStr, Any]] = None) -> requests.Response: ...

    def execute_command(self, command: AnyStr, request_params: Optional[Dict[AnyStr, Any]] = None, retryable: bool = False, **kwargs) -> requests.Response: ...

    def cmd_shutdown(self):
        return self.shutdown()

    def get_tass(self, retryable: bool = False) -> dict: ...

    def get_metrics(self, retryable: bool = False) -> str: ...

    def get_full_status(self, retryable: bool = False) -> str: ...

    def get_brief_status(self, retryable: bool = False) -> str: ...

    def detach(self, params: Optional[Dict[AnyStr, Any]] = None) -> requests.Response: ...

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

    def deploy(self, wait: int = 300) -> bool: ...

    def restart(self, timeout: int = 300) -> bool: ...

    def safe_shutdown(self) -> bool: ...

    def wait_up(self, timeout: int = 300) -> bool: ...

    @cached_property_with_ttl(30)
    def info_server(self) -> Dict[str, Union[str, Dict]]: ...

    def enable_search(self) -> None: ...

    def enable_indexing(self) -> None: ...

    @cached_property_with_ttl(30)
    def controller_config(self) -> Dict[str, Union[str, List[Dict[str, str]]]]: ...

    @property
    def dm_options(self) -> Dict[str, str]: ...

    def detect_cpu(self) -> Optional[str]: ...
