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

# OLD
# <<<solaris_services>>>
# STATE    STIME    FMRI
# $STATE   $STIME   $TYPE:${/CATEGORY/PATH/}$NAME:$INSTANCE

inventory_solaris_services_rules = []


def parse_solaris_services(info):
    def get_parts_of_descr(descr):
        svc_attrs = descr.split(":")
        if len(svc_attrs) == 3:
            svc_instance = svc_attrs[-1]
        else:
            svc_instance = None
        svc_category, svc_name = svc_attrs[1].rsplit("/", 1)
        return svc_attrs[0], svc_category, svc_name, svc_instance

    parsed = {}
    for line in info:
        if len(line) < 3 or line == ["STATE", "STIME", "FMRI"]:
            continue
        svc_descr = line[-1]
        type_, category, name, instance = get_parts_of_descr(svc_descr)
        parsed.setdefault(
            svc_descr,
            {
                "state": line[0],
                "stime": line[1],
                "type": type_,
                "category": category,
                "name": name,
                "instance": instance,
            },
        )
    return parsed


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

factory_settings["solaris_services_default_levels"] = {
    "states": [
        ("online", None, 0),
        ("disabled", None, 2),
        ("legacy_run", None, 0),
        ("maintenance", None, 0),
    ],
    "else": 2,
    "additional_servicenames": [],
}


def inventory_solaris_services(parsed):
    def regex_match(what, name):
        if not what:
            return True
        for entry in what:
            if entry.startswith("~") and regex(entry[1:]).match(name):
                return True
            elif entry == name:
                return True
        return False

    def state_match(rule_state, state):
        if rule_state is not None and rule_state != state:
            return False
        return True

    def get_svc_name(svc_attrs):
        return "%s/%s:%s" % (svc_attrs["category"], svc_attrs["name"], svc_attrs["instance"])

    for settings in host_extra_conf(host_name(), inventory_solaris_services_rules):
        descriptions = settings.get("descriptions", [])
        categories = settings.get("categories", [])
        names = settings.get("names", [])
        instances = settings.get("instances", [])
        state = settings.get("state")
        for svc_descr, attrs in parsed.items():
            if (
                regex_match(descriptions, svc_descr)
                and regex_match(categories, attrs["category"])
                and regex_match(names, attrs["name"])
                and regex_match(instances, attrs["instance"])
                and state_match(state, attrs["state"])
            ):
                if settings.get("outcome") in [None, "full_descr"]:
                    name = svc_descr
                else:
                    name = get_svc_name(attrs)
                yield name, {}


def check_solaris_services(item, params, parsed):
    for svc_name, attrs in parsed.items():
        if item in svc_name or svc_name in params["additional_servicenames"]:
            svc_state = attrs["state"]
            svc_stime = attrs["stime"]
            if svc_stime.count(":") == 2:
                has_changed = True
                info_stime = "Restarted in the last 24h (client's localtime: %s)" % svc_stime
            else:
                has_changed = False
                info_stime = "Started on %s" % svc_stime.replace("_", " ")

            check_state = 0
            for _, p_stime, p_state in [x for x in params["states"] if x[0] == svc_state]:
                if p_stime is not None:
                    if has_changed == p_stime:
                        check_state = p_state
                        break
                else:
                    check_state = p_state
                    break
            return check_state, "Status: %s, %s" % (svc_state, info_stime)

    return params["else"], "Service not found"


check_info["solaris_services"] = {
    "parse_function": parse_solaris_services,
    "inventory_function": inventory_solaris_services,
    "check_function": check_solaris_services,
    "service_description": "SMF Service %s",  # Service Management Facility
    "group": "solaris_services",
    "default_levels_variable": "solaris_services_default_levels",
}

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


def inventory_solaris_services_summary(parsed):
    return [(None, {})]


def check_solaris_services_summary(_no_item, params, parsed):
    yield 0, "%d services" % len(parsed)

    services_by_state = {}
    for svc_name, attrs in parsed.items():
        services = services_by_state.setdefault(attrs["state"], [])
        services.append(svc_name)

    for svc_state, svc_names in services_by_state.items():
        state = 0
        extra_info = ""
        if svc_state == "maintenance" and params.get("maintenance_state", 0):
            extra_info += " (%s)" % ", ".join(svc_names)
            state = params["maintenance_state"]

        yield state, "%d %s%s" % (len(svc_names), svc_state.replace("_", " "), extra_info)


check_info["solaris_services.summary"] = {
    "parse_function": parse_solaris_services,
    "inventory_function": inventory_solaris_services_summary,
    "check_function": check_solaris_services_summary,
    "service_description": "SMF Services Summary",  # Service Management Facility
    "group": "solaris_services_summary",
}
