# -*- mode: python; coding: utf-8 -*-
"""
==============
Blog Controller
==============
:Copyright: (c) 2007,2009 Higgins and Macfarlane
:Author: Graham Higgins
:Contact: gjh@bel-epa.com
:Date: <2009-03-14 14:32 gjh>
:Notes: Further adaptations of TurboBlog
"""
import random
import os
import logging

from pylons import request
from pylons.templating import render_mako as render
from pylons.controllers.util import abort, redirect_to, log
from pylons.decorators import jsonify, validate

# from authkit.permissions import NotAuthenticatedError
# from authkit.authorize.pylons_adaptors import authorize
# from authkit.permissions import RemoteUser

import formencode
from formencode import validators
from sqlalchemy import *

from {{package}}.lib.base import *
import {{package}}.lib.helpers as h
from {{package}}.lib import antispam
from {{package}}.lib.helpers import dcmeta
from {{package}}.model import *
from {{package}}.lib.pager import *
from {{package}}.lib.feed import *

from pprint import pformat

log = logging.getLogger(__name__)

class Settings(object):
    def __init__(self, admin=1, default_blog=1):
        self.admin = admin
        self.default_blog = default_blog 

# Fake it for now
settings = Settings(admin=1, default_blog=1)
#settings = Settings.get(1) 

def _theme(blog,template):
    log.debug("_theme with blog:%s tpl: %s" % (blog, template))
    default_template = template%'default'
    # For when no blog is selected
    try:
        current_template = template%blog.theme
    except:
        current_template = default_template
    current_template_path = os.curdir+"/%s.html"%"/".join(current_template.split('.'))    
    default_template_path = default_template    
    ret = [default_template_path,current_template][int(os.path.exists(current_template_path))]
    log.debug("Themed template = %s" % ret)
    return ret

def _theme_css(blog):
    url = "/css/%s/style.css"%blog.theme
    def_url = "/css/style.css"
    cp = os.curdir+"/blog"
    ret = [def_url,url][int(os.path.exists(cp+url))]
    return ret


