import os
import yaml
import werkzeug
import logging
import pyuwsgi
import argparse

from flask import Flask

from sandbox.serviceapi import plugins as serviceapi_plugins
from load.projects.lunaparkapi.database.models import db
from load.projects.lunaparkapi.settings import base
from load.projects.lunaparkapi.plugins import openapi as lunapi_openapi


def rule_wrapper(rule, **kwargs):
    if kwargs.pop("accept_all_methods", False):
        kwargs["methods"] = None
    return werkzeug.routing.Rule(rule, **kwargs)


def indent_text(text, indent, indent_char=' '):
    return ''.join(indent * indent_char + line + '\n' for line in text.splitlines())


def setup_logging():
    handler = logging.StreamHandler()
    handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)-7s (%(pathname)s:%(lineno)s) %(message)s'))

    logging.root.handlers = []  # Somebody could have already initialized logging
    logging.root.addHandler(handler)
    logging.root.setLevel(logging.DEBUG)

    # Make noisy libraries less noisy
    logging.getLogger('requests.packages.urllib3').setLevel(logging.ERROR)
    logging.getLogger('urllib3.connectionpool').setLevel(logging.WARNING)
    logging.getLogger('tvm2.sync').setLevel(logging.WARNING)


def dump_config(config, indent=2):
    sharedareas = config['uwsgi'].pop('sharedareas')
    # mules = config["uwsgi"].pop("mules")

    config = yaml.dump(config, Dumper=IndentDumper, default_flow_style=False, indent=indent)

    config += indent_text(sharedareas, indent)
    # config += indent_text(mules, indent)

    return config


class IndentDumper(yaml.Dumper):
    def increase_indent(self, flow=False, indentless=False):
        return super(IndentDumper, self).increase_indent(flow, False)


def get_uwsgi_yaml_config(args):
    from library.python import resource
    config = yaml.load(resource.find('lunaparkapi/uwsgi.yaml'), Loader=yaml.CSafeLoader)
    uwsgi = config['uwsgi']

    # Override defaults
    port = args.port or 5000
    uwsgi['http-socket'] = '[::]:{}'.format(port)
    return dump_config(config)


def get_uwsgi_args(args):
    r, w = os.pipe()
    os.write(w, get_uwsgi_yaml_config(args))
    os.close(w)

    return ['--yaml', 'fd://' + str(r)]


def create_app():
    setup_logging()

    app = Flask('lunaparkapi')
    app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}?sslmode=require'.format(
        **base)
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    app.url_rule_class = rule_wrapper

    db.init_app(app)

    serviceapi_plugins.context.init_plugin(app)
    lunapi_openapi.init_plugin(app)

    from . import web
    web.init_api(app)

    @app.route('/')
    def index():
        return 'pysch pysch'

    return app


def main():

    parser = argparse.ArgumentParser()
    parser.add_argument('-v', '--version', action='store_true', help='Print version')
    parser.add_argument('-p', '--port', type=int, help='Http port')
    parser.add_argument('-w', '--workers', type=int, help='Number of workers')
    parser.add_argument('--stderr-log', help='Write logs to stderr', action='store_true')
    args = parser.parse_args()

    pyuwsgi.run(get_uwsgi_args(args))


if __name__ == '__main__':
    pyuwsgi.run(['--yaml', 'uwsgi.yaml', '--module', 'app:create_app()', '--stderr-log'])
