"""
Return salt data to Nagios

The following fields can be set in the minion conf file::

    nagios.url (required)
    nagios.token (required)
    nagios.service (optional)
    nagios.check_type (optional)

Alternative configuration values can be used by prefacing the configuration.
Any values not found in the alternative configuration will be pulled from
the default location::

    nagios.url
    nagios.token
    nagios.service

Nagios settings may also be configured as::

    nagios:
        url: http://localhost/nrdp
        token: r4nd0mt0k3n
        service: service-check

    alternative.nagios:
        url: http://localhost/nrdp
        token: r4nd0mt0k3n
        service: another-service-check

  To use the Nagios returner, append '--return nagios' to the salt command. ex:

  .. code-block:: bash

    salt '*' test.ping --return nagios

  To use the alternative configuration, append '--return_config alternative' to the salt command. ex:

    salt '*' test.ping --return nagios --return_config alternative

To override individual configuration items, append --return_kwargs '{"key:": "value"}' to the salt command.

.. versionadded:: 2016.3.0

.. code-block:: bash

    salt '*' test.ping --return nagios --return_kwargs '{"service": "service-name"}'

"""

import html
import http.client
import logging

import salt.returners

log = logging.getLogger(__name__)

__virtualname__ = "nagios_nrdp"


def __virtual__():
    """
    Return virtualname
    """
    return "nagios.list_plugins" in __salt__


def _get_options(ret=None):
    """
    Get the requests options from salt.
    """
    attrs = {
        "url": "url",
        "token": "token",
        "service": "service",
        "checktype": "checktype",
    }

    _options = salt.returners.get_returner_options(
        __virtualname__, ret, attrs, __salt__=__salt__, __opts__=__opts__
    )

    log.debug("attrs %s", attrs)
    if "checktype" not in _options or _options["checktype"] == "":
        # default to passive check type
        _options["checktype"] = "1"

    if _options["checktype"] == "active":
        _options["checktype"] = "0"

    if _options["checktype"] == "passive":
        _options["checktype"] = "1"

    # checktype should be a string
    _options["checktype"] = str(_options["checktype"])

    return _options


def _prepare_xml(options=None, state=None):
    """
    Get the requests options from salt.
    """

    if state:
        _state = "0"
    else:
        _state = "2"

    xml = "<?xml version='1.0'?>\n<checkresults>\n"

    # No service defined then we set the status of the hostname
    if options.get("service"):
        xml += (
            "<checkresult type='service' checktype='" + str(options["checktype"]) + "'>"
        )
        xml += "<hostname>" + html.escape(options["hostname"]) + "</hostname>"
        xml += "<servicename>" + html.escape(options["service"]) + "</servicename>"
    else:
        xml += "<checkresult type='host' checktype='" + str(options["checktype"]) + "'>"
        xml += "<hostname>" + html.escape(options["hostname"]) + "</hostname>"

    xml += "<state>" + _state + "</state>"

    if options.get("output"):
        xml += "<output>" + html.escape(options["output"]) + "</output>"

    xml += "</checkresult>"

    xml += "\n</checkresults>"

    return xml


def _getText(nodelist):
    """
    Simple function to return value from XML
    """
    rc = []
    for node in nodelist:
        if node.nodeType == node.TEXT_NODE:
            rc.append(node.data)
    return "".join(rc)


def _post_data(options=None, xml=None):
    """
    Post data to Nagios NRDP
    """
    params = {"token": options["token"].strip(), "cmd": "submitcheck", "XMLDATA": xml}

    res = salt.utils.http.query(
        url=options["url"],
        method="POST",
        params=params,
        data="",
        decode=True,
        status=True,
        header_dict={},
        opts=__opts__,
    )

    if res.get("status", None) == http.client.OK:
        if res.get("dict", None) and isinstance(res["dict"], list):
            _content = res["dict"][0]
            if _content.get("status", None):
                return True
            else:
                return False
        else:
            log.error("No content returned from Nagios NRDP.")
            return False
    else:
        log.error("Error returned from Nagios NRDP. Status code: %s.", res.status_code)
        return False


def returner(ret):
    """
    Send a message to Nagios with the data
    """

    _options = _get_options(ret)
    log.debug("_options %s", _options)
    _options["hostname"] = ret.get("id")

    if "url" not in _options or _options["url"] == "":
        log.error("nagios_nrdp.url not defined in salt config")
        return

    if "token" not in _options or _options["token"] == "":
        log.error("nagios_nrdp.token not defined in salt config")
        return

    xml = _prepare_xml(options=_options, state=ret["return"])
    res = _post_data(options=_options, xml=xml)

    return res
