from . import main
from ..models import User, Post
from flask import render_template, session, redirect, url_for, current_app, flash, abort, request, make_response
from threading import Thread
from .forms import NameForm, EditProfileForm, EditProfileAdminForm, PostForm, CommentForm
from .. import db, mail
from ..email import send_mail
from ..models import Permission, Follow, Comment
from ..decorators import permission_required, admin_required
from flask.ext.login import login_required, current_user
from flask.ext.sqlalchemy import get_debug_queries

@main.after_app_request
def after_request(response):
    for query in get_debug_queries():
        if query.duration >= current_app.config['FLASKY_SLOW_DB_QUERY_TIME']:
            current_app.logger.warning(
                'Slow query: %s\nParameters: %s\nDuration: %fs\nContext: %s\n' %
                (query.statement, query.nParameters, query.duration, query.context))
    return response

@main.route('/shutdown')
def server_shutdown():
    if not current_app.testing:
        abort(404)
    shutdown = request.environ.get('werkzeug.server.shutdown')
    if not shutdown:
        abort(500)
    shutdown()
    return 'Shutting down...'

@main.route('/old_index', methods=['GET', 'POST'])
def old_index():
    form = NameForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.name.data).first()
        if user is None:
            user = User(username=form.name.data)
            db.session.add(user)
            session['known'] = False
            # send e-mail to admin about receiving a new name
            if current_app.config['FLASKY_ADMIN']:
                send_mail(current_app.config['FLASKY_ADMIN'], 'New User', 'mail/new_user', user=user)
        else:
            session['known'] = True
        session['name'] = form.name.data
        return redirect(url_for('.index'))
    return render_template('old_index.html',
                           form=form,
                           name=session.get('name'),
                           known=session.get('known', False))

