import logging
import time
from uuid import UUID

try:
    import os_client_config
except ImportError:
    os_client_config = None
from salt import exceptions

log = logging.getLogger(__name__)


class GnocchiException(Exception):

    _msg = "Gnocchi module exception occured."

    def __init__(self, message=None, **kwargs):
        super(GnocchiException, self).__init__(message or self._msg)


class NoGnocchiEndpoint(GnocchiException):
    _msg = "Gnocchi endpoint not found in keystone catalog."


class NoAuthPluginConfigured(GnocchiException):
    _msg = ("You are using keystoneauth auth plugin that does not support "
            "fetching endpoint list from token (noauth or admin_token).")


class NoCredentials(GnocchiException):
    _msg = "Please provide cloud name present in clouds.yaml."


class ResourceNotFound(GnocchiException):
    _msg = "Uniq resource: {resource} with name: {name} not found."

    def __init__(self, resource, name, **kwargs):
        super(GnocchiException, self).__init__(
            self._msg.format(resource=resource, name=name))


class MultipleResourcesFound(GnocchiException):
    _msg = "Multiple resource: {resource} with name: {name} found."

    def __init__(self, resource, name, **kwargs):
        super(GnocchiException, self).__init__(
            self._msg.format(resource=resource, name=name))


def get_raw_client(cloud_name):
    if not os_client_config:
        raise exceptions.SaltInvocationError(
            "Cannot load os-client-config. Please check your environment "
            "configuration.")
    service_type = 'metric'
    config = os_client_config.OpenStackConfig()
    cloud = config.get_one_cloud(cloud_name)
    api_version = '1'
    try:
        # NOTE(pas-ha) for Queens and later,
        # 'version' kwarg in absent for Pike and older
        adapter = cloud.get_session_client(service_type, version=api_version)
    except TypeError:
        adapter = cloud.get_session_client(service_type)
        adapter.version = api_version
    try:
        access_info = adapter.session.auth.get_access(adapter.session)
        endpoints = access_info.service_catalog.get_endpoints()
    except (AttributeError, ValueError) as exc:
        log.exception('%s' % exc)
        e = NoAuthPluginConfigured()
        log.exception('%s' % e)
        raise e
    if service_type not in endpoints:
        if not service_type:
            e = NoGnocchiEndpoint()
            log.error('%s' % e)
            raise e
    return adapter


def send(method):
    def wrap(func):
        def wrapped_f(*args, **kwargs):
            connect_retries = 30
            connect_retry_delay = 1
            cloud_name = kwargs.pop('cloud_name')
            if not cloud_name:
                e = NoCredentials()
                log.error('%s' % e)
                raise e
            adapter = get_raw_client(cloud_name)
            # Remove salt internal kwargs
            kwarg_keys = list(kwargs.keys())
            for k in kwarg_keys:
                if k.startswith('__'):
                    kwargs.pop(k)
            url, request_kwargs = func(*args, **kwargs)
            response = None
            for i in range(connect_retries):
                try:
                    response = getattr(adapter, method)(
                        url, connect_retries=connect_retries,
                        **request_kwargs)
                except Exception as e:
                    if not hasattr(e, 'http_status') or (
                            e.http_status >= 500 or e.http_status == 0):
                        msg = ("Got retriable exception when contacting "
                               "Gnocchi API. Sleeping for %s seconds. "
                               "Attepmpts %s of %s")
                        log.error(msg % (connect_retry_delay, i,
                                         connect_retries))
                        time.sleep(connect_retry_delay)
                        continue
                    else:
                        raise
                break
            try:
                resp = response.json()
            except ValueError:
                resp = response.content
            return resp
        return wrapped_f
    return wrap


def _check_uuid(val):
    try:
        return str(UUID(val)).replace('-', '') == val.replace('-', '')
    except (TypeError, ValueError, AttributeError):
        return False


def get_by_name_or_uuid(resource_list, resp_key):
    def wrap(func):
        def wrapped_f(*args, **kwargs):
            if 'name' in kwargs:
                ref = kwargs.pop('name', None)
                start_arg = 0
            else:
                start_arg = 1
                ref = args[0]
            if _check_uuid(ref):
                uuid = ref
            else:
                # Then we have name not uuid
                cloud_name = kwargs['cloud_name']
                resp = resource_list(
                    name=ref, cloud_name=cloud_name)[resp_key]
                if len(resp) == 0:
                    raise ResourceNotFound(resp_key, ref)
                elif len(resp) > 1:
                    raise MultipleResourcesFound(resp_key, ref)
                uuid = resp[0]['id']
            return func(uuid, *args[start_arg:], **kwargs)
        return wrapped_f
    return wrap
