# -*- coding: utf-8 -*-
'''
The Salt Cloud Runner
=====================

This runner wraps the functionality of salt cloud making salt cloud routines
available to all internal apis via the runner system
'''
from __future__ import absolute_import, print_function, unicode_literals

# Import python libs
import logging
import os

# Import Salt libs
import salt.cloud
import salt.utils.args
from salt.exceptions import SaltCloudConfigError

# Get logging started
log = logging.getLogger(__name__)


def _get_client():
    '''
    Return cloud client
    '''
    client = salt.cloud.CloudClient(
            os.path.join(os.path.dirname(__opts__['conf_file']), 'cloud')
            )
    return client


def list_sizes(provider='all'):
    '''
    List cloud provider sizes for the given providers
    '''
    client = _get_client()
    sizes = client.list_sizes(provider)
    return sizes


def list_images(provider='all'):
    '''
    List cloud provider images for the given providers
    '''
    client = _get_client()
    images = client.list_images(provider)
    return images


def list_locations(provider='all'):
    '''
    List cloud provider sizes for the given providers
    '''
    client = _get_client()
    locations = client.list_locations(provider)
    return locations


def query(query_type='list_nodes'):
    '''
    List cloud provider data for all providers
    '''
    client = _get_client()
    info = client.query(query_type)
    return info


def full_query(query_type='list_nodes_full'):
    '''
    List all available cloud provider data
    '''
    client = _get_client()
    info = client.full_query(query_type)
    return info


def select_query(query_type='list_nodes_select'):
    '''
    List selected nodes
    '''
    client = _get_client()
    info = client.select_query(query_type)
    return info


def profile(prof=None, instances=None, opts=None, **kwargs):
    '''
    Create a cloud vm with the given profile and instances, instances can be a
    list or comma-delimited string

    CLI Example:

    .. code-block:: bash

        salt-run cloud.profile prof=my-ec2 instances=node1,node2,node3
    '''
    if prof is None and 'profile' in kwargs:
        prof = kwargs['profile']

    if prof is None:
        return {'Error': 'A profile (or prof) must be defined'}

    if instances is None and 'names' in kwargs:
        instances = kwargs['names']

    if instances is None:
        return {'Error': 'One or more instances (comma-delimited) must be set'}

    client = _get_client()
    if isinstance(opts, dict):
        client.opts.update(opts)
    info = client.profile(prof, instances, **salt.utils.args.clean_kwargs(**kwargs))
    return info


def map_run(path=None, opts=None, **kwargs):
    '''
    Execute a salt cloud map file
    '''
    client = _get_client()
    if isinstance(opts, dict):
        client.opts.update(opts)
    info = client.map_run(path, **salt.utils.args.clean_kwargs(**kwargs))
    return info


def destroy(instances, opts=None):
    '''
    Destroy the named vm(s)
    '''
    client = _get_client()
    if isinstance(opts, dict):
        client.opts.update(opts)
    info = client.destroy(instances)
    return info


def action(func=None,
           cloudmap=None,
           instances=None,
           provider=None,
           instance=None,
           opts=None,
           **kwargs):
    '''
    Execute a single action on the given map/provider/instance

    CLI Example:

    .. code-block:: bash

        salt-run cloud.action start my-salt-vm
    '''
    info = {}
    client = _get_client()
    if isinstance(opts, dict):
        client.opts.update(opts)
    try:
        info = client.action(
            func,
            cloudmap,
            instances,
            provider,
            instance,
            salt.utils.args.clean_kwargs(**kwargs)
        )
    except SaltCloudConfigError as err:
        log.error(err)
    return info


def create(provider, instances, opts=None, **kwargs):
    '''
    Create an instance using Salt Cloud

    CLI Example:

    .. code-block:: bash

        salt-run cloud.create my-ec2-config myinstance \\
            image=ami-1624987f size='t1.micro' ssh_username=ec2-user \\
            securitygroup=default delvol_on_destroy=True
    '''
    client = _get_client()
    if isinstance(opts, dict):
        client.opts.update(opts)
    info = client.create(provider, instances, **salt.utils.args.clean_kwargs(**kwargs))
    return info