class BlogController(BaseController):
    # comment = CommentController()

    def __before__(self):
        c.dcmeta = h.dcmeta(title="Bel-EPA :: Blogstar")

    # Not relevant for Pylons, unless specified as a default in
    # config/routing.py
    def view(self, *args, **kwargs):
        log.debug("Blog default ---\n args:%s\n kwargs: %s" % (args, pformat(kwargs)))
        #print "def with:",args,kwargs
        blogslug = kwargs['blogslug']
        if len(args)>1: #have more params
            mname = args[1]
            method = getattr(self, mname, None) # try root first
            if method:
                log.debug("running 1 %s with %s %s" % (method, args[1:], kwargs))
                #print "running 1 ",method , " with: " , args[1:], kwargs
                return method(*args[1:], **kwargs)
            method = getattr(self.blog, mname, None)
            if method:
                kwargs.update({'blogslug':blogslug})
                if callable(method):
                    log.debug("1.1 running method %s with %s %s" % (method, args[2:], kwargs))
                    #print "running 2 ", method , " with: " , args[2:], kwargs
                    return method(*args[2:], **kwargs)
                else:
                    sm = getattr(method, args[2])
                    sa = args[3:]
                    log.debug("1.2 running got method %s with %s %s" % (sm, sa, kwargs))
                    #print "running 3 ", sm , " with: " , sa, kwargs
                    return sm(*sa, **kwargs)
            else:
                c = getattr(self, args[0], None)
                log.debug("2.0 - default: not method, getting method for %s, dir %s" % (c,dir(self)))
                #print c,dir(self)
                if c:
                    method = getattr(c, args[1], None)
                    log.debug("2.1 - calling got method %s with %s" % (method, args[1:]))
                    #print method
                    if method:
                        return method(args[1:])
                sa = args[2:]
                log.debug("2.2 defaulting to post with %s and %s %s %s %s" % (self.blog.post, blogslug, mname, sa, kwargs))
                #print "running 4 ", self.blog.post , " with: " , blogslug, mname,sa, kwargs
                return self.post(blogslug, mname, *sa, **kwargs)
        else:
            log.debug("running default index for slug %s and kwargs %s" % (blogslug, kwargs.keys()))
            return self.index(blogslug, **kwargs)

    # Need to integrate this into the real index
    # def index(self, *args, **kwargs):
    #     if settings.default_blog != -1:
    #         log.debug("Settings found, default blog = %s" % settings.default_blog)
    #         return self.index(Blog.get(settings.default_blog).slug)
    #     log.debug("No default blog setting found, calling selector")
    #     return self.blog_selector() 

    # Rework so that a blog selection is presented if no bid is supplied
    # @pager.pager('blog_posts', default_size=5)
    def index(self, *args, **kwargs):
        log.debug("Blog-index : %s %s" % (args, pformat(request.environ['wsgiorg.routing_args'])))
        blogslug = request.environ['wsgiorg.routing_args'][1].get('blogslug', '')
        if not blogslug:
            return self.blog_selector()
        else:
            bq = Session.query(Blog)
            pq = Session.query(Post)
            cq = Session.query(Comment)
            selblog = bq.filter_by(slug = blogslug).one()
            posts = selblog.posts
            # posts = pq.filter_by(blog = selblog).order_by(Post.creation_time.desc()).all()
            # comments = [cq.get(post.id) for post in pq.filter_by(blog_id == blog.id]
            log.debug("Blog has %s posts %s" % (len(posts), posts))
            for post in posts:
                log.debug("Doing post %s" % type(post))
                # Insert number of comments
                nc = 'No Comments'
                comments = post.comments
                # comments = cq.filter(Comment.c.post_id == post.id).order_by(Comment.c.creation_time)
                if len(comments) == 1:
                    nc = '1 Comment'
                elif len(comments) > 1:
                    nc = '%d Comments'%comments.count()
                # Calculate post_match ????
                post.post_match = False
                try:
                    post.post_match = (post.creation_time.month == int(kwargs['arc_month']) and post.creation_time.year == int(kwargs['arc_year']))
                except:
                    try:
                        post.a = tag_name
                        if post.a in post.tags:
                            post.post_match = True
                    except:
                        try:
                            post.a = untagged
                            post.post_match = not post.tagged()
                        except:        
                            post.post_match = True
            # p_link = pager.previous_link(locals())
            # n_link = pager.next_link(locals())
            c.blog = selblog
            c.blog_posts = posts
            c.nc = nc
            if 'cloud' in kwargs:
                c.cloud = kwargs['cloud']
            if 'untagged' in kwargs:
                c.untagged = 1
            if 'tagged' in kwargs:
                tagname = Tag.select(and_(Tag.c.blog_id==blog.id,Tag.c.id==kwargs['tagged']))[0]
                c.tag_name = tagname
            if ('arc_year' in kwargs) and ('arc_month' in kwargs):
                c.arc_month = int(kwargs['arc_month'])
                c.arc_year = int(kwargs['arc_year'])
            c.blog_count = bq.count()
            c.title = selblog.name
            c.sidebar = self.get_sidebar(selblog)
            #can_edit = has_permission('can_post') and (std.identity.user in blog.posters) or (std.identity.user == blog.owner)
            c.can_edit = True
            return render(_theme(selblog,"turboblog.%s.index"))

    def blog_selector(self, *args, **kwargs):
        c.dcmeta.title = c.dcmeta.title + ' :: Blog Store, Select point'
        log.debug("_theme call in selector: blog:%s %s %s" % (blog, args, kwargs))
        c.blogs = Session.query(Blog).order_by(Blog.created.desc()).all()
        template = _theme(blog,"turboblog/%s/selector.mak")
        log.debug("Blog Selector blogs %s" % c.blogs)
        log.debug("Blog Selector template %s" % template)
        return render(template)

    @validate(validators={"pid":validators.Int()})
    def tag_post(self, tagname, pid, blogslug):
        p=Post.get(pid)
        blog = Blog.select_by(slug=blogslug)
        t=Tag.select(and_(Tag.blog_id==blog.id,Tag.name==tagname))[0]
        session = create_session()
        p.addTag(t)
        session.flush()
        return dict()
    
    @validate(validators={"pid":validators.Int()})
    def trackback(self, pid, blogslug, url,  *args, **kw):
        title = kw.get('title','')
        excerpt = kw.get('excerpt','')
        blog_name = kw.get('blog_name','')
        session = create_session()
        p = Post.get(pid)
        Trackback(url=url,title=title,excerpt=excerpt,blog_name=blog_name,post=p)
        session.flush()
        return """<?xml version="1.0" encoding="utf-8"?><response><error>0</error></response>"""
     
    def recent_posts(self, blog):
        log.debug("RecentPosts called")
        html = "<div id='recent_posts'><strong>Last 5 Posts</strong><ol>"
        posts = blog.get_posts(True, 5)
        log.debug("RecentPosts posts %s" % posts)
        for p in posts:
            log.debug("RecentPosts html: %s" % html)
            html += """<li><a href="%s">%s</li>"""%(p.link(), p.title)
            log.debug("RecentPosts html: %s" % html)
        html += "</ol></div>"
        #ret = ElementTree.XML(html)
        log.debug("RecentPosts returning %s" % html)
        return html

    def calendar_of_recent_posts(self, blog, arrows=None, monthlink=None, yearlink=None):
        log.debug("CalendarOfRecentPosts called")
        from {{package}}.lib.blogcalendar import HtmlCalendar
        from datetime import datetime
        now = datetime.now()
        posts = blog.get_posts(True, False, now.month)
        if posts:
            log.debug("calendar_of_recent_events %s (%s)" % (posts[0].creation_time.day, posts[0].creation_time))
            links = dict([(p.creation_time.day, p.link()) for p in posts])
        else:
            links = {}
        from mx.DateTime import RelativeDateTime, now as mxnow
        ult = mxnow()+RelativeDateTime(months=-1)
        inst = mxnow()+RelativeDateTime(months=+1)
        res = HtmlCalendar(year=now.year, month=now.month, links=links, arrows=("/blog/%s/%s" % (ult.year, ult.month), "/blog/%s/%s" % (inst.year, inst.month)), monthlink=None, yearlink=None)
        log.debug("CalendarOfRecentPosts returning")
        return res

    def get_sidebar(self, blog):
        log.debug("GetSidebar called")
        calendar = self.calendar_of_recent_posts(blog)
        recent_posts = self.recent_posts(blog)
        log.debug("GetSidebar returning")
        return '<div id="sidebar"><div id="calendar"><!-- Calendar-generating code courtesy of James Tauber: http://leonardo.pyworks.org/ -->%s</div><h4>Recent posts</h4>%s<h4>BlogRoll</h4><h4>Trackbacks</h4></div>' % (calendar, recent_posts)

    # @turbogears.expose(format="xhtml", content_type="application/xhtml+xml", template="turboblog.templates.post")
    # FIXME: @@GJH@@ More work required here 
    def post(self, *args, **kwargs):
        log.debug("Post: args %s, kwargs %s" % (args, pformat(kwargs)))
        blogslug = kwargs['blogslug']
        postslug = kwargs['postslug']
        try:
            post = Post.get_by(slug=postslug)
            blog = Blog.get_by(slug=blogslug)
        except Exception, e:
            log.debug("Exception trapped by post: %s" % e)
            # print "-00---",e
            abort(404)
        if not post or not blog:
            abort(404)
        log.debug("Post: blog %s, post %s" % (blog, post))
        nc = 'No Responses'
        if post and len(post.comments) == 1:
            nc = 'One Response'
        elif post and len(post.comments) > 1:
            nc = '%d Responses'%len(post.comments)
        post.tags = []
        more_tags = []
        # if blog.tags:
        #     for tag in blog.tags:
        #         if not tag in post.tags:
        #             more_tags += [ tag ]
        cloud = 0
        if 'cloud' in kwargs:
            cloud = kwargs['cloud']
        log.debug("_theme call in post: blogslug %s postslug %s, blog: %s, post %s" % (blogslug, postslug, blog, post))
        from {{package}}.model import Comment,Tag
        # registered = has_permission('can_comment')    
        # can_edit = has_permission('can_post')    
        # if registered:
        #     from turboblog.model import User
        #     calink = User.get(std.identity.user.id).link() 
        c.beldict = dcmeta(title='Blog Store')
        ns = dict(
                dc=c.beldict,
                blog=blog, 
                post=post, 
                sidebar=self.get_sidebar(blog),
                comment_link=Comment.link_add(blog.id,post.id),
                cloud=cloud,
                cat=Comment.allowed_tags,
                nc=nc,
                can_edit=True,
                registered=True,
                more_tags=more_tags)
        return render(_theme(blog,"turboblog.%s.post"), **ns)

