#!/usr/bin/env python3
# -*- coding: utf-8; py-indent-offset: 4 -*-
#
# Author:  Linuxfabrik GmbH, Zurich, Switzerland
# Contact: info (at) linuxfabrik (dot) ch
#          https://www.linuxfabrik.ch/
# License: The Unlicense, see LICENSE file.

# https://github.com/Linuxfabrik/monitoring-plugins/blob/main/CONTRIBUTING.md

"""See the check's README for more details.
"""

import argparse  # pylint: disable=C0413
import json  # pylint: disable=C0413
import sys  # pylint: disable=C0413

import lib.base  # pylint: disable=C0413

try:
    import lib.smb  # pylint: disable=C0413
    HAVE_SMB = True
except ModuleNotFoundError as e:
    HAVE_SMB = False
    missing_lib = e.name
import lib.txt  # pylint: disable=C0413
import lib.url  # pylint: disable=C0413
from lib.globals import (STATE_CRIT, STATE_OK,  # pylint: disable=C0413
                          STATE_UNKNOWN, STATE_WARN)

__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
__version__ = '2023112901'

DESCRIPTION = """This check parses a flat json array from a file or url and simply returns the
                 message, state and perfdata from the json."""

DEFAULT_INSECURE = False
DEFAULT_MESSAGE_KEY = 'message'
DEFAULT_NO_PROXY = False
DEFAULT_PERFDATA_KEY = 'perfdata'
DEFAULT_STATE_KEY = 'state'
DEFAULT_TIMEOUT = 3


def parse_args():
    """Parse command line arguments using argparse.
    """
    parser = argparse.ArgumentParser(description=DESCRIPTION)

    parser.add_argument(
        '-V', '--version',
        action='version',
        version='{0}: v{1} by {2}'.format('%(prog)s', __version__, __author__)
    )

    parser.add_argument(
        '--always-ok',
        help='Always returns OK.',
        dest='ALWAYS_OK',
        action='store_true',
        default=False,
    )

    parser.add_argument(
        '--filename',
        help='Set the url of the json file. This is mutually exclusive with -u / --url.',
        dest='FILENAME',
        type=str,
    )

    parser.add_argument(
        '--insecure',
        help='This option explicitly allows to perform "insecure"'
        ' SSL connections. Default: %(default)s',
        dest='INSECURE',
        action='store_true',
        default=DEFAULT_INSECURE,
    )

    parser.add_argument(
        '--message-key',
        help='Name of the json array key containing the output message. Default: %(default)s',
        dest='MESSAGE_KEY',
        type=str,
        default=DEFAULT_MESSAGE_KEY,
    )

    parser.add_argument(
        '--no-proxy',
        help='Do not use a proxy. Default: %(default)s',
        dest='NO_PROXY',
        action='store_true',
        default=DEFAULT_NO_PROXY,
    )

    parser.add_argument(
        '--password',
        help='SMB Password.',
        dest='PASSWORD',
    )

    parser.add_argument(
        '--perfdata-key',
        help='Name of the json array key containing the perfdata. Default: %(default)s',
        dest='PERFDATA_KEY',
        type=str,
        default=DEFAULT_PERFDATA_KEY,
    )

    parser.add_argument(
        '--state-key',
        help='Name of the json array key containing the state. Default: %(default)s',
        dest='STATE_KEY',
        type=str,
        default=DEFAULT_STATE_KEY,
    )

    parser.add_argument(
        '--timeout',
        help='Network timeout in seconds. Default: %(default)s (seconds)',
        dest='TIMEOUT',
        type=int,
        default=DEFAULT_TIMEOUT,
    )

    parser.add_argument(
        '-u', '--url',
        help='Set the url of the json file, either starting with "http://", "https://" or "smb://". This is mutually exclusive with --filename.',
        dest='URL',
        type=str,
    )

    parser.add_argument(
        '--username',
        help='SMB Username.',
        dest='USERNAME',
    )

    return parser.parse_args()


def main():
    """The main function. Hier spielt die Musik.
    """

    # parse the command line, exit with UNKNOWN if it fails
    try:
        args = parse_args()
    except SystemExit:
        sys.exit(STATE_UNKNOWN)

    if args.FILENAME and args.URL:
        lib.base.cu('The --filename and -u / --url parameter are mutually exclusive. Please only use one.')

    result = None
    if args.FILENAME:
        with open(args.FILENAME) as json_file:
            result = json.load(json_file)

    if args.URL:
        split_url = args.URL.split('://')
        if len(split_url) != 2:
            lib.base.cu('Could not parse the protocol of the url "{}".'.format(args.URL))
        proto, url = split_url

        if proto in ['http', 'https']:
            result = lib.base.coe(lib.url.fetch_json(
                args.URL, insecure=args.INSECURE, no_proxy=args.NO_PROXY,
                timeout=args.TIMEOUT
            ))
        elif proto == 'smb':
            if not HAVE_SMB:
                lib.base.cu('Python module "{}" is not installed.'.format(missing_lib))
            with lib.base.coe(lib.smb.open_file(url, args.USERNAME, args.PASSWORD, args.TIMEOUT)) as fd:
                try:
                    result = json.loads(lib.txt.to_text(fd.read()))
                except:
                    lib.base.cu('ValueError: No JSON object could be decoded')
        else:
            lib.base.cu('The protocol "{}" is not supported.'.format(proto))

    if result is None:
        lib.base.cu('Nothing returned.')

    msg = result.get(args.MESSAGE_KEY, "") if args.MESSAGE_KEY else ""
    state = result.get(args.STATE_KEY, STATE_UNKNOWN) if args.STATE_KEY else STATE_UNKNOWN
    perfdata = result.get(args.PERFDATA_KEY) if args.PERFDATA_KEY else None

    # over and out
    lib.base.oao(msg, state, perfdata, always_ok=args.ALWAYS_OK)


if __name__ == '__main__':
    try:
        main()
    except Exception:   # pylint: disable=W0703
        lib.base.cu()
