# coding=utf-8
import os
from datetime import datetime
from random import random
import urllib
from flask import render_template, redirect, url_for, session, flash, abort, request, current_app, make_response
from flask_login import login_required, current_user
import json
from app import db
from app.decorators import admin_required, permission_required
from app.main import main
from app.main.forms import EditProfileForm, EditProfileAdminForm, PostForm, CommentForm
from app.models import Permission, User, Role, Post, Comment, Tag
import flask_whooshalchemyplus


@main.route('/', methods=['GET', 'POST'])
def index():
    flask_whooshalchemyplus.index_one_model(Post)
    form = PostForm()
    page = request.args.get('page', 1, type=int)
    if form.validate_on_submit() and current_user.can(Permission.WRITE_ARTICLES):
        tag = Tag.query.filter_by(name=form.tag.data.strip()).first_or_404()
        if tag == None:
            tag = Tag(name=form.tag.data.strip())
            db.session.add(tag)
        # current_user._get_current_object().tags = [tag]
        post = Post(body = form.body.data,
                    title=form.title.data,
                    tags = [tag],
                    author = current_user._get_current_object())
        db.session.add(post)
        db.session.commit()
        return redirect(url_for('.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
    pagination = query.order_by(Post.timestamp.desc()).paginate(
        page, per_page=current_app.config['POSTS_PER_PAGE'],
        error_out=False
    )
    posts = pagination.items
    return render_template('index.html', form=form, posts = posts, show_followed=show_followed, pagination=pagination)

@main.route('/all')
@login_required
def show_all():
    resp = make_response(redirect(url_for('.index')))
    resp.set_cookie('show_followed', '', max_age=30*24*60*60)
    return resp

@main.route('/followed')
@login_required
def show_followed():
    resp = make_response(redirect(url_for('.index')))
    resp.set_cookie('show_followed', '1', max_age=30*24*60*60)
    return resp

@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('/tag/<id>')
def tag(id=0):
    tag_id = id
    page = request.args.get('page', 1, type=int)
    tag = Tag.query.filter_by(id=id).first()
    if tag == None:
        query = Post.query
    else:
        query = tag.post
    pagination = query.order_by(Post.timestamp.desc()).paginate(
        page, per_page=current_app.config['POSTS_PER_PAGE'],
        error_out=False
    )
    posts = pagination.items
    tags = Tag.query.all()

    return render_template('tag.html', tags=tags, posts=posts, pagination=pagination, tag_id=tag_id)

# 测试图片上传
@main.route('/upload/')
def upload():
    return render_template('upload.html')

# ckeditor 上传图片
def gen_rnd_filename():
    filename_prefix = datetime.now().strftime('%Y%m%d%H%M%S')
    return '%s%s' % (filename_prefix, str(random.randrange(1000, 10000)))

@main.route('/ckupload/', methods=['POST', 'OPTIONS'])
def ckupload():
    """CKEditor file upload"""
    error = ''
    url = ''
    callback = request.args.get("CKEditorFuncNum")
    print('upload' in request.files)
    print(request.method == 'POST')
    if request.method == 'POST' and 'upload' in request.files:

        fileobj = request.files['upload']
        fname, fext = os.path.splitext(fileobj.filename)
        rnd_name = '%s%s' % (gen_rnd_filename(), fext)
        filepath = os.path.join(main.static_folder, 'upload', rnd_name)
        # 检查路径是否存在，不存在则创建
        dirname = os.path.dirname(filepath)
        if not os.path.exists(dirname):
            try:
                os.makedirs(dirname)
            except:
                error = 'ERROR_CREATE_DIR'
        elif not os.access(dirname, os.W_OK):
            error = 'ERROR_DIR_NOT_WRITEABLE'
        if not error:
            fileobj.save(filepath)
            url = url_for('static', filename='%s/%s' % ('upload', rnd_name))
    else:

        error = 'post error'
    res = """
    <script type="text/javascript">
      window.parent.CKEDITOR.tools.callFunction(%s, '%s', '%s');
    </script>
    """ % (callback, url, error)
    response = make_response(res)
    response.headers["Content-Type"] = "text/html"
    return response

@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('您的资料已更新')
        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=user)
    if form.validate_on_submit():
        user.email = form.email.data
        user.username = form.username.data
        user.confirmed = form.confirmed.data
        user.role = Role.query.get(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('您的资料已更新')
        return redirect(url_for('.user', username = user.username))
    form.name.data = user.name
    form.username.data = user.username
    form.email.data = user.email
    form.confirmed.data = user.confirmed
    form.role.data = user.role_id
    form.location.data = user.location
    form.about_me.data = user.about_me
    return render_template('edit_profile.html', form=form)

@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,
                          post=post,
                          author=current_user._get_current_object())
        db.session.add(comment)
        db.session.commit()
        flash('您的评论已发布')
        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['COMMENTS_PER_PAGE'] + 1
    pagination = post.comments.order_by(Comment.timestamp.asc()).paginate(page,
                         per_page=current_app.config['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(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('文章已经更新')
        return redirect(url_for('.post', id=post.id))
    if post.body == '' or post.body is None:
        form.body.data=post.body_html
    else:
        form.body.data=post.body
    # if post.title is None or post.title == '':
    #     form.title.data = post.body_html[:lambda x:if len(post.body_html)<50 len(post.body_html) else 50]
    form.title.data = post.title
    return render_template('edit_post.html', form=form)

@main.route('/follow/<username>')
@login_required
@permission_required(Permission.FOLLOW)
def follow(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        flash('该账户无效')
        return redirect(url_for('.index'))
    if current_user.is_following(user):
        flash('你已关注')
        return redirect(url_for('.user', username=username))
    current_user.follow(user)
    flash('你关注了%s' % username)
    return redirect(url_for('.user', username=username))

@main.route('/unfollow/<username>')
@login_required
@permission_required(Permission.FOLLOW)
def unfollow(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        flash('该账户无效')
        return redirect(url_for('.index'))
    if not current_user.is_following(user):
        flash('你没有关注他')
        return redirect(url_for('.user', username=username))
    current_user.unfollow(user)
    flash('你不在关注%s' % username)
    return redirect(url_for('.user', username=username))


@main.route('/followers/<username>')
def followers(username):
    user = User.query.filter_by(username=username).first()
    if user is None:
        flash('该账户无效')
        return redirect(url_for('.index'))
    page = request.args.get('page', 1, type=int)
    pagination = user.follower.paginate(page,
                                         per_page=current_app.config['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='关注%s的人' % user.username,
                           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('该账户无效')
        return redirect(url_for('.index'))
    page = request.args.get('page', 1, type=int)
    pagination = user.followed.paginate(page,
                                         per_page=current_app.config['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='%s关注的人' % user.username,
                           endpoint='.followed_by', pagination=pagination, follows=follows)

@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['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):
    comment = Comment.query.get_or_404(id)
    comment.disabled = False
    db.session.add(comment)
    return redirect(url_for('.moderate', page=request.args.get('page', 1, type=int)))


@main.route('/moderate/disable/<int:id>')
@login_required
@permission_required(Permission.MODERATE_COMMENTS)
def moderate_disable(id):
    comment = Comment.query.get_or_404(id)
    comment.disabled = True
    db.session.add(comment)
    return redirect(url_for('.moderate', page=request.args.get('page', 1, type=int)))



@main.route('/admin')
@login_required
@admin_required
def for_admin():
    if current_user.can(Permission.ADMINISTER):
        query = User.query
        page = request.args.get('page', 1, type=int)
        pagination = query.order_by(User.member_since.desc()).paginate(
            page, per_page=current_app.config['POSTS_PER_PAGE'],
            error_out=False
        )
        users = pagination.items
        return render_template('admin.html', users=users, pagination=pagination)
    else:
        return redirect(url_for('.index'))


@main.route('/search', methods=['POST'])
def search():
    if not request.form['search']:
        return redirect(url_for('.index'))
    return redirect(url_for('.search_results', query=request.form['search']))


@main.route('/search_results/<query>')
def search_results(query):
    results = Post.query.whoosh_search(query).all()
    count = len(results)
    return render_template('search.html', query=query, posts=results, count = count)