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

log = logging.getLogger(__name__)


class DesignateException(Exception):

    _msg = "Designate module exception occured."

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


class NoDesignateEndpoint(DesignateException):
    _msg = "Designate endpoint not found in keystone catalog."


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


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


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

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


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

    def __init__(self, resource, name, **kwargs):
        super(DesignateException, 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 = 'dns'
    config = os_client_config.OpenStackConfig()
    cloud = config.get_one_cloud(cloud_name)
    adapter = cloud.get_session_client(service_type)
    adapter.version = 'v2'
    try:
        access_info = adapter.session.auth.get_access(adapter.session)
        endpoints = access_info.service_catalog.get_endpoints()
    except (AttributeError, ValueError):
        e = NoAuthPluginConfigured()
        log.exception('%s' % e)
        raise e
    if service_type not in endpoints:
        if not service_type:
            e = NoDesignateEndpoint()
            log.error('%s' % e)
            raise e
    return adapter


def send(method, microversion_header=None):
    def wrap(func):
        def wrapped_f(*args, **kwargs):
            headers = kwargs.pop('headers', {})
            if kwargs.get('microversion'):
                headers.setdefault(microversion_header,
                                   kwargs.get('microversion'))
            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, json = func(*args, **kwargs)
            if json:
                response = getattr(adapter, method)(url, headers=headers,
                                                    json=json)
            else:
                response = getattr(adapter, method)(url, headers=headers)
            if not response.content:
                return {}
            try:
                resp = response.json()
            except:
                resp = response.content
            return resp
        return wrapped_f
    return wrap