# class UserController(BaseController):
    def user_show(self, userId):
        user = User.get_by(id=userId)
        if not user.blogs:
            blog = Blog.get(1)
        else:
            blog = user.blogs[0] #FIXME!
        dc = dcmeta(title='Blog Store, Blogger')
        log.debug("_theme call in show: blog %s %s %s" % (blog, args, kwargs))
        ns = dict(user=user,dc=dc)
        return render(_theme(blog,"/genshi/turboblog/%s/user"), **ns)

    # @turbogears.expose(content_type='image/jpg')
    def user_avatar(self, userId):
        avatar = User.get_by(id = userId).avatar
        return avatar
                    
# class BlogRoot(BaseController):
#     admin = AdminController()
#     blog_admin = BlogAdminController()
#     blog = BlogController()
#     user = UserController()
#     RPC = RPCController()
    
    # @turbogears.expose(content_type='image/png')
    def get_antispam_image(self):
        session['number'] = str(random.randrange(1,99999,1))
        return antispam.writeImage(session['number'])

    # @turbogears.expose()
    def create_user( self, *args, **kw ):        
        flash = None
        try:
            validators.FieldsMatch('psw', 'psw2').to_python(kw)
            num = session['number']
            assert (kw['code'] == num)
        except formencode.api.Invalid, e:
            flash = 'Password don\'t match'
        except Exception,e :
            flash = 'Code was incorrect'
        if flash:
            #turbogears.flash(flash)
            redirect_to("/admin/signup")
        session = create_session()
        try:
            avatar = kw['image'].file.read()
        except:
            avatar = None
            if ('usegravatar' in kw) and (kw['usegravatar']=='on'):
                import gravatar
                (mime,avatar) = gravatar.get_image(kw['email'])
        u = User(userId=kw['userid'],password=kw['psw'],displayName=kw['fullname'], emailAddress=kw['email'],avatar=avatar,about=kw.get('summary',''))
        g = TG_Group.get_by(group_id='user')
        u.addTG_Group(g)
        session.flush()
        # turbogears.flash('Please login with your details.')
        return redirect_to("/login")
    
    # @turbogears.expose()
    def livesearch( self, *args, **kw ):
        return """<div class="LSRes"><div class="LSRow"><a href="http://reflog.wordpress.com/2005/11/29/conversion-command-for-ipod-video/" rel="bookmark" title="Permanent Link: conversion command for ipod video">conversion command for ipod video</a>
        </div><div>
        <div class="LSRes"><a href="/index.php?s=conv">More Results...</a></div>"""
    
    # # @turbogears.expose(format="xhtml", content_type="application/xhtml+xml", template="bel.templates.turboblog.login" )
    # def login( self, *args, **kw ):
    #     if hasattr(request,"identity_exception"):
    #         msg= str(request.identity_exception)
    #         userId= getattr( request.identity_exception, "userId", None )
    #     else:
    #         msg= "Please log in"
    #         userId= None
    #         abort(403)
    #     return dict( message=msg, previous_url=kw.get('redirect_to','/'),
    #                  userId=userId )
    #     
    # # @turbogears.expose(format="xhtml", content_type="application/xhtml+xml", template="bel.templates.turboblog.signup" )
    # def signup( self, *args, **kw ):
    #     return dict()
    #
    # # @turbogears.expose()
    # def logout( self, *args, **kw ):
    #     identity.current.logout()
    #     raise cherrypy.InternalRedirect(kw.get('redirect_to','/'))

