"""
Management of Cinder resources
"""

import ast
import logging

log = logging.getLogger(__name__)


def __virtual__():
    return 'cinderv3' if 'cinderv3.volume_list' in __salt__ else False  # noqa


def _cinder_call(fname, *args, **kwargs):
    if __opts__.get('test') and not (fname.find('_list') > 0 or fname.find('_get_') > 0):
        return {'changes': 'cinderv3 state {} with options {} {} will be executed'.format(fname, args, kwargs),
                'result': None}
    else:
        return __salt__['cinderv3.{}'.format(fname)](*args, **kwargs)


def _resource_present(resource, name, cloud_name, **kwargs):
    try:
        method_name = '{}_get_details'.format(resource)
        exact_resource = _cinder_call(
            method_name, name, cloud_name=cloud_name, **kwargs
        )[resource]
    except Exception as e:
        if 'ResourceNotFound' in repr(e):
            try:
                method_name = '{}_create'.format(resource)
                resp = _cinder_call(
                    method_name, name=name, cloud_name=cloud_name, **kwargs
                )
            except Exception as e:
                log.exception('Cinder {0} create failed with {1}'.
                    format(resource, e))
                return _failed('create', name, resource)
            return _succeeded('create', name, resource, resp)
        elif 'MultipleResourcesFound' in repr(e):
            return _failed('find', name, resource)
        else:
            raise

    to_update = {}
    if to_update:
        for key in kwargs:
            if key not in exact_resource or kwargs[key] != exact_resource[key]:
                to_update[key] = kwargs[key]
        try:
            method_name = '{}_update'.format(resource)
            resp = _cinder_call(
                method_name, name, cloud_name=cloud_name, **to_update
            )
        except Exception as e:
            log.exception('Cinder {0} update failed with {1}'.format(resource, e))
            return _failed('update', name, resource)
        return _succeeded('update', name, resource, resp)
    return _succeeded('no_changes', name, resource)


def _resource_absent(resource, name, cloud_name, connection_params=None):
    try:
        method_name = '{}_get_details'.format(resource)
        _cinder_call(
            method_name, name, cloud_name=cloud_name,
            connection_params=connection_params
        )[resource]
    except Exception as e:
        if 'ResourceNotFound' in repr(e):
            return _succeeded('absent', name, resource)
        if 'MultipleResourcesFound' in repr(e):
            return _failed('find', name, resource)
    try:
        method_name = '{}_delete'.format(resource)
        _cinder_call(
            method_name, name, cloud_name=cloud_name,
            connection_params=connection_params
        )
    except Exception as e:
        log.error('Cinder delete {0} failed with {1}'.format(resource, e))
        return _failed('delete', name, resource)
    return _succeeded('delete', name, resource)


def service_enabled(name, binary, cloud_name, connection_params=None):
    """Ensures that the service is enabled on the host

    :param name:              name of a host where service is running
    :param binary:            name of the service have to be run
    :param connection_params: dictionary with salt internal connection params
    """
    changes = {}
    ret = []

    services = _cinder_call('service_list', host=name, binary=binary, cloud_name=cloud_name,
                            connection_params=connection_params)['services']

    disabled_service = [s for s in services if s['status'] == 'disabled']

    if len(disabled_service):
        for service in disabled_service:
            changes = _cinder_call('service_update', service['host'], binary, 'enable', cloud_name=cloud_name,
                                   connection_params=connection_params)
            ret.append(changes)
        return _succeeded('update', name, binary, {'changes':ret})
    return  _succeeded('no_changes', name, binary)


def service_disabled(name, binary, cloud_name, disabled_reason=None, connection_params=None):
    """Ensures that the service is disabled on the host

    :param name:    name of a host where service is running
    :param binary:  name of the service have to be disabled
    :param connection_params: dictionary with salt internal connection params
    """
    kwargs = {}
    ret = []

    if disabled_reason:
        kwargs['disabled_reason'] = disabled_reason

    services = _cinder_call('service_list', host=name, binary=binary, cloud_name=cloud_name,
                            connection_params=connection_params)['services']

    enabled_services = [s for s in services if s['status'] == 'enabled']

    if len(enabled_services):
        for service in enabled_services:
            changes = _cinder_call('service_update', service['host'], binary, 'disable',
                                   cloud_name=cloud_name, connection_params=connection_params,
                                   **kwargs)
            ret.append(changes)
        return _succeeded('update', name, binary, {'changes':ret})
    return  _succeeded('no_changes', name, binary)


def volume_type_present(name, cloud_name, **kwargs):
    return _resource_present('volume_type', name, cloud_name, **kwargs)


def volume_type_absent(name, cloud_name, connection_params=None):
    return _resource_absent('volume_type', name, cloud_name, connection_params)


def volume_present(name, cloud_name, size, **kwargs):
    kwargs.update({
        'size': size,
    })
    return _resource_present('volume', name, cloud_name, **kwargs)


def volume_absent(name, cloud_name, connection_params=None):
    return _resource_absent('volume', name, cloud_name, connection_params)


def volume_type_key_present(name=None, key=None, value=None, cloud_name=None,
                            connection_params=None):
    """
    Ensures that the extra specs are present on a volume type.
    """
    keys = "{u'" + key + "': u'" + value + "'}"
    keys = ast.literal_eval(keys)
    signal_create = _cinder_call('keys_volume_type_set', name, keys=keys,
                                 cloud_name=cloud_name,
                                 connection_params=connection_params)
    if signal_create["result"] is True:
        ret = {
            'name': name,
            'changes': keys,
            'result': True,
            'comment': 'Volume type "{0}" was updated'.format(name)
        }
    elif signal_create["result"] is None:
        ret = {
            'name': name,
            'changes': {},
            'result': None,
            'comment': 'Volume type "{0}" will be updated'.format(name)
        }
    else:
        ret = {
            'name': name,
            'changes': {},
            'result': False,
            'comment': signal_create.get("comment")
        }
    return ret

def _succeeded(op, name, resource, changes=None):
    msg_map = {
        'create': '{0} {1} created',
        'delete': '{0} {1} removed',
        'update': '{0} {1} updated',
        'no_changes': '{0} {1} is in desired state',
        'absent': '{0} {1} not present',
        'resources_moved': '{1} resources were moved from {0}',
    }
    changes_dict = {
        'name': name,
        'result': None if __opts__.get('test') else True,
        'comment': msg_map[op].format(resource, name),
        'changes': changes or {},
    }
    return changes_dict

def _failed(op, name, resource):
    msg_map = {
        'create': '{0} {1} failed to create',
        'delete': '{0} {1} failed to delete',
        'update': '{0} {1} failed to update',
        'find': '{0} {1} found multiple {0}',
        'resources_moved': 'failed to move {1} from {0}',
    }
    changes_dict = {
        'name': name,
        'result': False,
        'comment': msg_map[op].format(resource, name),
        'changes': {},
    }
    return changes_dict
