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

# <<<appdynamics_memory:sep(124)>>>
# Hans|Non-Heap|Max Available (MB):304|Current Usage (MB):78|Used %:25|Committed (MB):267
# Hans|Heap|Max Available (MB):455|Current Usage (MB):66|Used %:14|Committed (MB):252


def inventory_appdynamics_memory(info):
    for line in info:
        yield " ".join(line[0:2]), {}


def check_appdynamics_memory(item, params, info):
    for line in info:
        if item == " ".join(line[0:2]):
            mb = 1024 * 1024.0

            if item.endswith("Non-Heap"):
                mem_type = "nonheap"
            elif item.endswith("Heap"):
                mem_type = "heap"
            else:
                mem_type = ""  # Should not happen...

            values = {}
            for metric in line[2:]:
                name, value = metric.split(":")
                values[name] = int(value)

            used = values.get("Current Usage (MB)", 0) * mb
            committed = values.get("Committed (MB)", 0) * mb

            try:
                max_available = values["Max Available (MB)"] * mb
            except KeyError:
                max_available = -1  # Java 8 has no maximum for Non-Heap

            if max_available > 0:
                used_percent = 100.0 * used / max_available

                warn, crit = params.get(mem_type, (None, None))
            else:
                warn, crit = (None, None)

            if isinstance(crit, float):
                crit_label = "%.2f%%" % crit
                crit = int((max_available / 100.0) * crit)
            elif isinstance(crit, int):
                crit_label = "%d MB free" % (crit)
                crit = max_available - (crit * mb)
            else:
                crit_label = ""

            if isinstance(warn, float):
                warn_label = "%.2f%%" % warn
                warn = int((max_available / 100.0) * warn)
            elif isinstance(warn, int):
                warn_label = "%d MB free" % (warn)
                warn = max_available - (warn * mb)
            else:
                warn_label = ""

            state = 0
            if crit and used >= crit:
                state = 2
            elif warn and used >= warn:
                state = 1

            levels_label = ""
            if state > 0:
                levels_label = " (levels at %s/%s)" % (warn_label, crit_label)

            if max_available > 0:
                perfdata = [("mem_%s" % mem_type, used, warn, crit, 0, max_available)]
                yield state, "Used: %s of %s (%.2f%%)%s" % (
                    get_bytes_human_readable(used),
                    get_bytes_human_readable(max_available),
                    used_percent,
                    levels_label,
                ), perfdata
            else:
                perfdata = [("mem_%s" % mem_type, used)]
                yield state, "Used: %s" % get_bytes_human_readable(used), perfdata

            if max_available > 0:
                perfdata = [
                    ("mem_%s_committed" % mem_type, committed, None, None, 0, max_available)
                ]
            else:
                perfdata = [("mem_%s_committed" % mem_type, committed)]
            yield 0, "Committed: %s" % get_bytes_human_readable(committed), perfdata


check_info["appdynamics_memory"] = {
    "inventory_function": inventory_appdynamics_memory,
    "check_function": check_appdynamics_memory,
    "service_description": "AppDynamics Memory %s",
    "has_perfdata": True,
    "group": "jvm_memory",
}
