from functools import wraps
import json

from flask_admin import Admin
from werkzeug.utils import redirect

import APIFactory
import messaging
from models import SigninForm, SignupForm, UserEncoder, ProfileForm, AdminView
from providers import User
import providers


__author__ = 'hanl'

from flask import Flask, render_template, request, session, url_for, flash, current_app

from flask_babel import Babel, gettext as _
from flask_login import LoginManager, logout_user, login_user, current_user
import config

lm = LoginManager()
babel = Babel()
admin = Admin()

app = Flask(__name__)
message_handler = messaging.NotificationHandler()
providers.load_provider(config.AUTH_PROVIDER, message_handler)

app.config.from_object(config)
app.json_encoder = UserEncoder
app.debug = config.DEBUG

admin.init_app(app)
babel.init_app(app)
lm.init_app(app)

admin.add_view(AdminView())

# @app.before_request
@app.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(config.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):
        if current_app.login_manager._login_disabled:
            return func(*args, **kwargs)
        elif not current_user.is_authenticated():
            # fixme: how to set next?
            return redirect(request.args.get('next') or 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(username, session)


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


@app.route('/profile', methods=['GET', 'POST'])
@secured
def profile():
    user = providers.provider.get_user(session['user_id'], session, True)
    form = ProfileForm(obj=user)
    if request.method == 'POST':
        pass
    elif request.method == 'GET':
        return render_template('profile.html', form=form, submit=_('Update'))


@app.route('/profile/<user>', methods=['GET'])
def user_profile(user=None):
    user = User(username=user)
    form = ProfileForm(obj=user)
    if request.method == 'POST':
        pass
    elif request.method == 'GET':
        return render_template('profile.html', form=form, submit=_('Update'))


@app.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 message_handler.isError(response):
                message_handler.notifyNext(response.json(), flash)
            else:
                raw_json = response.json()
                return render_template('search.html', lang=config.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=config.QUERY_LANGUAGES,
                           q=None, ql=None,
                           result=None)


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


@app.route('/login', methods=['GET', 'POST'])
def login():
    form = SigninForm()
    if request.method == 'POST':
        if not form.validate():
            print "unsuccessful validation"
            return render_template('login.html', form=form)
        else:
            user = User(username=form.username.data, password=form.password.data)
            success = providers.provider.login(session, user)
            if success:
                login_user(user)
            else:
                return redirect(url_for('login'))
            print "the data serialized %s" % json.dumps(user, cls=UserEncoder)
            return redirect(request.args.get('next') or url_for('profile'))
    elif request.method == 'GET':
        return render_template('login.html', form=form, submit=_('sign in'))


@app.route('/logout')
@secured
def logout():
    if not providers.provider.logout(session):
        redirect(url_for('login'))
    logout_user()
    return redirect(url_for('index'))


@app.route('/signup', methods=['GET', 'POST'])
def signup():
    form = SignupForm()
    if request.method == 'POST':
        if not form.validate():
            print "unsuccessful validation"
            return render_template('signup.html', form=form)
        else:
            passw = form.password.data
            newuser = User(firstName=form.firstName.data, lastName=form.lastName.data,
                           email=form.email.data, username=form.username.data,
                           institution=form.institution.data, phone=form.phone.data,
                           address=form.address.data)
            response = APIFactory.post("user/register")

    elif request.method == 'GET':
        return render_template('signup.html', form=form, submit=_('sign up'))


@app.route('/reset', methods=['POST'])
def reset():
    pass


@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404


if __name__ == '__main__':
    app.run()