#!/usr/bin/env python3.6
import configparser
import logging
import logging.handlers
import os
import platform
import sys
import time

import sau
import sau.services
import sau.platforms

def init():
    sau.config = configparser.SafeConfigParser()
    conf = sau.config

    if platform.system() == 'FreeBSD':
        syslog_socket = '/var/run/log'
        conf_file = '/usr/local/etc/sau.cfg'
    else:
        syslog_socket = '/dev/log'
        conf_file = '/etc/sau.cfg'

    if os.path.isfile(conf_file):
        conf.read(conf_file)

    log = logging.getLogger(sau.LOGNAME) 
    log.setLevel(logging.DEBUG)

    conf_level = _conf_level_to_logging_level(conf.get('default', 'stderr_loglevel', fallback="debug"))
    handler = logging.StreamHandler()
    formatter = logging.Formatter(fmt='%(asctime)s %(levelname)s: %(message)s')
    handler.setFormatter(formatter)
    handler.setLevel(conf_level)
    log.addHandler(handler)


    conf_level = _conf_level_to_logging_level(conf.get('default', 'syslog_loglevel', fallback="debug"))
    handler = logging.handlers.SysLogHandler(address=syslog_socket)
    formatter = logging.Formatter(fmt='{}[%(process)s] %(message)s'.format(sau.LOGNAME))
    handler.setFormatter(formatter)
    handler.setLevel(conf_level)
    log.addHandler(handler)


def fork_and_reboot():
    log = logging.getLogger(sau.LOGNAME)
    try:
        pid = os.fork()
        if pid != 0:
            sys.exit(0)
    except OSError as err:
        log.error("Fork #1 failed when going for reboot: {}".format(err))
        sys.exit(1)

    os.chdir('/')
    os.setsid()
    os.umask(0)

    try:
        pid = os.fork()
        if pid != 0:
            sys.exit(0)
    except OSError as err:
        log.error("Fork #2 failed when going for reboot: {}".format(err))
        sys.exit(1)

    sys.stdout.flush()
    sys.stderr.flush()
    stdin = open(os.devnull, 'r')
    stdout = open(os.devnull, 'a+')
    stderr = open(os.devnull, 'a+')

    os.dup2(stdin.fileno(), sys.stdin.fileno())
    os.dup2(stdout.fileno(), sys.stdout.fileno())
    os.dup2(stderr.fileno(), sys.stderr.fileno())

    log.warning("New fork!")

    # sleep for a short while to give parent time to exit
    time.sleep(30)
    try:
        #log.error('would reboot now')
        os.execv('/sbin/reboot', ['/sbin/reboot'])
    except OSError as err:
        log.error('Could not reboot: {}'.format(err))
    sys.exit(1)

def main():
    conf = sau.config
    log = logging.getLogger(sau.LOGNAME)
    platform = sau.platforms.get_platform()

    reboot_required = False
    reboot_recommended = False

    if conf.getboolean('default', 'do_system_upgrade', fallback=True):
        reboot_required = platform.system_upgrade()

    if conf.getboolean('default', 'do_package_upgrade', fallback=True):
        platform.pkg_upgrade()

    if conf.getboolean('default', 'do_service_restart', fallback=True):
        reboot_recommended = sau.services.restart_services()

    if conf.getboolean('default', 'do_reboot', fallback=False):
        if reboot_required:
            log.warning('Rebooting because of a system upgrade')
        elif reboot_recommended:
            log.warning('Rebooting because service restarts did not close all deleted files')
        if reboot_required or reboot_recommended:
            fork_and_reboot()

def _conf_level_to_logging_level(conf_level):
    if conf_level.lower() == 'debug':
        return logging.DEBUG
    if conf_level.lower() == 'info':
        return logging.INFO
    if conf_level.lower() == 'warning':
        return logging.WARNING
    if conf_level.lower() == 'error':
        return logging.error
    return logging.DEBUG
    
if __name__ == '__main__':
    init()
    sys.exit(main())