@main.route('/user/<username>')
def user(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        abort(404)
    posts = user.posts.order_by(Post.timestamp.desc()).all()
    return render_template('user.html', user=user, posts=posts)

@main.route("/moderators")
@login_required
@permission_required(Permission.MODERATE_COMMENTS)
def for_moderators_only():
    return "For comment moderators!"

@main.route("/admin")
@login_required
@admin_required
def for_admins_only():
    return "For administrators!"

@main.route('/edit-profile', methods=['GET', 'POST'])
@login_required
def edit_profile():
    form = EditProfileForm()
    if form.validate_on_submit():
        current_user.name = form.name.data
        current_user.location = form.location.data
        current_user.about_me = form.about_me.data
        db.session.add(current_user)
        flash('Your profile has been updated.')
        return redirect(url_for('.user', username=current_user.username))
    form.name.data = current_user.name
    form.location.data = current_user.location
    form.about_me.data = current_user.about_me
    return render_template('edit_profile.html', form=form)

@main.route('/edit-profile/<int:id>', methods=['GET', 'POST'])
@login_required
@admin_required
def edit_profile_admin(id):
    user = User.query.get_or_404(id)
    form = EditProfileAdminForm(user)
    print form.user.email
    if form.validate_on_submit():
        user.email = form.email.data
        user.username = form.username.data
        user.confirmed = form.confirmed.data
        user.role_id = form.role.data
        user.name = form.name.data
        user.location = form.location.data
        user.about_me = form.about_me.data
        db.session.add(user)
        flash("Your changes on '" + user.username + "' have been made.")
        return redirect(url_for('main.user', username=user.username))
    form.email.data = user.email
    form.username.data = user.username
    form.confirmed.data = user.confirmed
    form.role.data = user.role_id
    form.name.data = user.name
    form.location.data = user.location
    form.about_me.data = user.about_me 
    return render_template('edit_profile.html', form=form, user=user)

@main.route('/', methods=['GET', 'POST'])
def index():
    form = PostForm()
    if form.validate_on_submit() and \
            current_user.can(Permission.WRITE_ARTICLES):
        new_post = Post()
        new_post.body = form.body.data
        new_post.author = current_user._get_current_object()
        db.session.add(new_post)
        return redirect(url_for("main.index"))
    show_followed = False
    if current_user.is_authenticated():
        show_followed = bool(request.cookies.get('show_followed', ''))
    if show_followed:
        query = current_user.followed_posts
    else:
        query = Post.query

    page = request.args.get('page', 1, type=int)
    pagination = query.order_by(Post.timestamp.desc()).paginate(
        page, per_page=current_app.config['FLASKY_POSTS_PER_PAGE'],
        error_out=False)
    posts = pagination.items
    return render_template('index.html',
                           form=form,
                           posts=posts,
                           pagination=pagination,
                           showfollowed=show_followed)

@main.route('/post/<int:id>', methods=['GET', 'POST'])
def post(id):
    post = Post.query.get_or_404(id)
    form = CommentForm()
    if form.validate_on_submit():
        comment = Comment(body=form.body.data, 
                          author=current_user._get_current_object(),
                          post=post)
        db.session.add(comment)
        flash('Your comment has been published.')
        return redirect(url_for('.post', id=post.id, page=-1))
    page = request.args.get('page', 1, type=int)
    if page == -1:
        page = (post.comments.count() - 1) / \
                current_app.config['FLASKY_COMMENTS_PER_PAGE'] + 1
    pagination = post.comments.order_by(
                    Comment.timestamp.desc()).paginate(
                        page=page, 
                        per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
                        error_out=False)
    comments = pagination.items
    return render_template('post.html', 
                           posts=[post], 
                           form=form, 
                           comments=comments,
                           pagination=pagination)

@main.route('/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_post(id):
    post = Post.query.get_or_404(id)
    if current_user != post.author and \
            not current_user.can(Permission.ADMINISTER):
        abort(403)
    form = PostForm()
    if form.validate_on_submit():
        post.body = form.body.data
        db.session.add(post)
        flash('The post has been updated.')
        return redirect(url_for('.post', id=post.id))
    form.body.data = post.body
    return render_template('edit_post.html', form=form)

@main.route('/follow/<username>')
@login_required
def follow(username):
    to_follow = User.query.filter_by(username=username).first()
    if to_follow is None:
        flash('Invalid user.')
        return redirect(url_for('.index'))
    if current_user.is_following(to_follow):
        flash('You are already following %s.' % username)
        return redirect(url_for('.user', username=username))

    current_user.follow(to_follow)
    flash("Your're now following %s." % username)
    return redirect(url_for('.user', username=to_follow.username))

@main.route('/unfollow/<username>')
@login_required
def unfollow(username):
    to_unfollow = User.query.filter_by(username=username).first()
    if to_unfollow is None:
        flash('Invalid user.')
        return redirect(url_for('.index'))
    if not current_user.is_following(to_unfollow):
        flash('You are not following %s.' % username)
        return redirect(url_for('.user', username=username))
    current_user.unfollow(to_unfollow)
    flash("You've unfollowed %s." % username)
    return redirect(url_for(".user", username=to_unfollow.username))

@main.route('/followers/<username>')
@login_required
def followers(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        flash('Invalid user.')
        return redirect(url_for('.index'))
    page = request.args.get('page', 1, type=int)
    pagination = user.followers.order_by(Follow.timestamp.desc()).paginate(
            page, per_page=current_app.config['FLASKY_FOLLOWERS_PER_PAGE'],
            error_out=False)
    follows = [{'user': item.follower, 'timestamp': item.timestamp} 
               for item in pagination.items]
    return render_template('followers.html', user=user, title='Followers of',
                           endpoint='.followers', pagination=pagination,
                           follows=follows)

@main.route('/followed-by/<username>')
def followed_by(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        flash('Invalid user.')
        return redirect(url_for('.index'))
    page = request.args.get('page', 1, type=int)
    pagination = user.followed.order_by(Follow.timestamp.desc()).paginate(
                    page, per_page=current_app.config['FLASKY_FOLLOWERS_PER_PAGE'],
                    error_out=False)
    follows = [{'user': item.followed, 'timestamp': item.timestamp} 
               for item in pagination.items]
    return render_template('followers.html', user=user, title='Followed by',
                           endpoint='.followed_by', pagination=pagination,
                           follows=follows)
@main.route('/all')
@login_required
def show_all():
    # Cookies can be set only on a response object
    response = make_response(redirect(url_for('.index')))
    # max_age = seconds in a month
    response.set_cookie('show_followed', "", max_age=30*24*60*60)
    return response

@main.route('/followed')
@login_required
def show_followed():
    # Cookies can be set only on a response object
    response = make_response(redirect(url_for('.index')))
    response.set_cookie('show_followed', "1", max_age=30*24*60*60)
    return response

@main.route('/moderate')
@login_required
@permission_required(Permission.MODERATE_COMMENTS)
def moderate():
    page = request.args.get('page', 1, type=int)
    pagination = Comment.query.order_by(Comment.timestamp.desc()).paginate(
        page, per_page=current_app.config['FLASKY_COMMENTS_PER_PAGE'],
        error_out=False)
    comments = pagination.items
    return render_template('moderate.html', 
                           comments=comments,
                           pagination=pagination,
                           page=page)

@main.route('/moderate_enable/<int:id>')
@login_required
@permission_required(Permission.MODERATE_COMMENTS)
def moderate_enable(id):
    page = request.args.get('page', 1, type=int)
    comment = Comment.query.get_or_404(id)
    if comment.disabled:
        comment.disabled = False
        flash('Comment has beeb enabled.')
    else:
        flash('Comment does not need to be enabled.')
    return redirect(url_for('.moderate', page=page))

@main.route('/moderate_disable/<int:id>')
@login_required
@permission_required(Permission.MODERATE_COMMENTS)
def moderate_disable(id):
    page = request.args.get('page', 1, type=int)
    comment = Comment.query.get_or_404(id)
    if comment is None:
        flash('Invalid comment.')
    else:
        if comment.disabled:
            flash('Comment does not need to be disabled.')
        else:
            comment.disabled = True
            flash('Comment has been disabled.')
            db.session.add(comment)
    return redirect(url_for('.moderate', page=page))
