# !/usr/bin/env python
# -*- coding: utf-8 -*-
from wtforms import Form, TextField, validators, TextAreaField, ValidationError
from flask import render_template, request, flash, session, redirect, url_for, abort
from markdown import Markdown
from flask_blog import db, cache
from flask_blog.blog import blueprint
from flask_blog.blog.comment import CommentForm
from flask_blog.user import admin_required
from flask_blog.model.blog import Blog
from flask_blog.model.comment import Comment


class BlogForm(Form):
    title = TextField(u"Title", [
        validators.Required(message=u"title needed"),
        validators.length(min=1, max=100)
    ])
    context = TextAreaField(u"Context", [
        validators.Required(message=u"context needed"),
        validators.length(min=1, max=10000)
    ])


@blueprint.route("/")
@cache.cached(60)
def index():
    """ index of the site """
    blogs = Blog.query.filter(Blog.status == "public").limit(10).all()
    md = Markdown()
    for blog in blogs:
        blog.context = md.convert(blog.context)
    return render_template("blog/index.html", blogs=blogs)


@blueprint.route("/<int:blog_id>/<blog_title>")
@cache.cached(60)
def fetch_blog(blog_id, blog_title):
    """ fetch a blog, available for everyone """
    blog = Blog.query.get(blog_id)
    if not blog:
        return abort(404)
    errors = []
    form = CommentForm(request.form)
    md = Markdown()
    blog.context = md.convert(blog.context)
    comments = Comment.query.filter(
        Comment.blog_id == blog.blog_id,
        Comment.status == "normal"
    ).all()
    return render_template("blog/fetch_blog.html", blog=blog, comments=comments, form=form, errors=errors)


@blueprint.route("/manage", methods=["GET", "POST"])
@admin_required
def blog():
    """ Blog manage, only available for admin

    Include:
    1. add a blog
    2. update a blog
    3. delete a blog
    """
    errors = []
    op = request.args.get("op")
    blog_form = BlogForm(request.form)
    blog_id = request.args.get("blog_id")
    blog = None
    if blog_id:
        #global blog
        try:
            blog_id = int(blog_id)
            blog = Blog.query.get(blog_id)
            assert blog
        except Exception as e:
            return abort(400), repr(e)
    if request.method == "GET":
        if op == "add":
            # pre-add a blog
            return render_template("blog/add_blog.html", form=blog_form, errors=errors)
        elif op == "edit":
            # pre-edit a blog
            blog_form.title.data = blog.title
            blog_form.context.data = blog.context
            return render_template("blog/edit_blog.html", form=blog_form, blog=blog, errors=errors)
    elif request.method == "POST":
        if op == "add":
            # add a blog
            if not blog_form.validate():
                return render_template("blog/add_blog.html", form=blog_form, errors=errors)
            blog = Blog(title=blog_form.title.data, context=blog_form.context.data)
            blog.user_id = session["current_user"].user_id
            db.session.add(blog)
            db.session.commit()
            cache.clear()
            flash("Successfully added a blog named '{0}'!".format(blog.title.encode("utf-8")))
            return redirect(url_for("blog.index"))
        elif op == "edit":
            # edit a blog
            if not blog_form.validate():
                return render_template("blog/edit_blog.html", form=blog_form, blog=blog, errors=errors)
            blog.title = blog_form.title.data
            blog.context = blog_form.context.data
            db.session.add(blog)
            db.session.commit()
            cache.clear()
            flash("Successfully edited a blog named '{0}'!".format(blog.title.encode("utf-8")))
            return redirect(url_for("blog.fetch_blog", blog_id=blog.blog_id, blog_title=blog.title))
        elif op == "delete":
            # delete a blog
            # TODO: 需要支持级联删除
            db.session.delete(blog)
            db.session.commit()
            cache.clear()
            flash("Blog '{0}' have been deleted!".format(blog.title.encode("utf-8")))
            return redirect(url_for("blog.index"))