# coding: utf-8

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

from logging import Logger
from contextlib import contextmanager
from cached_property import cached_property
from typing import AnyStr, Dict, List, Union, Any, Optional, overload, Pattern, Type, Iterable, Sequence, ContextManager

from infra.nanny.nanny_services_rest.nanny_services_rest.client import ServiceRepoClient

from .cms_snapshot_info import CmsSnapshotInfo
from .enums import AllocationType, ServiceSummaryStatus
from .resource import SandboxFile, StaticFile, UrlFile, TemplateSetFile
from .shard_resource import RegisteredShard, SandboxShard, SandboxShardmap
from .service_mutable_proxy import NannyServiceBaseRuntimeProxy, NannyServiceBaseInfoProxy
from .service_mutable_proxy.instance_spec import ReadonlyInstanceSpec
from .recipe import AlemateRecipe

InfoAttributes = Dict[AnyStr, Union[List, int, AnyStr, Dict[AnyStr, Any]]]
RuntimeAttributes = Dict[AnyStr, Dict[AnyStr: Union[AnyStr, List, Dict[AnyStr, Any]]]]
AuthAttributes = Dict[AnyStr, Dict[AnyStr: List]]

class NannyServiceBase(object):
    LOGGER: Logger
    _NANNY: ServiceRepoClient
    _attrs_regexp: Pattern
    _resource_type_mapping: Dict[AnyStr, Type]
    _cached_property_map: Dict[str, Iterable[str]]

    @classmethod
    def initialize_nanny_client(cls): ...

    def __init__(
            self, name: AnyStr,
            runtime_attrs: Optional[Dict[AnyStr,Union[Dict, AnyStr, RuntimeAttributes]]] = None,
            info_attrs: Optional[Dict[AnyStr,Union[Dict, AnyStr, InfoAttributes]]] = None,
            auth_attrs: Optional[Dict[AnyStr, Union[Dict, AnyStr, AuthAttributes]]] = None,
            history_runtime_attrs: Optional[Dict[AnyStr,Union[Dict, AnyStr]]] = None
    ):
        self.initialize_nanny_client()
        self.name = name
        self._info_attrs = info_attrs
        self._runtime_attrs = runtime_attrs
        self._auth_attrs = auth_attrs
        self._history_runtime_attrs = history_runtime_attrs

    @overload
    def __eq__(self, other: NannyServiceBase) -> bool: ...

    @overload
    def __eq__(self, other: Any) -> NotImplemented: ...

    def __ne__(self, other):
        return not self.__eq__(other)

    def __hash__(self) -> int: ...

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

    @property
    def info_attrs(self) -> InfoAttributes: ...
    @property
    def runtime_attrs(self) -> RuntimeAttributes: ...
    @property
    def auth_attrs(self) -> AuthAttributes: ...
    @property
    def history_runtime_attrs(self) -> Sequence[RuntimeAttributes]: ...

    @property
    def cms_snapshots_info(self) -> List[CmsSnapshotInfo]:...

    def get_info_attrs(self) -> InfoAttributes: ...
    def get_runtime_attrs(self) -> RuntimeAttributes: ...
    def get_auth_attrs(self) -> AuthAttributes: ...

    def set_info_attrs(self, content: InfoAttributes, comment: AnyStr) -> InfoAttributes: ...
    def set_runtime_attrs(self, content: RuntimeAttributes, comment: AnyStr, ticket_id: Optional[AnyStr] = None) -> RuntimeAttributes: ...
    def set_auth_attrs(self, content: AuthAttributes, comment: AnyStr) -> AuthAttributes: ...

    def invalidate_cache(self, kind: AnyStr) -> None:
        """
        :param kind: one of {'runtime', 'info', 'auth'} to clear corresponding attributes caches
        """
    ...

    @contextmanager
    def info_attrs_transaction(self, comment: AnyStr) -> ContextManager[NannyServiceBaseInfoProxy]:  ...

    @contextmanager
    def runtime_attrs_transaction(self, comment: AnyStr, ticket: Optional[AnyStr] = None) -> ContextManager[NannyServiceBaseRuntimeProxy]:  ...

    # Runtime attributes
    @property
    def allocation_type(self) -> AllocationType: ...

    @property
    def resources(self) -> Dict[AnyStr, Dict[AnyStr, Union[
        Sequence[SandboxFile], Sequence[StaticFile], Sequence[UrlFile], Sequence[TemplateSetFile], Dict]]]: ...

    # Specific resources
    @property
    def sandbox_files(self) -> Dict[AnyStr, SandboxFile]: ...

    @property
    def static_files(self) -> Dict[AnyStr, StaticFile]: ...

    @property
    def url_files(self) -> Dict[AnyStr, UrlFile]: ...

    @property
    def template_set_files(self) -> Dict[AnyStr, TemplateSetFile]: ...

    @property
    def shard(self) -> Union[None, RegisteredShard, SandboxShard, SandboxShardmap]: ...

    @property
    def files(self) -> Dict[AnyStr, Union[SandboxFile, StaticFile, UrlFile, TemplateSetFile, Dict]]: ...

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

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

    @cached_property
    def instance_spec(self) -> ReadonlyInstanceSpec: ...

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

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

    @property
    def current_state_summary_status(self) -> ServiceSummaryStatus: ...

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

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

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

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

    def set_shard(self, shard: Union[RegisteredShard, SandboxShard, SandboxShardmap], snapshot_comment: AnyStr, ticket_id: Optional[AnyStr] = None): ...
