"""
    polaris.server
    ~~~~~~~~~~~~~~

    :copyright: (c) 2013 Eleme, http://polaris.eleme.io
    :license: MIT

    Polaris app server.
"""

import hashlib
import os.path

from flask import Flask as _Flask
from werkzeug.datastructures import ImmutableDict
from werkzeug.utils import import_string

__all__ = ['create_app']


class Flask(_Flask):
    jinja_options = ImmutableDict(
        trim_blocks=True,
        lstrip_blocks=True,
        extensions=[
            'jinja2.ext.autoescape',
            'jinja2.ext.with_',
        ]
    )


def create_app(config=None):
    app = Flask(__name__)
    app.config.from_object("polaris.defaults")

    # try to find config in $PWD, and "/etc/".
    if not config:
        for path in ("%s/" % os.getcwd(), "/etc/", ):
            fname = os.path.join(path, "polaris_config.py")
            if os.path.isfile(fname):
                config = fname
                break

    if config:
        if isinstance(config, str) and config.endswith(".py"):
            app.config.from_pyfile(config)
        else:
            app.config.from_object(config)

    register_extensions(app)
    register_blueprints(app)

    ##########
    # Dogpile Cache

    from dogpile.cache import make_region
    from polaris.utils import kw_generator

    region = make_region(function_key_generator=kw_generator).configure(
        **app.config["CACHE"])
    app.config["cache_region"] = region

    ##########
    # Register sources

    app.config["ext"] = {}
    for name, path in app.config["EXTENSIONS"].items():
        app.config["ext"][name] = import_string(path)

    app.config["source"] = {}
    app.config["category"] = {}
    for name, cfg in app.config["SOURCES"].items():
        source = app.config["ext"][cfg["ext"]](**cfg["params"])
        app.config["source"][name] = source
        app.config["category"][name] = source.category

    register_jinja(app)
    return app


def register_jinja(app):
    app._assets = app.config.get('ASSETS', {})

    def static_url(filename):
        if app.testing:
            return filename

        if filename in app._assets:
            return app._assets[filename]

        filepath = os.path.join(app.static_folder, filename)
        if not os.path.exists(filepath):
            app.logger.warn('%s not exists', filepath)
            return filename

        with open(os.path.join(app.static_folder, filename), 'r') as f:
            content = f.read()
            hsh = hashlib.md5(content.encode('utf-8')).hexdigest()

        app.logger.info('Generate %s md5sum: %s' % (filename, hsh))
        value = '/static/%s?v=%s' % (filename, hsh)
        app._assets[filename] = value
        return value

    app.jinja_env.globals['static_url'] = static_url


def register_extensions(app):
    from polaris.models import db
    db.init_app(app)
    db.app = app

    from polaris.auth.oauth import oauth
    oauth.init_app(app)

    from polaris.auth.login import login
    login.init_app(app)

    from polaris.auth.form import csrf
    csrf.init_app(app)

    # Babel for internationalization
    from flask import current_app, request
    from flask_babel import Babel
    babel = Babel(app)

    @babel.localeselector
    def get_locale():
        return request.accept_languages.best_match(
            current_app.config["BABEL_SUPPORTED_LOCALE"])


def register_blueprints(app):
    from polaris.views import (
        api,
        chart,
        dashboard,
        errors,
        index,
        profile,
    )
    app.register_blueprint(api)
    app.register_blueprint(index)
    app.register_blueprint(chart)
    app.register_blueprint(dashboard)
    app.register_blueprint(errors)
    app.register_blueprint(profile)
