#!/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 sys  # pylint: disable=C0413

import lib.args  # pylint: disable=C0413
import lib.base  # pylint: disable=C0413
import lib.cache  # pylint: disable=C0413
import lib.net  # pylint: disable=C0413
import lib.lftest  # pylint: disable=C0413
import lib.time  # pylint: disable=C0413
import lib.txt  # pylint: disable=C0413
from lib.globals import STATE_OK, STATE_UNKNOWN  # pylint: disable=C0413

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

DESCRIPTION = """Returns the peer statistics of the Starface PBX.
                It uses the data output of the Starface Monitoring Module, which was
                originally written for Check_MK and listens on port 6556. Supports both IPv4 and
                IPv6. Fetched data is cached up to one minute, so that other Starface plugins
                running in parallel do not query the data again and overload the PBX."""

DEFAULT_CACHE_EXPIRE = 1        # minutes
DEFAULT_HOSTNAME = 'localhost'
DEFAULT_IPV6 = False
DEFAULT_PORT = 6556
DEFAULT_TIMEOUT = 8             # seconds


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

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

    parser.add_argument(
        '--cache-expire',
        help='The amount of time after which the cached data expires, in minutes. Default: %(default)s',
        dest='CACHE_EXPIRE',
        type=int,
        default=DEFAULT_CACHE_EXPIRE,
    )

    parser.add_argument(
        '-H', '--hostname',
        help='Starface PBX address, can be IP address or hostname. Default: %(default)s',
        dest='HOSTNAME',
        default=DEFAULT_HOSTNAME,
    )

    parser.add_argument(
        '--port',
        help='Starface PBX monitoring port. Default: %(default)s',
        dest='PORT',
        type=int,
        default=DEFAULT_PORT,
    )

    parser.add_argument(
        '--test',
        help='For unit tests. Needs "path-to-stdout-file,path-to-stderr-file,expected-retc".',
        dest='TEST',
        type=lib.args.csv,
    )

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

    parser.add_argument(
        '--ipv6',
        help='Use IPv6.',
        dest='USE_IPV6',
        action='store_true',
        default=DEFAULT_IPV6,
    )

    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)

    # fetch data
    if args.TEST is None:
        # fetch data from PBX, but first from cache
        data = lib.cache.get(args.HOSTNAME, filename='linuxfabrik-monitoring-plugins-starface.db')
        if not data:
            data = lib.base.coe(lib.net.fetch(args.HOSTNAME, args.PORT, timeout=args.TIMEOUT))
            lib.cache.set(args.HOSTNAME, data, lib.time.now() + args.CACHE_EXPIRE*60, filename='linuxfabrik-monitoring-plugins-starface.db')
    else:
        # do not call the command, put in test data
        stdout, stderr, retc = lib.lftest.test(args.TEST)
        data = stdout

    if not data:
        lib.base.cu('Got no valuable response from {}:{}.'.format(args.HOSTNAME, args.PORT))

    # extract data
    result = lib.txt.extract_str(data, '<<<starface_peers>>>', '<<<').splitlines()

    # init some vars
    msg = ''
    state = STATE_OK
    perfdata = ''

    # analyze the data
    for row in result:
        if not row:
            continue
        if ' sip peers ' in row:
            row = row.split(' ')
            sip_peers = row[0]
            mon_online = row[4]
            mon_offline = row[6]
            unmon_online = row[9]
            unmon_offline = row[11]
            break

    # build the message
    msg += '{} SIP Peers: {} online / {} offline (monitored), {} online / {} offline (unmonitored)'.format(
        sip_peers,
        mon_online,
        mon_offline,
        unmon_online,
        unmon_offline,
    )

    perfdata += lib.base.get_perfdata('sip_peers', sip_peers, None, None, None, 0, None)
    perfdata += lib.base.get_perfdata('mon_online', mon_online, None, None, None, 0, None)
    perfdata += lib.base.get_perfdata('mon_offline', mon_offline, None, None, None, 0, None)
    perfdata += lib.base.get_perfdata('unmon_online', unmon_online, None, None, None, 0, None)
    perfdata += lib.base.get_perfdata('unmon_offline', unmon_offline, None, None, None, 0, None)

    # over and out
    lib.base.oao(msg, state, perfdata)


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