#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.

# NOTE: Careful when replacing the *-import below with a more specific import. This can cause
# problems because it might remove variables from the check-context which are necessary for
# resolving legacy discovery results such as [("SUMMARY", "diskstat_default_levels")]. Furthermore,
# it might also remove variables needed for accessing discovery rulesets.
from cmk.base.check_legacy_includes.humidity import *  # pylint: disable=wildcard-import,unused-wildcard-import

# NOTE: Careful when replacing the *-import below with a more specific import. This can cause
# problems because it might remove variables from the check-context which are necessary for
# resolving legacy discovery results such as [("SUMMARY", "diskstat_default_levels")]. Furthermore,
# it might also remove variables needed for accessing discovery rulesets.
from cmk.base.check_legacy_includes.temperature import *  # pylint: disable=wildcard-import,unused-wildcard-import

# The etherbox supports the following sensor types on each port
# sensor types
# 0 = no sensor
# 1 = temperature      - implemented
# 2 = brightness
# 3 = humidity         - implemented
# 4 = switch contact   - implemented
# 5 = voltage detector
# 6 = smoke sensor     - implemented

# Note: The short contact config option in the etherbox is of type switch contact
#       The short contact status is set for 15 seconds after a button press

# TODO: insert missing snmp output


def etherbox_convert(info):
    sensor_data = []
    for i in range(0, len(info[1])):
        sensor_data.append((info[1][i][1], info[2][i][1], info[3][i][1], info[4][i][1]))
    return sensor_data


def inventory_etherbox(info, req_sensor_type):
    sensor_data = etherbox_convert(info)
    for index, _name, sensor_type, value in sensor_data:
        # Ignore not connected Sensors
        if sensor_type in ("1", "3") and value == "0":
            continue
        if sensor_type == req_sensor_type:
            yield "%s.%s" % (index, sensor_type), None


def etherbox_get_sensor(item, item_type, info):
    sensor_data = etherbox_convert(info)
    item_index, item_type = item.split(".")
    for index, name, sensor_type, value in sensor_data:
        if index == item_index:
            if sensor_type != item_type:
                raise Exception("Sensor type changed %s" % item)
            return name, value
    raise Exception("Sensor not found")


def etherbox_scan(oid):
    # 2015:
    # Older firmware version of Etherbox do not answer on
    # .1.3.6.1.2.1. (sysDescr). Yurks. We need to fetch
    # a vendor specific OID here and wait until all old devices
    # have vanished.
    return oid(".1.3.6.1.4.1.14848.2.1.1.1.0", "").startswith("Version")
    # 2021:
    # Have they yet? How do we know? Anyway: better would be the following,
    # but we need to known what's in the sysDescr in the good case.
    # return (
    #    "etherbox" in oid(".1.3.6.1.2.1.1.1.0").lower() or  # TODO: "etherbox" is a wild guess
    #    (not oid(".1.3.6.1.2.1.1.1.0") and
    #     oid(".1.3.6.1.4.1.14848.2.1.1.1.0", "").startswith("Version"))
    # )


etherbox_info = [
    (".1.3.6.1.4.1.14848.2.1.1.3", [""]),  # temperature unit
    (".1.3.6.1.4.1.14848.2.1.2.1.1", [OID_END, ""]),  # index
    (".1.3.6.1.4.1.14848.2.1.2.1.2", [OID_END, ""]),  # name
    (".1.3.6.1.4.1.14848.2.1.2.1.3", [OID_END, ""]),  # type
    (".1.3.6.1.4.1.14848.2.1.2.1.5", [OID_END, ""]),  # value * 10
]

#   .--temperature---------------------------------------------------------.
#   |      _                                      _                        |
#   |     | |_ ___ _ __ ___  _ __   ___ _ __ __ _| |_ _   _ _ __ ___       |
#   |     | __/ _ \ '_ ` _ \| '_ \ / _ \ '__/ _` | __| | | | '__/ _ \      |
#   |     | ||  __/ | | | | | |_) |  __/ | | (_| | |_| |_| | | |  __/      |
#   |      \__\___|_| |_| |_| .__/ \___|_|  \__,_|\__|\__,_|_|  \___|      |
#   |                       |_|                                            |
#   '----------------------------------------------------------------------'


def check_etherbox_temp(item, params, info):
    try:
        name, value = etherbox_get_sensor(item, "1", info)
    except Exception as error:
        return 3, str(error)

    uom = {"0": "c", "1": "f", "2": "k"}[info[0][0][0]]
    temp = int(value) / 10.0
    state, infotext, perfdata = check_temperature(temp, params, "etherbox_temp_%s" % item, uom)
    return state, "[%s] %s" % (name, infotext), perfdata


