#!/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.


def inventory_win_cpuusage(info):
    for line in info:
        try:
            if line[0] == "238:6":
                return [(None, {})]
        except Exception:
            pass


def check_win_cpuusage(item, params, info):
    if isinstance(params, tuple):
        levels = params
    elif isinstance(params, dict):
        levels = params.get("levels")
    else:  # legacy: old params may be None
        levels = None

    for line in info:
        if line[0] == "238:6":
            this_time = int(float(line[1]))
            # Windows sends one counter for each CPU plus one counter that
            # I've forgotton what's it for (idle?)
            num_cpus = len(line) - 4
            overall_perc = 0
            for cpu in range(0, num_cpus):
                ticks = int(line[2 + cpu])
                ticks_per_sec = get_rate("cpuusage.%d" % cpu, this_time, ticks)
                secs_per_sec = ticks_per_sec / 10000000.0
                used_perc = 100 * (1 - secs_per_sec)
                overall_perc += used_perc

            used_perc = overall_perc / num_cpus
            if used_perc < 0:
                used_perc = 0
            elif used_perc > 100:
                used_perc = 100

            if num_cpus == 1:
                num_txt = ""
            else:
                num_txt = " / %d CPUs" % num_cpus

            return check_levels(
                used_perc,
                "cpuusage",
                levels,
                human_readable_func=get_percent_human_readable,
                infoname="Used%s" % num_txt,
                boundaries=(0, 100),
            )

    return (3, "counter for cpu (238:6) not found")


def inventory_win_diskstat(info):
    for line in info:
        try:
            if line[0] == "2:16" or line[0] == "2:18":
                return [(None, None, None)]
        except Exception:
            pass
    return []


def check_win_diskstat(item, params, info):
    read_bytes_ctr = 0
    write_bytes_ctr = 0
    this_time = None
    for line in info:
        if line[0] == "2:16":
            read_bytes_ctr = int(line[2])
        elif line[0] == "2:18":
            write_bytes_ctr = int(line[2])
            this_time = int(float(line[1]))
            break

    if not this_time:
        return

    try:
        read_per_sec = get_rate("diskstat.read", this_time, read_bytes_ctr)
        write_per_sec = get_rate("diskstat.write", this_time, write_bytes_ctr)
    except MKCounterWrapped as e:
        # make sure that inital check does not need three cycles for all counters
        # to be initialized
        get_rate("diskstat.write", this_time, write_bytes_ctr)
        raise e

    perfdata = [("read", "%dc" % read_bytes_ctr), ("write", "%dc" % write_bytes_ctr)]
    return (
        0,
        "reading %.1f MB/s, writing %.1f MB/s"
        % (read_per_sec / 1024.0**2, write_per_sec / 1024.0**2),
        perfdata,
    )


check_info["winperf.cpuusage"] = {
    "check_function": check_win_cpuusage,
    "inventory_function": inventory_win_cpuusage,
    "service_description": "CPU Usage",
    "has_perfdata": True,
}

check_info["winperf.diskstat"] = {
    "check_function": check_win_diskstat,
    "inventory_function": inventory_win_diskstat,
    "service_description": "Disk IO",
    "has_perfdata": True,
}
