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

import logging
import sys
import argparse
import socket
import time
import os

import flask
import jinja2
import gunicorn.app.base

from backend.blueprints.ssm_viewer_page import ssm_viewer_page
from backend.blueprints.ping_page import ping_page
from backend.blueprints.quotas import quotas

from saas.library.python import errorbooster
from saas.tools.ssm.modules.misc import load_resources, load_and_write_resources


load_and_write_resources('/conf')
load_and_write_resources('/static')

reload(sys)
sys.setdefaultencoding('utf8')

logger = logging.getLogger()


def create_flask_app(passport_disabled=False, csrf_enabled=True):

    fqdn = socket.getfqdn()

    app = flask.Flask(__name__)
    app.jinja_loader = jinja2.DictLoader(dict(load_resources('/jinja')))
    app.secret_key = 'fd$%#S$@2BGd465grgr?///s56633256ers2sAAAe4GG'
    app.config['WTF_CSRF_ENABLED'] = csrf_enabled
    app.config['WTF_CSRF_TIME_LIMIT'] = 86400
    app.config['SESSION_COOKIE_SECURE'] = True
    app.config['REMEMBER_COOKIE_SECURE'] = True
    app.config['PASSPORT_OFF'] = passport_disabled
    app.config['PASSPORT_LOGIN_URL'] = 'https://passport.yandex-team.ru/login'
    app.config['PASSPORT_TVM_ID'] = os.environ.get('TVM_PASSPORT_ID', 2011828)
    app.config['PASSPORT_TVM_SECRET'] = os.environ.get('TVM_PASSPORT_SECRET')
    app.config['BASE_HOST'] = 'ssm.n.yandex-team.ru'

    app.register_blueprint(ping_page)
    app.register_blueprint(ssm_viewer_page)
    app.register_blueprint(quotas, url_prefix='/quotas')

    errorbooster.ErrorBooster('saas-ssm')

    @app.before_request
    def before():
        try:
            flask.request.start_time = time.time()
        except Exception as e:
            logger.exception(e)

    @app.after_request
    def after(response):
        try:
            response.headers['X-HOST'] = fqdn
            stime_in_ms = str(int(1000 * (time.time() - flask.request.start_time)))
            response.headers['X-TIME'] = stime_in_ms
        except Exception as e:
            logger.exception(e)
        return response

    return app


class GunicornApp(gunicorn.app.base.BaseApplication):
    __slots__ = ('flask_app', 'host', 'port', 'workers', 'errorlog', 'accesslog')

    def __init__(self, flask_app, host, port, workers, errorlog=None, accesslog=None):
        self.flask_app = flask_app
        self.host = host
        self.port = port
        self.workers = workers
        self.errorlog = errorlog
        self.accesslog = accesslog
        super(GunicornApp, self).__init__()

    def load_config(self):
        self.cfg.set('workers', self.workers)
        bind_pattern = '[{}]:{}' if ':' in self.host else '{}:{}'
        self.cfg.set('bind', bind_pattern.format(self.host, self.port))
        if self.errorlog is not None:
            self.cfg.set('errorlog', self.errorlog)
        if self.accesslog is not None:
            self.cfg.set('accesslog', self.accesslog)
        self.cfg.set('worker_class', 'gunicorn.workers.gthread.ThreadWorker')

    def load(self):
        return self.flask_app


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--host', '-H', dest='host', default='0.0.0.0')
    parser.add_argument('-p', '--port', type=int, default=5000)
    parser.add_argument('-w', '--workers', type=int, default=1)
    parser.add_argument('-l', '--logfile')
    parser.add_argument('--disable-passport', action='store_true', default=False)
    parser.add_argument('--debug', action='store_true', default=False)
    options, unknown = parser.parse_known_args()

    handlers = [logging.StreamHandler()]
    if options.logfile:
        handlers.append(logging.FileHandler(options.logfile))
    formatter = logging.Formatter('[%(asctime)s SSM [%(process)d] [%(levelname)s] %(message)s',
                                  datefmt='%Y-%m-%d %H:%M:%S')
    for handler in handlers:
        handler.setFormatter(formatter)
        logger.addHandler(handler)
    logger.setLevel(logging.DEBUG)

    try:
        if options.debug:
            non_gunicorn(options.host, options.port, disable_passport=options.disable_passport)
        else:
            flask_app = create_flask_app(passport_disabled=options.disable_passport)
            flask_app.debug = True
            app = GunicornApp(flask_app, host=options.host, port=options.port, workers=options.workers,
                              errorlog=options.logfile, accesslog='-')
            app.run()
    except Exception as e:
        errorbooster.handle_flask_exception(e)
        logger.exception(e)
        raise


def non_gunicorn(hostname, portnum, disable_passport=False):
    flask_app = create_flask_app(passport_disabled=disable_passport)
    flask_app.debug = True
    flask_app.run(host=hostname, port=portnum, debug=True)


if __name__ == '__main__':
    main()
