from flask import Flask, render_template
from flask.ext.misaka import Misaka
from flask.ext.migrate import Migrate
from flask.ext.sqlalchemy import SQLAlchemy
from flask_kvsession import KVSessionExtension
from flask_wtf.csrf import CsrfProtect


db = SQLAlchemy()
md = Misaka()
csrf = CsrfProtect()
migrate = Migrate()
session = KVSessionExtension()


def create_app(config):
    app = Flask(
        __name__.split('.')[0],
        static_url_path='',
        static_folder='../public',
        template_folder='frontend/templates'
    )

    app.config.from_object(config)
    app.jinja_env.lstrip_blocks = True
    app.jinja_env.trim_blocks = True
    app.jinja_env.auto_reload = app.config["JINJA_AUTO_RELOAD"]

    register_blueprints(app)
    register_errorhandlers(app)
    register_extensions(app)
    register_template_functions(app)

    return app


def register_blueprints(app):
    from . import controllers

    for name in dir(controllers):
        if not name.startswith("__"):
            app.register_blueprint(getattr(controllers, name).blueprint)


def register_errorhandlers(app):
    def render_error(error):
        error_code = getattr(error, 'code', 500)
        return render_template('errors/{}.jinja'.format(error_code)), error_code

    for errcode in [403, 404, 500]:
        app.errorhandler(errcode)(render_error)


def register_extensions(app):
    db.init_app(app)
    md.init_app(app)
    csrf.init_app(app)
    migrate.init_app(app, db)
    session.init_app(app, app.config["STORE"])


def register_template_functions(app):
    from . import template

    # TODO: Implement this in a sane manner
    for name in dir(template.TemplateGlobals):
        if not name.startswith("__"):
            app.context_processor(getattr(template.TemplateGlobals, name))

    for name in dir(template.TemplateFunctions):
        if not name.startswith("__"):
            app.add_template_global(getattr(template.TemplateFunctions, name))

    for name in dir(template.TemplateFilters):
        if not name.startswith("__"):
            app.add_template_filter(getattr(template.TemplateFilters, name))
