#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2018             mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk is free software;  you can redistribute it and/or modify it
# under the  terms of the  GNU General Public License  as published by
# the Free Software Foundation in version 2.  check_mk is  distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
# PARTICULAR PURPOSE. See the  GNU General Public License for more de-
# tails. You should have  received  a copy of the  GNU  General Public
# License along with GNU Make; see the file  COPYING.  If  not,  write
# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
# Boston, MA 02110-1301 USA.
import ast

# params = {
#     "mincount": (tuple, integer),
#     "maxcount": -"-,
#     "minage_oldest": (tuple, seconds),
#     "maxage_oldest":  -"-,
#     "minage_newest": -"-,
#     "maxage_newest": -"-,
#     "minsize_smallest": (tuple, bytes),
#     "maxsize_...
#     "minsize_largest": -"-,
#     "maxsize_...
# }

#.
#   .--Parsing-------------------------------------------------------------.
#   |                  ____                _                               |
#   |                 |  _ \ __ _ _ __ ___(_)_ __   __ _                   |
#   |                 | |_) / _` | '__/ __| | '_ \ / _` |                  |
#   |                 |  __/ (_| | |  \__ \ | | | | (_| |                  |
#   |                 |_|   \__,_|_|  |___/_|_| |_|\__, |                  |
#   |                                              |___/                   |
#   +----------------------------------------------------------------------+
#   |                                                                      |
#   '----------------------------------------------------------------------'


def parse_filestats(info):
    sections_info = {}
    current = []  # should never be used, but better safe than sorry
    for line in info:
        if not line:
            continue
        if line[0].startswith('[[['):
            _output_variety, subsection_name = line[0][3:-3].split(None, 1)
            current = sections_info.setdefault(subsection_name, [])
        else:
            current.append(line[0])

    return {k: _parse_filestats_load_lines(v) for k, v in sections_info.items() if v}


def _parse_filestats_load_lines(info):
    list_of_dicts = []
    for line in info:
        try:
            list_of_dicts.append(ast.literal_eval(line))
        except SyntaxError:
            pass
    return list_of_dicts


#.
#   .--Helpers-------------------------------------------------------------.
#   |                  _   _      _                                        |
#   |                 | | | | ___| |_ __   ___ _ __ ___                    |
#   |                 | |_| |/ _ \ | '_ \ / _ \ '__/ __|                   |
#   |                 |  _  |  __/ | |_) |  __/ |  \__ \                   |
#   |                 |_| |_|\___|_| .__/ \___|_|  |___/                   |
#   |                              |_|                                     |
#   +----------------------------------------------------------------------+
#   |                                                                      |
#   '----------------------------------------------------------------------'


def filestats_check_int_levels(value,
                               lower_levels_pair,
                               upper_levels_pair,
                               hr_function=lambda i: "%d" % i):
    state, msg = 0, ""
    if lower_levels_pair not in (None, (None, None)):
        warn, crit = lower_levels_pair
        if value <= warn:
            state = 1
            msg = " (warn/crit below %s/%s)" % (hr_function(warn), hr_function(crit))
        if value <= crit:
            return 2, msg

    if upper_levels_pair not in (None, (None, None)):
        warn, crit = upper_levels_pair
        if value >= warn:
            state = 1
            msg = " (warn/crit at %s/%s)" % (hr_function(warn), hr_function(crit))
        if value >= crit:
            return 2, msg

    return state, msg


def check_filestats_count(count, params):
    '''common check result - used by main and count_only check'''
    state, text = filestats_check_int_levels(count, params.get("mincount"), params.get("maxcount"))
    warn, crit = params.get("maxcount", (None, None))
    return state, "Files in total: %d%s" % (count, text), \
           [('file_count', count, warn, crit, None, None)]


def check_filestats_extremes(files, params):
    '''common check result - used by main and extremes_only check'''
    for key, hr_function, minlabel, maxlabel in (
        ('size', get_bytes_human_readable, 'smallest', 'largest'),
        ('age', get_age_human_readable, 'newest', 'oldest'),
    ):
        files.sort(key=lambda f: f.get(key))  # pylint: disable=cell-var-from-loop
        for efile, label in ((files[0], minlabel), (files[-1], maxlabel)):
            state, text = filestats_check_int_levels(
                efile.get(key),
                params.get("min%s_%s" % (key, label)),
                params.get("max%s_%s" % (key, label)),
                hr_function,
            )
            if state:
                text = "%s: %s" % (text, efile.get('path', "<path info missing>"))
            value_hr = hr_function(efile.get(key))
            yield state, "%s: %s%s" % (label.title(), value_hr, text)


#.
#   .--Checks--------------------------------------------------------------.
#   |                    ____ _               _                            |
#   |                   / ___| |__   ___  ___| | _____                     |
#   |                  | |   | '_ \ / _ \/ __| |/ / __|                    |
#   |                  | |___| | | |  __/ (__|   <\__ \                    |
#   |                   \____|_| |_|\___|\___|_|\_\___/                    |
#   |                                                                      |
#   +----------------------------------------------------------------------+
#   |                                                                      |
#   '----------------------------------------------------------------------'


@get_parsed_item_data
def check_filestats(_item, params, data):

    sumry = [s for s in data if s.get("type") == "summary"]
    count = sumry[0].get("count", None) if sumry else None
    if count is not None:
        yield check_filestats_count(count, params)

    files = [i for i in data if i.get("type") == "file"]
    if files:
        for subresult in check_filestats_extremes(files, params):
            yield subresult


check_info['filestats'] = {
    "parse_function": parse_filestats,
    "inventory_function": discover(),
    "check_function": check_filestats,
    "service_description": "File group %s",
    "has_perfdata": True,
    "group": "filestats",
}
