#!/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.dhcp_pools import *  # pylint: disable=wildcard-import,unused-wildcard-import

# Example outputs from agent:
#
# <<<win_dhcp_pools>>>
#
# MIB-Anzahl:
#     Entdeckungen = 0.
#     Angebote = 0.
#     Anforderungen = 0.
#     Acks = 0.
#     Naks = 0.
#     Abweisungen = 0.
#     Freigaben = 0.
#     ServerStartTime = Dienstag, 29. Juni 2010 19:08:55
#     Bereiche = 1.
#     Subnetz = 192.168.123.0.
#         Anzahl der verwendeten Adressen = 0.
#         Anzahl der freien Adressen = 239.
#         Anzahl der anstehenden Angebote = 0.
#
# MIBCounts:
#         Discovers = 0.
#         Offers = 0.
#         Requests = 0.
#         Acks = 1.
#         Naks = 0.
#         Declines = 0.
#         Releases = 0.
#         ServerStartTime = Sunday, May 25, 2008 12:38:06 PM
#         Scopes = 1.
#         Subnet = 172.16.11.0.
#                 No. of Addresses in use = 1.
#                 No. of free Addresses = 23.
#                 No. of pending offers = 0.

#   .--Pools---------------------------------------------------------------.
#   |                       ____             _                             |
#   |                      |  _ \ ___   ___ | |___                         |
#   |                      | |_) / _ \ / _ \| / __|                        |
#   |                      |  __/ (_) | (_) | \__ \                        |
#   |                      |_|   \___/ \___/|_|___/                        |
#   |                                                                      |
#   '----------------------------------------------------------------------'

win_dhcp_pools_default_levels = (10, 5)
win_dhcp_pools_inventorize_empty = False
discovery_win_dhcp_pools = []

# Attention:
#
# Tried to get the win-agent plugin to report always in utf-8, unfortunately without luck.
# ...that's the reason why french translations with special characters must get provided like here.

win_dhcp_pools_stats_translate = {
    "Entdeckungen": "Discovers",
    "Angebote": "Offers",
    "Anforderungen": "Requests",
    "Acks": "Acks",
    "Naks": "Nacks",
    "Abweisungen": "Declines",
    "Freigaben": "Releases",
    "Subnetz": "Subnet",
    "Bereiche": "Scopes",
    "Anzahl der verwendeten Adressen": "No. of Addresses in use",
    "Anzahl der freien Adressen": "No. of free Addresses",
    "Anzahl der anstehenden Angebote": "No. of pending offers",
    "D\x82couvertes": "Discovers",
    "Offres": "Offers",
    "Requ\x88tes": "Requests",
    "AR": "Acks",
    "AR n\x82g.": "Nacks",
    "Refus": "Declines",
    "Lib\x82rations": "Releases",
    "Sous-r\x82seau": "Subnet",
    "\x90tendues": "Scopes",
    "Nb d'adresses utilis\x82es": "No. of Addresses in use",
    "Nb d'adresses libres": "No. of free Addresses",
    "Nb d'offres en attente": "No. of pending offers",
}


def parse_win_dhcp_pools(info):
    return [" ".join(line).rstrip(".").split(" = ") for line in info]


def inventory_win_dhcp_pools(info):
    settings = host_extra_conf_merged(host_name(), discovery_win_dhcp_pools)
    discover_empty = settings.get("empty_pools", win_dhcp_pools_inventorize_empty)

    inventory = []
    in_block = False
    last_pool = ""
    pool_stats = []
    for line in parse_win_dhcp_pools(info):
        if win_dhcp_pools_stats_translate.get(line[0], line[0]) == "Subnet":
            in_block = True
            pool_stats = []
            last_pool = line[1]
            continue
        if in_block:
            pool_stats.append(saveint(line[1]))

        if len(pool_stats) == 3:
            in_block = False
            used, free, pending = pool_stats  # pylint: disable=unbalanced-tuple-unpacking
            size = used + free + pending
            if size > 0 or discover_empty:
                inventory.append((last_pool, "win_dhcp_pools_default_levels"))
    return inventory


def check_win_dhcp_pools(item, params, info):
    in_block = False
    pool_stats = [None, None, None]
    for line in parse_win_dhcp_pools(info):
        if win_dhcp_pools_stats_translate.get(line[0], line[0]) == "Subnet" and line[1] == item:
            in_block = True
            pool_stats = []
            continue

        if in_block:
            pool_stats.append(saveint(line[1]))
            if len(pool_stats) == 3:
                break

    if all(v is not None for v in pool_stats):
        used, free, pending = pool_stats
        size = used + free + pending

        # Catch unused pools
        if size == 0:
            yield 3, "DHCP Pool contains no IP addresses / is deactivated"
            return

        for state, infotext, perfdata in check_dhcp_pools_levels(free, used, pending, size, params):
            # The Windows DHCP plugin collects statistics, not real-time
            # measurements. "Average" is pre-pended in order to clarify this. See
            # SUP-9126
            yield state, f"Average {infotext}", perfdata

    else:
        yield 3, "Pool information not found"


check_info["win_dhcp_pools"] = {
    "check_function": check_win_dhcp_pools,
    "inventory_function": inventory_win_dhcp_pools,
    "service_description": "DHCP Pool %s",
    "has_perfdata": True,
    "group": "win_dhcp_pools",
}

# .
#   .--Pool stats----------------------------------------------------------.
#   |              ____             _       _        _                     |
#   |             |  _ \ ___   ___ | |  ___| |_ __ _| |_ ___               |
#   |             | |_) / _ \ / _ \| | / __| __/ _` | __/ __|              |
#   |             |  __/ (_) | (_) | | \__ \ || (_| | |_\__ \              |
#   |             |_|   \___/ \___/|_| |___/\__\__,_|\__|___/              |
#   |                                                                      |
#   '----------------------------------------------------------------------'


def inventory_win_dhcp_pools_stats(info):
    return [(None, None) for line in info if line[0] != ""]


def check_win_dhcp_pools_stats(item, params, info):
    output = ""
    perfdata = []
    this_time = int(time.time())

    for line in parse_win_dhcp_pools(info):
        if len(line) > 0:
            key = win_dhcp_pools_stats_translate.get(line[0], line[0])
            if key in [
                "Discovers",
                "Offers",
                "Requests",
                "Acks",
                "Nacks",
                "Declines",
                "Releases",
                "Scopes",
            ]:
                value = saveint(line[1])
                per_sec = get_rate("win_dhcp_stats.%s" % key, this_time, value)
                output += "%s: %.0f/s, " % (key, per_sec)
                perfdata.append((key, per_sec))

    if output == "":
        return (3, "Information not available")
    return 0, output.rstrip(", "), perfdata


check_info["win_dhcp_pools.stats"] = {
    "check_function": check_win_dhcp_pools_stats,
    "inventory_function": inventory_win_dhcp_pools_stats,
    "service_description": "DHCP Stats",
    "has_perfdata": True,
}
