#!/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.elphase 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
from cmk.base.plugins.agent_based.agent_based_api.v1 import render

# 508 and 604 have the same mib
janitza_umg_device_map = {
    ".1.3.6.1.4.1.34278.8.6": "96",
    ".1.3.6.1.4.1.34278.10.1": "604",
    ".1.3.6.1.4.1.34278.10.4": "508",
}


def janitza_umg_scan(oid):
    return oid(".1.3.6.1.2.1.1.2.0") in (
        ".1.3.6.1.4.1.34278.8.6",
        ".1.3.6.1.4.1.34278.10.1",
        ".1.3.6.1.4.1.34278.10.4",
    )


def parse_janitza_umg_inphase(info):
    def flatten(line):
        return [x[0] for x in line]

    dev_type = janitza_umg_device_map[info[0][0][0]]

    info_offsets = {
        "508": {
            "energy": 4,
            "sumenergy": 5,
            "misc": 8,
        },
        "604": {
            "energy": 4,
            "sumenergy": 5,
            "misc": 8,
        },
        "96": {
            "energy": 3,
            "sumenergy": 4,
            "misc": 6,
        },
    }[dev_type]

    rmsphase = flatten(info[1])
    sumphase = flatten(info[2])
    energy = flatten(info[info_offsets["energy"]])
    sumenergy = flatten(info[info_offsets["sumenergy"]])

    if dev_type in ["508", "604"]:
        num_phases = 4
        num_currents = 4
    elif dev_type == "96":
        num_phases = 3
        num_currents = 6

    # the number of elements in each "block" within the snmp. This differs between
    # devices
    counts = [
        num_phases,  # voltages
        3,  # L1-L2, L2-L3, L3-L1
        num_currents,  # umg96 reports voltage for 3 phases and current for 6
        num_phases,  # real power
        num_phases,  # reactive power
        num_phases,  # Power in VA
        num_phases,  # Cos(Phi)
    ]

    def offset(block_id, phase):
        return sum(counts[:block_id], phase)

    # voltages are in 100mv, currents in 1mA, power in Watts / VA
    result = {}

    for phase in range(num_phases):
        result["Phase %d" % (phase + 1)] = {
            "voltage": int(rmsphase[offset(0, phase)]) / 10.0,
            "current": int(rmsphase[offset(2, phase)]) / 1000.0,
            "power": int(rmsphase[offset(3, phase)]),
            "appower": int(rmsphase[offset(5, phase)]),
            "energy": int(energy[phase]) / 10,
        }

    result["Total"] = {"power": int(sumphase[0]), "energy": int(sumenergy[0])}

    misc = flatten(info[info_offsets["misc"]])
    result["Frequency"] = int(misc[0])
    # temperature not present in UMG508 and UMG604
    if len(misc) > 1:
        result["Temperature"] = list(map(int, misc[1:]))
    else:
        result["Temperature"] = []
    return result


def inventory_janitza_umg_inphase(parsed):
    for item in parsed:
        if item.startswith("Phase"):
            yield item, {}


check_info["janitza_umg"] = {
    "parse_function": parse_janitza_umg_inphase,
    "inventory_function": inventory_janitza_umg_inphase,
    "check_function": check_elphase,
    "service_description": "Input %s",
    "has_perfdata": True,
    "default_levels_variable": "janitza_umg_inphase_default_levels",
    "group": "el_inphase",
    "snmp_info": [
        (".1.3.6.1.2.1.1.2", ["0"]),  # device id
        (".1.3.6.1.4.1.34278", ["1"]),  # rmsPhase
        (".1.3.6.1.4.1.34278", ["2"]),  # rmsSum
        (".1.3.6.1.4.1.34278", ["3"]),  # device dependent
        (".1.3.6.1.4.1.34278", ["4"]),  #       "
        (".1.3.6.1.4.1.34278", ["5"]),  #       "
        (".1.3.6.1.4.1.34278", ["6"]),  #       "
        (".1.3.6.1.4.1.34278", ["7"]),  #       "
        (".1.3.6.1.4.1.34278", ["8"]),  #       "
    ],
    "snmp_scan_function": janitza_umg_scan,
}


def inventory_janitza_umg_freq(parsed):
    # info[0] is frequency, info[1] is first temperature reading, info[2] is second.
    if "Frequency" in parsed:
        yield "1", {}  # why?? :-(


def check_janitza_umg_freq(item, params, parsed):
    if "Frequency" not in parsed:
        return

    return check_levels(
        float(parsed["Frequency"]) / 100.0,
        "in_freq",
        (None, None) + params["levels"],
        human_readable_func=render.frequency,
        infoname="Frequency",
    )


factory_settings["janitza_umg_freq_default_levels"] = {"levels": (0, 0)}


check_info["janitza_umg.freq"] = {
    "inventory_function": inventory_janitza_umg_freq,
    "check_function": check_janitza_umg_freq,
    "service_description": "Frequency %s",
    "has_perfdata": True,
    "default_levels_variable": "janitza_umg_freq_default_levels",
    "group": "efreq",
}


def inventory_janitza_umg_temp(parsed):
    ctr = 1
    for temp in parsed["Temperature"]:
        if temp != -1000:
            yield str(ctr), {}
        ctr += 1


def check_janitza_umg_temp(item, params, parsed):
    idx = int(item) - 1
    if len(parsed["Temperature"]) > idx:
        return check_temperature(
            float(parsed["Temperature"][idx]) / 10.0, params, "janitza_umg_%s" % item
        )


check_info["janitza_umg.temp"] = {
    "inventory_function": inventory_janitza_umg_temp,
    "check_function": check_janitza_umg_temp,
    "service_description": "Temperature External %s",
    "has_perfdata": True,
    "default_levels_variable": "janitza_umg_temp_default_levels",
    "group": "temperature",
}
