#!/usr/lib/python3/dist-packages/sylk-pushserver/bin/python
import argparse
import logging
import os
import sys
import uvicorn
from pushserver import __info__ as package_info

from application.process import process
from application import log
from pushserver.resources import settings
from pushserver.resources.utils import (log_event, resources_available,
                                        ssl_cert, try_again)

name = 'sylk-pushserver'
fullname = "Sylk Pushserver"

logging.getLogger("uvicorn").setLevel(logging.WARN)

default_dir = '/etc/sylk-pushserver'

parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-h', '--help',
                    action='help',
                    default=argparse.SUPPRESS,
                    help='Show this help message and exit.')

parser.add_argument("--ip",
                    default='',
                    help="If set, server will run in its address")

parser.add_argument("--port",
                    default='',
                    help="If set, server will run in its address")

parser.add_argument("--config_dir",
                    default=None,
                    metavar='PATH',
                    help="Specify a config directory that contains "
                         "general.ini, applications.ini and "
                         "the credentials directory, "
                         "Default it uses '/etc/sylk-pushserver'")

parser.add_argument('--no-fork',
                    action='store_false',
                    dest='fork',
                    help='log and run in the foreground')

parser.add_argument("--debug",
                    action="store_true",
                    default=False,
                    help="If set, log headers and body requests to log file.")

args = parser.parse_args()

if args.fork:
    try:
        from cysystemd.journal import JournaldLogHandler
    except ImportError:
        from systemd.journal import JournalHandler

    try:
        journal_handler = JournaldLogHandler()
    except NameError:
        journal_handler = JournalHandler(SYSLOG_IDENTIFIER='sylk-pushserver')

    log.set_handler(journal_handler)
    log.capture_output()

root_logger = log.get_logger()
root_logger.name = name

if not args.fork:
    console_formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
    log.set_default_formatter(console_formatter)

log.info('Starting %s %s' % (fullname, package_info.__version__))
config_dir = default_dir

if args.config_dir is not None:
    if not os.path.exists(f'{args.config_dir}'):
        log.info('Specified config directory does not exist')
        sys.exit(1)
    config_dir = args.config_dir

settings.init(config_dir, args.debug, args.ip, args.port)

# Since TokenStorage config relies on the config_dir it has to be imported here
process.configuration.local_directory = config_dir
from pushserver.resources.storage import TokenStorage

if __name__ == '__main__':

    if not settings.params.dir['error'] or 'default' in settings.params.dir['error']:
        storage = TokenStorage()
        storage.load()
        sock_available = False
        while not sock_available:
            host = settings.params.server['host']
            port = int(settings.params.server['port'])
            tls_cert = settings.params.server['tls_cert']
            sock_available = resources_available(host, port)
            if sock_available:
                if tls_cert:
                    if ssl_cert(tls_cert):
                        msg = 'Starting app over SSL...'
                        print(msg)
                        log_event(loggers=settings.params.loggers,
                                  msg=msg, level='info')
                        uvicorn.run('pushserver.resources.app:app', host=host,
                                    port=port, ssl_certfile=tls_cert,
                                    acces_log=False, log_level='error')
                        break
                    else:
                        msg = f'{tls_cert} is not a valid ssl cert, app will be run without it'
                        print(msg)
                        log_event(loggers=settings.params.loggers,
                                  msg=msg, level='deb')
                        uvicorn.run('pushserver.resources.server:server',
                                    host=host, port=port,
                                    access_log=False, log_level='error')
                        break
                else:
                    uvicorn.run('pushserver.resources.server:server',
                                host=host, port=port,
                                access_log=False, log_level='error')
                    break
            else:
                try_again(timer=30,
                          host=host, port=port,
                          start_error=settings.params.dir['error'],
                          loggers=settings.params.loggers)

    else:
        log_event(loggers=settings.params.loggers,
                  msg=settings.params.dir['error'],
                  level='error')
        print(settings.params.dir['error'])
