"""
Module for handling OpenStack Swift calls
Author: Anthony Stanton <anthony.stanton@gmail.com>

Inspired by the S3 and Nova modules

:depends:   - swiftclient Python module
:configuration: This module is not usable until the user, tenant, auth URL, and password or auth_key
    are specified either in a pillar or in the minion's config file.
    For example::

        keystone.user: admin
        keystone.tenant: admin
        keystone.auth_url: 'http://127.0.0.1:5000/v2.0/'
        keystone.password: verybadpass
        # or
        keystone.auth_key: 203802934809284k2j34lkj2l3kj43k

    If configuration for multiple OpenStack accounts is required, they can be
    set up as different configuration profiles:
    For example::

        openstack1:
          keystone.user: admin
          keystone.tenant: admin
          keystone.auth_url: 'http://127.0.0.1:5000/v2.0/'
          keystone.password: verybadpass
          # or
          keystone.auth_key: 203802934809284k2j34lkj2l3kj43k

        openstack2:
          keystone.user: admin
          keystone.tenant: admin
          keystone.auth_url: 'http://127.0.0.2:5000/v2.0/'
          keystone.password: verybadpass
          # or
          keystone.auth_key: 303802934809284k2j34lkj2l3kj43k

    With this configuration in place, any of the swift functions can make use of
    a configuration profile by declaring it explicitly.
    For example::

        salt '*' swift.get mycontainer myfile /tmp/file profile=openstack1

    NOTE: For Rackspace cloud files setting keystone.auth_version = 1 is recommended.
"""

import logging

import salt.utils.openstack.swift as suos

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


def __virtual__():
    """
    Only load this module if swift
    is installed on this minion.
    """
    return suos.check_swift()


__opts__ = {}


def _auth(profile=None):
    """
    Set up openstack credentials
    """
    if profile:
        credentials = __salt__["config.option"](profile)
        user = credentials["keystone.user"]
        password = credentials.get("keystone.password", None)
        tenant = credentials["keystone.tenant"]
        auth_url = credentials["keystone.auth_url"]
        auth_version = credentials.get("keystone.auth_version", 2)
        region_name = credentials.get("keystone.region_name", None)
        api_key = credentials.get("keystone.api_key", None)
        os_auth_system = credentials.get("keystone.os_auth_system", None)
    else:
        user = __salt__["config.option"]("keystone.user")
        password = __salt__["config.option"]("keystone.password", None)
        tenant = __salt__["config.option"]("keystone.tenant")
        auth_url = __salt__["config.option"]("keystone.auth_url")
        auth_version = __salt__["config.option"]("keystone.auth_version", 2)
        region_name = __salt__["config.option"]("keystone.region_name")
        api_key = __salt__["config.option"]("keystone.api_key")
        os_auth_system = __salt__["config.option"]("keystone.os_auth_system")
    kwargs = {
        "user": user,
        "password": password,
        "key": api_key,
        "tenant_name": tenant,
        "auth_url": auth_url,
        "auth_version": auth_version,
        "region_name": region_name,
    }

    return suos.SaltSwift(**kwargs)


def delete(cont, path=None, profile=None):
    """
    Delete a container, or delete an object from a container.

    CLI Example to delete a container::

        salt myminion swift.delete mycontainer

    CLI Example to delete an object from a container::

        salt myminion swift.delete mycontainer remoteobject
    """
    swift_conn = _auth(profile)

    if path is None:
        return swift_conn.delete_container(cont)
    else:
        return swift_conn.delete_object(cont, path)


def get(cont=None, path=None, local_file=None, return_bin=False, profile=None):
    """
    List the contents of a container, or return an object from a container. Set
    return_bin to True in order to retrieve an object wholesale. Otherwise,
    Salt will attempt to parse an XML response.

    CLI Example to list containers:

    .. code-block:: bash

        salt myminion swift.get

    CLI Example to list the contents of a container:

    .. code-block:: bash

        salt myminion swift.get mycontainer

    CLI Example to return the binary contents of an object:

    .. code-block:: bash

        salt myminion swift.get mycontainer myfile.png return_bin=True

    CLI Example to save the binary contents of an object to a local file:

    .. code-block:: bash

        salt myminion swift.get mycontainer myfile.png local_file=/tmp/myfile.png

    """
    swift_conn = _auth(profile)

    if cont is None:
        return swift_conn.get_account()

    if path is None:
        return swift_conn.get_container(cont)

    if return_bin is True:
        return swift_conn.get_object(cont, path, return_bin)

    if local_file is not None:
        return swift_conn.get_object(cont, path, local_file)

    return False


def head():
    pass


def put(cont, path=None, local_file=None, profile=None):
    """
    Create a new container, or upload an object to a container.

    CLI Example to create a container:

    .. code-block:: bash

        salt myminion swift.put mycontainer

    CLI Example to upload an object to a container:

    .. code-block:: bash

        salt myminion swift.put mycontainer remotepath local_file=/path/to/file
    """
    swift_conn = _auth(profile)

    if path is None:
        return swift_conn.put_container(cont)
    elif local_file is not None:
        return swift_conn.put_object(cont, path, local_file)
    else:
        return False