# ----------- Comment handling -----------------------------------------------------
#    @identity.require(identity.has_permission('can_comment'))
    def add_comment(self, postslug, **kwargs):
        bid = Blog.get_by(slug=kwargs['blogslug']).id
        p=Post.get_by(slug=postslug)
        cparent_id = int(kwargs.get('comment_id','-1'))
        cparent = None
        if cparent_id != -1:
            cparent = Comment.get(cparent_id)
        content = kwargs['comment']
        if Comment.check_tags(content):
            # session = create_session()
            session = create_session() 
            c=Comment(content=content,author=identity.current.user,approved=False,post=p,parent_id=cparent_id)
            cparent.addComment(c)
            # session.flush()
            session.flush()
            raise cherrypy.HTTPRedirect(p.link(bid)+"#comment_%d"%c.id)
        else:
            flashData = {"status": "error", "msg": "Tags in the comment are not allowed!"}
            #turbogears.flash(jsonify.jsonify(flashData))
        raise redirect_to(p.link(bid))
        
    # Access to comment methods is controlled by the signature of the routes entry

    @validate(validators={"cid":validators.Int()})
#    @identity.require(identity.has_permission('can_moderate'))
    def approve_comment(self, cid, blogslug):
        # session = create_session()
        session = create_session() 
        c=Comment.get(cid)
        c.approved = True
        #turbogears.flash('Comment approved!')
        session.flush()
        # session.flush()
        return dict()

        ##### TO-DO Add in Akisment comment protection.
        # import akismet
        #         
        # akismet.USERAGENT = "MyApplication/MyVersion"
        #         
        # my_api_key = "SOMETHING"
        #         
        # try:
        #   real_key = akismet.verify_key(my_api_key,"http://www.example.com")
        #   if real_key:
        #     is_spam = akismet.comment_check(my_api_key,"http://www.example.com",
        #       "127.0.0.1", "Mozilla/5.0 (...) Gecko/20051111 Firefox/1.5",
        #         comment_content="VIAGRA! LOTS OF VIAGRA!")
        #       if is_spam:
        #         print "Yup, that's spam alright."
        #       else:
        #         print "Hooray, your users aren't scum!"
        # except akismet.AkismetError, e:
        #     print e.response, e.statuscode
        #         
        # # If you're a good person, you can report false positives via
        # # akismet.submit_ham(), and false negatives via akismet.submit_spam(),
        # # using exactly the same parameters as akismet.comment_check().

    @validate(validators={"cid":validators.Int()})
