from infra.awacs.proto import api_pb2, api_stub
from saas.library.python.nanny_proto.rpc_client_base import NannyRpcClientBase
from saas.library.python.deploy_manager_api.client import DeployManagerApiClient
from google.protobuf import json_format
from saas.library.python.awacs import helpers


class BalancerManager(NannyRpcClientBase):
    _RPC_URL = "https://awacs.yandex-team.ru/api/"
    _OAUTH_SLUG = 'awacs'
    _API_STUB = api_stub.BalancerServiceStub
    _API_DM = None

    @classmethod
    def init_dm_client(cls):
        if cls._API_DM is None:
            cls._API_DM = DeployManagerApiClient()

    def __init__(self):
        super(NannyRpcClientBase, self).__init__()
        self._init_client()
        self.init_dm_client()

    @staticmethod
    def _default_balancer_request_data(ctype, cluster, namespace_id, network_macro, author='', comment='', balancer_ctype=None,
                                       nanny_service_id_slug='not-used-yet', instance_count=2, preset_type='MICRO'):
        if balancer_ctype is None or balancer_ctype == 'prod':
            balancer_postfix = ""
        else:
            balancer_postfix = balancer_ctype + "_"
        request_data = {
            'meta': {
                'id': '{}.saas.yandex.net_{}{}'.format(ctype.lower().replace('_', '-'), balancer_postfix, cluster.lower()),
                'namespace_id': namespace_id,
                'author': author,
                'comment': comment,
                'auth': {
                    'type': "STAFF",
                    'staff': {
                        'owners': {
                            "group_ids": ["29985", ],
                        }
                    }
                },
                'location': {
                    'type': 'YP_CLUSTER',
                    'yp_cluster': cluster.upper(),
                }
            },
            'order': {
                'abc_service_id': 664,
                'cert_id': namespace_id,
                'allocation_request': {
                    'location': cluster.upper(),
                    'network_macro': str(network_macro),
                    'nanny_service_id_slug': nanny_service_id_slug,
                    "preset": {
                        'type': preset_type,
                        'instances_count': instance_count,
                    },
                }
            }
        }
        return request_data

    def create_balancer(self, ctype, cluster, namespace_id, network_macro, author='', comment='', balancer_ctype=None, nanny_service_id_slug='not-used-yet',
                        instance_count=2, preset_type='MICRO', advanced_settings=None):
        request_data = self._default_balancer_request_data(ctype, cluster, namespace_id, network_macro, author, comment, balancer_ctype, nanny_service_id_slug, instance_count, preset_type)
        req_pb = api_pb2.CreateBalancerRequest()
        if advanced_settings is not None:
            request_data.update(advanced_settings)
        json_format.ParseDict(request_data, req_pb)
        return self._CLIENT.create_balancer(req_pb)

    def get_balancer(self, ctype, balancer_id):
        req_pb = api_pb2.GetBalancerRequest()
        req_pb.id = balancer_id
        req_pb.namespace_id = helpers.namespace_id_from_ctype(ctype)
        return self._CLIENT.get_balancer(req_pb)

    def list_balancers(self, ctype):
        req_pb = api_pb2.ListBalancersRequest()
        req_pb.namespace_id = helpers.namespace_id_from_ctype(ctype)
        return self._CLIENT.list_balancers(req_pb)

    def remove_balancer(self, ctype, balancer_id):
        balancer = self.get_balancer(ctype, balancer_id).balancer
        geo = balancer.meta.location.yp_cluster.lower()
        ctype = balancer.spec.config_transport.nanny_static_file.instance_tags.ctype
        itype = balancer.spec.config_transport.nanny_static_file.instance_tags.itype
        prj = balancer.spec.config_transport.nanny_static_file.instance_tags.prj
        if helpers.mean_rps_last_30m(report='service_total', ctype=ctype, itype=itype, prj=prj, geo=geo) == 0:
            return self._remove_balancer(ctype, balancer_id)

    def _remove_balancer(self, ctype, balancer_id):
        balancer = self.get_balancer(balancer_id, helpers.namespace_id_from_ctype(ctype)).balancer
        req_pb = api_pb2.RemoveBalancerRequest()
        req_pb.id = balancer.meta.id
        req_pb.version = balancer.meta.version
        req_pb.namespace_id = balancer.meta.namespace_id
        req_pb.mode = 1
        self._CLIENT.remove_balancer(req_pb)
