# coding: utf-8

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

import logging
import argparse

from .client import DeployManagerApiClient

LOGGER = logging.getLogger(__name__)


def saas_service_iterator(saas_ctypes=None, saas_services=None, nanny_services=None, gencfg_groups=None, extra_filter=lambda s: True):
    # type: (List[AnyStr], List[AnyStr], List[AnyStr], List[AnyStr], Callable) -> Iterable[s_service.SaasService]
    """
    :param saas_ctypes: List of saas ctypes ex: ['stable', 'stable_kv']
    :param saas_services: List os saas service names, ex: ['sovetnik_filter', 'turbo_ecommerce']
    :param nanny_services: List of nanny service names, ex: ['saas_cloud_turbo_ecommerce', ]
    :param gencfg_groups: List of gencfg group names
    :param extra_filter: Extra filter lambda(SaasService) -> bool
    """
    dm = DeployManagerApiClient()
    ctypes = saas_ctypes if saas_ctypes else dm.stable_ctypes
    nanny_services = set(nanny_services) if nanny_services else None
    gencfg_groups = set(gencfg_groups) if gencfg_groups else None
    LOGGER.info('Iterating over saas services, filters: ctype: %s, service: %s, nanny_service: %s, gencfg: %s',
                ctypes, saas_services, nanny_services, gencfg_groups)

    for ctype in ctypes:
        def filter_function(s):  # TODO: Make it lasy && add tests
            return (saas_services and s.name in saas_services) or \
                   (nanny_services and nanny_services.intersection(s.nanny_services)) or \
                   (gencfg_groups and gencfg_groups.intersection(s.gencfg_groups_names))

        ctype_services = dm.get_services(ctype)
        no_filters = not (saas_services or nanny_services or gencfg_groups)
        for saas_service in ctype_services:
            if (no_filters or filter_function(saas_service)) and extra_filter(saas_service):
                yield saas_service
            else:
                continue


def get_unique_service(saas_ctype=None, saas_service_name=None, nanny_service=None, gencfg_group=None):
    # type: (AnyStr, AnyStr, AnyStr, AnyStr) -> s_service.SaasService
    saas_ctypes = {saas_ctype, } if saas_ctype else None
    saas_services = [saas_service_name, ] if saas_service_name else None
    nanny_services = [nanny_service, ] if nanny_service else None
    gencfg_groups = [gencfg_group, ] if gencfg_group else None
    matching_services = list(saas_service_iterator(saas_ctypes, saas_services, nanny_services, gencfg_groups))
    if len(matching_services) > 1:
        LOGGER.error('More than one saas service match with filters: %s', matching_services)
        raise RuntimeError('Too many services')
    elif not matching_services:
        LOGGER.error(
            'No services matched filters: ctype: %s, service: %s, nanny_service: %s, gencfg: %s', saas_ctype, saas_service_name, nanny_service, gencfg_group
        )
        raise RuntimeError('No services')

    return matching_services[0]


def get_saas_entity_arg_parser():
    parser = argparse.ArgumentParser(add_help=False)
    arg_group = parser.add_argument_group('saas entity')
    arg_group.add_argument('--saas-ctype',    help='SaaS ctype', choices=DeployManagerApiClient().ctypes)
    arg_group.add_argument('--saas-service',  help='SaaS service name')
    arg_group.add_argument('--nanny-service', help='Match saas service by nanny service')
    arg_group.add_argument('--gencfg-group',  help='Match saas service by gencfg group')
    return parser


def get_saas_service_from_args(args):
    saas_ctype = args.saas_ctype or None
    saas_service = args.saas_service or None
    nanny_service = args.nanny_service or None
    gencfg_group = args.gencfg_group or None
    if not any([saas_ctype, saas_service, nanny_service, gencfg_group]):
        raise ValueError('Set at least one filter to determine service')
    return get_unique_service(saas_ctype, saas_service, nanny_service, gencfg_group)