#    @identity.require(identity.has_permission('can_comment'))
    def source_comment(self, cid, blogslug):
        comment=Comment.get(cid)
        return dict(content=comment.content)
    
#    @identity.require(identity.has_permission('can_comment'))
    @validate(validators={"cid":validators.Int()})
    def edit_comment(self, cid, **kwargs):
        content = kwargs['content']
        if Comment.check_tags(content):
            session = create_session()
            Comment.get(cid).content = content
            session.flush()
        else:
            flashData = {"status": "error", "msg": "Tags in the comment are not allowed!"}
            #turbogears.flash(jsonify(flashData))
        return dict()


# ------- Modern version ------
#    @turbogears.expose(format="xhtml", content_type="application/xhtml+xml", template="turboblog.templates.login")
#    def login(self, forward_url=None, previous_url=None, *args, **kw):
#
#        if not identity.current.anonymous \
#            and identity.was_login_attempted() \
#            and not identity.get_identity_errors():
#            raise redirect(forward_url)
#
#        forward_url=None
#        previous_url= request.path
#
#        if identity.was_login_attempted():
#            msg=_("The credentials you supplied were not correct or "
#                   "did not grant access to this resource.")
#        elif identity.get_identity_errors():
#            msg=_("You must provide your credentials before accessing "
#                   "this resource.")
#        else:
#            msg=_("Please log in.")
#            forward_url= request.headers.get("Referer", "/")
#        cherrypy.response.status=403
#        return dict(message=msg, previous_url=previous_url, logging_in=True,
#                    original_parameters=request.params,
#                    forward_url=forward_url)
#
#    @expose()
#    def logout(self):
#        identity.current.logout()
#        raise redirect("/")