check_info["etherbox.temp"] = {
    "check_function": check_etherbox_temp,
    "inventory_function": lambda info: inventory_etherbox(info, "1"),
    "service_description": "Temperature %s",
    "has_perfdata": True,
    "group": "temperature",
    "snmp_scan_function": etherbox_scan,
    "snmp_info": etherbox_info,
}

# .
#   .--humidity------------------------------------------------------------.
#   |              _                     _     _ _ _                       |
#   |             | |__  _   _ _ __ ___ (_) __| (_) |_ _   _               |
#   |             | '_ \| | | | '_ ` _ \| |/ _` | | __| | | |              |
#   |             | | | | |_| | | | | | | | (_| | | |_| |_| |              |
#   |             |_| |_|\__,_|_| |_| |_|_|\__,_|_|\__|\__, |              |
#   |                                                  |___/               |
#   '----------------------------------------------------------------------'


def check_etherbox_humidity(item, params, info):
    try:
        name, value = etherbox_get_sensor(item, "3", info)
    except Exception as error:
        return 3, str(error)

    state, infotext, perfdata = check_humidity(int(value) / 10.0, params)
    return state, "[%s] %s" % (name, infotext), perfdata


check_info["etherbox.humidity"] = {
    "check_function": check_etherbox_humidity,
    "inventory_function": lambda x: inventory_etherbox(x, "3"),
    "service_description": "Sensor %s",
    "has_perfdata": True,
    "group": "humidity",
    "snmp_scan_function": etherbox_scan,
    "snmp_info": etherbox_info,
}

# .
#   .--switch contact------------------------------------------------------.
#   |               _ _       _                       _             _      |
#   |  _____      _(_) |_ ___| |__     ___ ___  _ __ | |_ __ _  ___| |_    |
#   | / __\ \ /\ / / | __/ __| '_ \   / __/ _ \| '_ \| __/ _` |/ __| __|   |
#   | \__ \\ V  V /| | || (__| | | | | (_| (_) | | | | || (_| | (__| |_    |
#   | |___/ \_/\_/ |_|\__\___|_| |_|  \___\___/|_| |_|\__\__,_|\___|\__|   |
#   |                                                                      |
#   '----------------------------------------------------------------------'


def check_etherbox_switch_contact(item, params, info):
    try:
        name, value = etherbox_get_sensor(item, "4", info)
    except Exception as error:
        return 3, str(error)

    state = 0
    perfdata = [("switch_contact", value)]
    switch_state = "open" if value == "1000" else "closed"

    state = 0
    extra_info = ""
    if params and params != "ignore":
        if switch_state != params:
            state = 2
            extra_info = ", should be %s" % params

    infotext = "[%s] Switch contact %s%s" % (name, switch_state, extra_info)
    return (state, infotext, perfdata)


check_info["etherbox.switch"] = {
    "check_function": check_etherbox_switch_contact,
    "inventory_function": lambda x: inventory_etherbox(x, "4"),
    "service_description": "Sensor %s",
    "group": "switch_contact",
    "has_perfdata": True,
    "snmp_scan_function": etherbox_scan,
    "snmp_info": etherbox_info,
}

# .
#   .--smoke---------------------------------------------------------------.
#   |                                        _                             |
#   |                    ___ _ __ ___   ___ | | _____                      |
#   |                   / __| '_ ` _ \ / _ \| |/ / _ \                     |
#   |                   \__ \ | | | | | (_) |   <  __/                     |
#   |                   |___/_| |_| |_|\___/|_|\_\___|                     |
#   |                                                                      |
#   '----------------------------------------------------------------------'


def check_etherbox_smoke(item, no_params, info):
    try:
        name, value = etherbox_get_sensor(item, "6", info)
    except Exception as error:
        return 3, str(error)

    state = 0
    perfdata = [("smoke", value)]
    infotext = "Status: OK"
    if value != "0":
        infotext = "Status: smoke alarm"
        state = 2
    return state, "[%s] %s" % (name, infotext), perfdata


check_info["etherbox.smoke"] = {
    "check_function": check_etherbox_smoke,
    "inventory_function": lambda x: inventory_etherbox(x, "6"),
    "service_description": "Sensor %s",
    "has_perfdata": True,
    "snmp_scan_function": etherbox_scan,
    "snmp_info": etherbox_info,
}
