"""
Execution module for Cisco Network Services Orchestrator Proxy minions

.. versionadded:: 2016.11.0

For documentation on setting up the cisconso proxy minion look in the documentation
for :mod:`salt.proxy.cisconso<salt.proxy.cisconso>`.
"""

import salt.utils.platform

__proxyenabled__ = ["cisconso"]
__virtualname__ = "cisconso"


def __virtual__():
    if salt.utils.platform.is_proxy():
        return __virtualname__
    return (
        False,
        "The cisconso execution module failed to load: "
        "only available on proxy minions.",
    )


def info():
    """
    Return system information for grains of the NSO proxy minion

    .. code-block:: bash

        salt '*' cisconso.info
    """
    return _proxy_cmd("info")


def get_data(datastore, path):
    """
    Get the configuration of the device tree at the given path

    :param datastore: The datastore, e.g. running, operational.
        One of the NETCONF store IETF types
    :type  datastore: :class:`DatastoreType` (``str`` enum).

    :param path: The device path to set the value at,
        a list of element names in order, / separated
    :type  path: ``list``, ``str`` OR ``tuple``

    :return: The network configuration at that tree
    :rtype: ``dict``

    .. code-block:: bash

        salt cisco-nso cisconso.get_data running 'devices/ex0'
    """
    if isinstance(path, str):
        path = "/".split(path)
    return _proxy_cmd("get_data", datastore, path)


def set_data_value(datastore, path, data):
    """
    Set a data entry in a datastore

    :param datastore: The datastore, e.g. running, operational.
        One of the NETCONF store IETF types
    :type  datastore: :class:`DatastoreType` (``str`` enum).

    :param path: The device path to set the value at,
        a list of element names in order, / separated
    :type  path: ``list``, ``str`` OR ``tuple``

    :param data: The new value at the given path
    :type  data: ``dict``

    :rtype: ``bool``
    :return: ``True`` if successful, otherwise error.

    .. code-block:: bash

        salt cisco-nso cisconso.set_data_value running 'devices/ex0/routes' 10.0.0.20/24
    """
    if isinstance(path, str):
        path = "/".split(path)
    return _proxy_cmd("set_data_value", datastore, path, data)


def get_rollbacks():
    """
    Get a list of stored configuration rollbacks

    .. code-block:: bash

        salt cisco-nso cisconso.get_rollbacks
    """
    return _proxy_cmd("get_rollbacks")


def get_rollback(name):
    """
    Get the backup of stored a configuration rollback

    :param name: Typically an ID of the backup
    :type  name: ``str``

    :rtype: ``str``
    :return: the contents of the rollback snapshot

    .. code-block:: bash

        salt cisco-nso cisconso.get_rollback 52
    """
    return _proxy_cmd("get_rollback", name)


def apply_rollback(datastore, name):
    """
    Apply a system rollback

    :param datastore: The datastore, e.g. running, operational.
        One of the NETCONF store IETF types
    :type  datastore: :class:`DatastoreType` (``str`` enum).

    :param name: an ID of the rollback to restore
    :type  name: ``str``

    .. code-block:: bash

        salt cisco-nso cisconso.apply_rollback 52
    """
    return _proxy_cmd("apply_rollback", datastore, name)


def _proxy_cmd(command, *args, **kwargs):
    """
    run commands from __proxy__
    :mod:`salt.proxy.cisconso<salt.proxy.cisconso>`

    command
        function from `salt.proxy.cisconso` to run

    args
        positional args to pass to `command` function

    kwargs
        key word arguments to pass to `command` function
    """
    proxy_prefix = __opts__["proxy"]["proxytype"]
    proxy_cmd = ".".join([proxy_prefix, command])
    if proxy_cmd not in __proxy__:
        return False
    for k in kwargs:
        if k.startswith("__pub_"):
            kwargs.pop(k)
    return __proxy__[proxy_cmd](*args, **kwargs)
