from functools import wraps
import json

from werkzeug.utils import redirect

import APIFactory
from app import user
import config
from models import UserEncoder
import providers


__author__ = 'hanl'

from flask import Flask, render_template, request, session, url_for, flash, current_app, Blueprint
from flask_email import LocmemMail
from flask_babel import Babel
from flask_login import LoginManager, current_user

app = Flask(__name__)

lm = LoginManager(app)
babel = Babel(app)
# admin = Admin(app)
mail = LocmemMail(app)

router = Blueprint('app', __name__,
                   template_folder='templates')


@router.route('/lang/<language>')
def set_locale(lang=None):
    setattr(session, 'lang', lang)
    return render_template(url_for('index'), lang_code=lang)


@babel.localeselector
def get_locale():
    browser_locale = request.accept_languages.best_match(app.config.get('LANGUAGES'), default="de")
    lang = session.get('lang', browser_locale)
    setattr(session, 'lang', lang)
    return lang


def secured(func):
    '''
    overriding login_required, but redirects to login, not to unauthorized page
    :param func:
    :return:
    '''

    @wraps(func)
    def decorated_view(*args, **kwargs):
        print "args %s" % str(args)
        print "kwargs %s" % str(kwargs)
        print "func %s" % str(func)
        if current_app.login_manager._login_disabled:
            return func(*args, **kwargs)
        elif not current_user.is_authenticated():
            # fixme: how to set next?
            # request.args.get('next') or
            return redirect(url_for('.login'))
        return func(*args, **kwargs)

    return decorated_view


@lm.user_loader
def load_user(username):
    # either from session of via rest; cache if possible
    return providers.PROVIDER.get_user(session)


# used to override the cookie encryption behaviour
# @lm.token_loader
def load_token(token):
    return providers.PROVIDER.get_user()


@router.route('/')
def index():
    return render_template('index.html', lang_code=get_locale())


@router.route('/search', methods=['GET'])
@secured
def search():
    if request.method == "GET":
        data = request.args
        print "has query %s" % str(data)
        if 'q' in data:
            # auth=APIFactory.Oauth2Auth(session['access_token'])
            response = APIFactory.get("search", params=data)
            if response is None:
                pass
            elif providers.NotificationHandler.isError(response):
                providers.NotificationHandler.notify(response.json(), flash)
            else:
                raw_json = response.json()
                return render_template('search.html', lang=app.config.get('QUERY_LANGUAGES'),
                                       q=data['q'], ql=data['ql'], result=raw_json,
                                       result_string=json.dumps(raw_json, indent=4))
    return render_template('search.html', lang=app.config.get('QUERY_LANGUAGES'),
                           q=None, ql=None,
                           result=None)


@router.route('/serialize', methods=['GET', 'POST'])
@secured
def serialize():
    return render_template('search.html')


# @router.app_errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404


if __name__ == '__main__':
    import admin

    app.config.from_object(config)
    app.json_encoder = UserEncoder
    app.debug = config.DEBUG
    app.register_blueprint(router, url_prefix='/app')
    app.register_blueprint(user.router, url_prefix='/user')
    app.register_blueprint(admin.router, url_prefix='/admin')
    providers.init_app(app.config)
    app.run()


