#! /usr/bin/env python3
import getopt
import logging
import os
import sys
import yaml
import socket


import aj
import aj.config
import aj.entry
import aj.log
import aj.plugins


# Is the ajenti virtualenv installed ?
panel_venv = '/opt/ajenti/bin/ajenti-panel'
if os.path.isfile(panel_venv) and os.path.abspath(__file__) != panel_venv:
    logging.info('Ajenti virtualenv detected, switching to it.')
    try:
        os.execv(panel_venv, sys.argv)
    except Exception:
        logging.error('Unable to start ajenti virtualenv, continuing with global python.')

class AjentiConfig(aj.config.BaseConfig):
    def __init__(self, path):
        aj.config.BaseConfig.__init__(self)
        self.data = None
        self.path = os.path.abspath(path)

    def __str__(self):
        return self.path

    def load(self):
        if os.geteuid() == 0:
            os.chmod(self.path, 384)  # 0o600
        self.data = yaml.load(open(self.path), Loader=yaml.Loader)

    def save(self):
        with open(self.path, 'w') as f:
            f.write(yaml.safe_dump(self.data, default_flow_style=False, encoding='utf-8', allow_unicode=True).decode('utf-8'))


def usage():
    print(f"""
Usage: {sys.argv[0]} [options]
Options:
    -c, --config <file> - Use given config file instead of default
    -v                  - Debug/verbose logging ( shortcut for --log debug )
    --dev               - Dev mode (recompile resources)
    -d, --daemon        - Run in background (daemon mode)
    --stock-plugins     - Load plugins from PYTHONPATH
    --plugins <dir>     - Load plugins from a directory
    --autologin         - Log in automatically as the running user
    --log '<level>'     - Fix log level : debug, info, warning or error
    -h, --help          - This help
    """)


if __name__ == '__main__':
    log_levels = {"debug": logging.DEBUG, "info": logging.INFO, "warning": logging.WARNING, "error": logging.ERROR}
    log_level = logging.INFO
    daemonize = False
    dev_mode = False
    debug_mode = False
    config_path = None
    autologin = False
    plugin_providers = []

    try:
        opts, args = getopt.getopt(
            sys.argv[1:],
            'hc:dv',
            ['help', 'config=', 'daemon', 'dev', 'stock-plugins', 'plugins=', 'autologin', 'log=']
        )
    except getopt.GetoptError as e:
        print(str(e))
        usage()
        sys.exit(2)

    for o, a in opts:
        if o in ('-h', '--help'):
            usage()
            sys.exit(0)
        elif o in ('-v',):
            log_level = logging.DEBUG
            debug_mode = True
        elif o in ('--dev',):
            log_level = logging.DEBUG
            debug_mode = True
            dev_mode = True
        elif o in ('--log',):
            log_level = log_levels[a]
        elif o in ('-c', '--config'):
            config_path = a
        elif o in ('-d', '--start'):
            daemonize = True
        elif o in ('--autologin',):
            autologin = True
        elif o == '--stock-plugins':
            plugin_providers.append(aj.plugins.PythonPathPluginProvider())
        elif o == '--plugins':
            plugin_providers.append(aj.plugins.DirectoryPluginProvider(a))

    if not plugin_providers:
        plugin_providers.append(aj.plugins.PythonPathPluginProvider())

    aj.log.init_console(log_level)

    if autologin and not debug_mode:
        logging.error('Autologin is a dangerous option and should be used together with -v')
        sys.exit(1)

    users_file = '/etc/ajenti/users.yml'
    smtp_file = '/etc/ajenti/smtp.yml'

    if not os.path.exists('/etc/ajenti'):
        os.makedirs('/etc/ajenti')

    if not os.path.exists(users_file):
        with open(users_file, 'w') as u:
            u.write("users: null")

    if not os.path.exists(smtp_file):
        with open(smtp_file, 'w') as u:
            u.write("""smtp:
  password: ''
  port: starttls
  server: ''
  user: ''
""")

    # Find default config file
    if not config_path:
        # Check for config file in /etc/ajenti/config.yml
        if os.path.isfile('/etc/ajenti/config.yml'):
            config_path = '/etc/ajenti/config.yml'
        elif os.path.isfile(os.path.join(sys.path[0], 'config.yml')):
            # Try local config file
            config_path = os.path.join(sys.path[0], 'config.yml')

    if not os.path.exists(config_path):
        logging.warning(f'No config file found, creating a new one /etc/ajenti/config.yml')

        with open(config_path, 'w') as c:
            c.write(f'''
auth:
  allow_sudo: true
  emails: {{}}
  provider: os
  users_file: {users_file}
bind:
  host: 0.0.0.0
  mode: tcp
  port: 8000
color: default
max_sessions: 9
trusted_domains: []
trusted_proxies: []
session_max_time: 3600
name: {socket.gethostname()}
ssl:
  certificate:
  fqdn_certificate:
  force: false
  client_auth:
    certificates: []
    enable: false
    force: false
  enable: false
        ''')

    aj.entry.start(
        config=AjentiConfig(config_path),
        dev_mode=dev_mode,
        debug_mode=debug_mode,
        autologin=autologin,
        product_name='ajenti',
        daemonize=daemonize,
        plugin_providers=plugin_providers,
        log_level=log_level,
    )
