#!/usr/bin/python3

'''
psconfig_hostmetrics_agent - Builds configuration for collecting host metrics from perfSONAR hosts based on pSConfig templates
'''

import pathlib

import os
parentdir = pathlib.Path(__file__).resolve().parents[1]

from psconfig.hostmetrics.agent import Agent
from psconfig.utilities.logging_utils import LoggingUtils
import pyinotify
import argparse
import time
import logging
import logging.config

##########
# set the process name
############################# not straight forward in python?

##########
# Parse command-line options
# Instantiate the parser
parser = argparse.ArgumentParser(description='psconfig_hostmetrics_agent')
parser.add_argument('--config', dest='CONFIG_FILE', action='store', required=True, help='configuration file')
parser.add_argument('--logger', dest='LOGGER_CONF', action='store', help='Logger Config', required=False)
parser.add_argument('--disable-inotify', dest='DISABLE_INOTIFY', action='store_true', help='disable inotify for file change detection.')
parser.add_argument('--verbose', dest='DEBUGFLAG', action='store_true', help='Add additional debug output')
############
#parser.add_argument('--help', dest='HELP', action='store', help='HELP')

args = parser.parse_args()

##########
# Now that we've dropped privileges, create the logger. If we do it in reverse
# order, the daemon won't be able to write to the logger.
logf = LoggingUtils()

if not args.LOGGER_CONF:

    output_level = logging.INFO
    if args.DEBUGFLAG:
        output_level = logging.DEBUG
    
    logging.basicConfig(level=output_level, format=logf.logging_format)
    logger = logging.getLogger('psconfig')

else:
    logging.config.fileConfig(args.LOGGER_CONF)
    logger = logging.getLogger("psconfig")

##########
# Create agent
agent = Agent()
agent.debug = args.DEBUGFLAG
if not agent.init(args.CONFIG_FILE):
    raise Exception('Error initializing agent: {}'.format(agent.error))

##########
# Setup Inotify2 on config files and directories
# NOTE: Don't watch requesting agent file because it may not exist
# NOTE: These do not work in well in container or VM shared directories. Use --disable-inotify
notifier = None
if not args.DISABLE_INOTIFY:
    watcher = pyinotify.WatchManager()
    watchMask = pyinotify.IN_MODIFY
    watcher.add_watch(args.CONFIG_FILE, watchMask) ############verify if file is registered
    watchMask2 = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY
    try:
        watcher.add_watch(agent.include_directory, watchMask2)
        logger.debug(logf.format('Watching include_directory {}.'.format(agent.include_directory)))
    except Exception as e:
        logger.debug(logf.format('Watching include_directory failed with error {}.'.format(agent.include_directory)))
    try:
        watcher.add_watch(agent.archive_directory, watchMask2)
        logger.debug(logf.format('Watching archive_directory {}.'.format(agent.archive_directory)))
    except Exception as e:
        logger.debug(logf.format('Watching archive_directory failed with error {}.'.format(agent.archive_directory)))
    try:
        watcher.add_watch(agent.transform_directory, watchMask2)
        logger.debug(logf.format('Watching transform_directory {}.'.format(agent.transform_directory)))
    except Exception as e:
        logger.debug(logf.format('Watching transform_directory failed with error {}.'.format(agent.transform_directory)))

    #create notifier
    notifier = pyinotify.Notifier(watcher, timeout=1)

    ##
# Start main program loop
logger.info(logf.format('Starting pSConfig Host Metrics agent'))

while(1):
    ###########
    #Initialize start
    start = time.time()

    #############
    #refresh configs
    logf.generate_guid() #generate new log id for run
    agent.logf.guid = logf.guid #pass to agent so guid consistent
    logger.info(logf.format("Running agent..."))
    agent.run()
    logger.info(logf.format("Agent completed running"))

    ###########
    # Sleep until its time to look for file updates or time to refesh
    end = time.time()
    until_next_refresh = agent.check_interval_seconds - (end - start)
    until_next_file_check = agent.check_config_interval_seconds
    if until_next_refresh < until_next_file_check:
        sleep_time = until_next_refresh
    else:
        sleep_time = until_next_file_check

    start = end
    while until_next_refresh > 0:
        time.sleep(sleep_time)

        if notifier and notifier.check_events():
            logger.info(logf.format("Configuration file change detected, refreshing records."))
            notifier.read_events()
            notifier.process_events()
            break
        else:
            end = time.time()
            until_next_refresh -= end-start
            start = end

#Exit the whole process
os._exit()
