#!/usr/bin/env python3
# *-* coding: utf-8 *-*

# This file is part of butterfly
#
# butterfly Copyright(C) 2015-2017 Florian Mounier
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import tornado.options
import tornado.ioloop
import tornado.httpserver
try:
    from tornado_systemd import SystemdHTTPServer as HTTPServer
except ImportError:
    from tornado.httpserver import HTTPServer

import logging
import webbrowser
import uuid
import ssl
import getpass
import os
import shutil
import stat
import socket
import sys

tornado.options.define("debug", default=False, help="Debug mode")
tornado.options.define("more", default=False,
                       help="Debug mode with more verbosity")
tornado.options.define("unminified", default=False,
                       help="Use the unminified js (for development only)")

tornado.options.define("host", default='localhost', help="Server host")
tornado.options.define("port", default=57575, type=int, help="Server port")
tornado.options.define("keepalive_interval", default=30, type=int,
                       help="Interval between ping packets sent from server "
                       "to client (in seconds)")
tornado.options.define("one_shot", default=False,
                       help="Run a one-shot instance. Quit at term close")
tornado.options.define("shell", help="Shell to execute at login")
tornado.options.define("motd", default='motd', help="Path to the motd file.")
tornado.options.define("cmd",
                       help="Command to run instead of shell, f.i.: 'ls -l'")
tornado.options.define("unsecure", default=False,
                       help="Don't use ssl not recommended")
tornado.options.define("i_hereby_declare_i_dont_want_any_security_whatsoever",
                       default=False,
                       help="Remove all security and warnings. There are some "
                       "use cases for that. Use this if you really know what "
                       "you are doing.")
tornado.options.define("login", default=False,
                       help="Use login screen at start")
tornado.options.define("pam_profile", default="", type=str,
                       help="When --login=True provided and running as ROOT, "
                       "use PAM with the specified PAM profile for "
                       "authentication and then execute the user's default "
                       "shell. Will override --shell.")
tornado.options.define("force_unicode_width",
                       default=False,
                       help="Force all unicode characters to the same width."
                       "Useful for avoiding layout mess.")
tornado.options.define("ssl_version", default=None,
                       help="SSL protocol version")
tornado.options.define("generate_certs", default=False,
                       help="Generate butterfly certificates")
tornado.options.define("generate_current_user_pkcs", default=False,
                       help="Generate current user pfx for client "
                       "authentication")
tornado.options.define("generate_user_pkcs", default='',
                       help="Generate user pfx for client authentication "
                       "(Must be root to create for another user)")
tornado.options.define("uri_root_path", default='',
                       help="Sets the servier root path: "
                       "example.com/<uri_root_path>/static/")


if os.getuid() == 0:
    ev = os.getenv('XDG_CONFIG_DIRS', '/etc')
else:
    ev = os.getenv(
        'XDG_CONFIG_HOME', os.path.join(
            os.getenv('HOME', os.path.expanduser('~')),
            '.config'))

butterfly_dir = os.path.join(ev, 'butterfly')
conf_file = os.path.join(butterfly_dir, 'butterfly.conf')
ssl_dir = os.path.join(butterfly_dir, 'ssl')

tornado.options.define("conf", default=conf_file,
                       help="Butterfly configuration file. "
                       "Contains the same options as command line.")

tornado.options.define("ssl_dir", default=ssl_dir,
                       help="Force SSL directory location")

# Do it once to get the conf path
tornado.options.parse_command_line()

if os.path.exists(tornado.options.options.conf):
    tornado.options.parse_config_file(tornado.options.options.conf)

# Do it again to overwrite conf with args
tornado.options.parse_command_line()

# For next time, create them a conf file from template.
# Need to do this after parsing options so we do not trigger
# code import for butterfly module, in case that code is
# dependent on the set of parsed options.
if not os.path.exists(conf_file):
    try:
        import butterfly
        shutil.copy(
            os.path.join(
                os.path.abspath(os.path.dirname(butterfly.__file__)),
                'butterfly.conf.default'), conf_file)
        print('butterfly.conf installed in %s' % conf_file)
    except:
        pass

options = tornado.options.options

for logger in ('tornado.access', 'tornado.application',
               'tornado.general', 'butterfly'):
    level = logging.WARNING
    if options.debug:
        level = logging.INFO
        if options.more:
            level = logging.DEBUG
    logging.getLogger(logger).setLevel(level)

log = logging.getLogger('butterfly')

host = options.host
port = options.port

if options.i_hereby_declare_i_dont_want_any_security_whatsoever:
    options.unsecure = True


if not os.path.exists(options.ssl_dir):
    os.makedirs(options.ssl_dir)


def to_abs(file):
    return os.path.join(options.ssl_dir, file)


ca, ca_key, cert, cert_key, pkcs12 = map(to_abs, [
    'butterfly_ca.crt', 'butterfly_ca.key',
    'butterfly_%s.crt', 'butterfly_%s.key',
    '%s.p12'])