#!/usr/bin/env python3
# ***************************************************************************
#  IIIIII NNN  NNN  Copyright (C) 2022 Innovative Networks, Inc.
#    II    NNN  N   All Rights Reserved. Any redistribution or reproduction
#    II    N NN N   of part or all of the content of this program in any form
#    II    N  NNN   without expressed written consent of the copyright holder
#  IIIIII NNN  NNN  is strictly prohibited.  Please contact admins@in-kc.com
#   Be Innovative.  for additional information.
# ***************************************************************************
#  check_intools.py
#  Author - Ian Perry <iperry@indigex.com>
#
#  Purpose:  Checks intools services.
#
#  Version History:
#       2023.05.09 - Initial creation
# ***************************************************************************


try:
    from inmon_utils import *
except:
    import sys

    print("Unable to import inmon utils")
    sys.exit(3)

import subprocess
import re
import psutil
import copy


def check_intools(config):
    """Checks to make sure that all intools services are running

    Arguments:
    config -- Object in the following format:
    {'check_intools': {
        'root': {
            'service1': {
                'all': ['servicename1', 'servicename2']
            },
            'service2': {
                'any': ['servicename3', 'servicename4']
            },
            'service3': {
                'all': ['servicename5', 'servicename6'],
                'any': ['servicename7', 'servicename8']
            }
        },
        'user': {
            'service1': {
                'all': ['servicename1', 'servicename2']
            },
            'service2': {
                'any': ['servicename3', 'servicename4']
            },
            'service3': {
                'all': ['servicename5', 'servicename6'],
                'any': ['servicename7', 'servicename8']
            }
        }
    }}

    Services under root are any services that should be running as root
    Any services under user will be checked against all users currently logged in
    'all' defines an array, length >= 1, where all services in the array must be running
    'any' defines an array, length >= 1, where any services in the array must be running
    Multiple service set definitions (e.g. an all and an any) will be compounded via AND,
    e.g. all services in the all statement AND any services in the any statement.
    """

    # Process:
    # Get logged in users
    # Check system services for root
    # Check user services for each user

    logged_in_users = subprocess.check_output(
        ["last"]
    )  # Get list of all logged in users
    logged_in_users = logged_in_users.decode().split("\n")  # Process output to lines
    logged_in_users = [
        line.split() for line in logged_in_users
    ]  # Split each line by whitespace

    # Get usernames for users that are logged in at console
    logged_in_users = [
        line[0] for line in logged_in_users if "console" in line and "logged" in line
    ]
    for user in logged_in_users:
        service_names[user] = copy.deepcopy(user_services)

    process_dict = []

    # Go through processes and add them to the process dict
    for process in psutil.process_iter(["name", "username"]):
        process_dict.append(process.info)

    services_status = {}

    # Go through the services and match them up.
    for user in service_names:
        services_status[user] = {}
        for service in service_names[user]:
            services_status[user][service] = {}
            for service_set in service_names[user][service]:
                services_status[user][service][service_set] = []
                for sub_service in service_names[user][service][service_set]:
                    for item in process_dict:
                        if item["name"] == sub_service and item["username"] == user:
                            services_status[user][service][service_set].append(True)
                            break
                    else:
                        services_status[user][service][service_set].append(False)
                if service_set == "all" and all(
                    services_status[user][service][service_set]
                ):
                    services_status[user][service][service_set] = True
                elif service_set == "any" and any(
                    services_status[user][service][service_set]
                ):
                    services_status[user][service][service_set] = True
                else:
                    services_status[user][service][service_set] = False

    return_text = ""
    return_status = 0

    for user in services_status:
        for service in services_status[user]:
            if not all(
                [
                    services_status[user][service][val]
                    for val in services_status[user][service]
                ]
            ):
                return_text += f"{user}-{service}; "
                return_status = 2

    if return_status == 0:
        return (0, f"[OK] - All INtools services are nominal.")
    elif return_status == 2:
        return (
            2,
            f"[CRIT] - The following services are not running: {return_text.rsplit('; ', 1)[0]}",
        )
