from datetime import datetime
from DateTime import DateTime

from urllib import quote as url_quote

from zope.interface import implements

from zope.component import createObject, getMultiAdapter, queryUtility

from zope.viewlet.interfaces import IViewlet

from Acquisition import aq_inner, aq_parent, aq_base

from AccessControl import getSecurityManager

from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile

from Products.CMFCore.utils import getToolByName

from Products.CMFPlone import PloneMessageFactory as _
from Products.statusmessages.interfaces import IStatusMessage

from plone.registry.interfaces import IRegistry

from plone.app.layout.viewlets.common import ViewletBase

from plone.app.discussion.comment import CommentFactory
from plone.app.discussion.interfaces import IConversation, IComment, IReplies, IDiscussionSettings



class View(BrowserView):
    """Comment View
    """

    def __call__(self):
        # Redirect from /path/to/object/++conversation++default/123456789
        # to /path/to/object#comment-123456789
        comment_id = aq_parent(self).id
        #self.request.response.redirect(aq_parent(aq_parent(aq_parent(self))).absolute_url() + '#comment-' + comment_id)
        self.request.response.redirect(aq_parent(aq_parent(aq_parent(self))).absolute_url() + '#' + comment_id)

class CommentsViewlet(ViewletBase):
    """Discussion Viewlet
    """

    implements(IViewlet)

    template = ViewPageTemplateFile('comments.pt')

    def update(self):
        super(CommentsViewlet, self).update()
        self.portal_discussion = getToolByName(self.context, 'portal_discussion', None)
        self.portal_membership = getToolByName(self.context, 'portal_membership', None)

    def can_reply(self):
        return getSecurityManager().checkPermission('Reply to item', aq_inner(self.context))

    def can_manage(self):
        return getSecurityManager().checkPermission('Manage portal', aq_inner(self.context))

    def is_discussion_allowed(self):
        context = aq_inner(self.context)
        conversation = IConversation(context)
        return conversation.enabled

    def get_replies(self, workflow_actions=False):
        context = aq_inner(self.context)
        conversation = IConversation(context)

        def replies_with_workflow_actions():
            # Return dict with workflow actions
            #context = aq_inner(self.context)
            wf = getToolByName(context, 'portal_workflow')

            for r in conversation.getThreads():
                comment_obj = r['comment']
                # list all possible workflow actions
                actions = [a for a in wf.listActionInfos(object=comment_obj)
                               if a['category'] == 'workflow' and a['allowed']]
                r = r.copy()
                r['actions'] = actions
                yield r

        # Return all direct replies
        if conversation.total_comments > 0:
            if workflow_actions:
                return replies_with_workflow_actions()
            else:
                return conversation.getThreads()
        else:
            return None


    def get_commenter_home_url(self, username):
        if username is None:
            return None
        else:
            return "%s/author/%s" % (self.context.portal_url(), username)

    def get_commenter_portrait(self, username):

        if username is None:
            # return the default user image if no username is given
            return 'defaultUser.gif'
        else:
            portal_membership = getToolByName(self.context, 'portal_membership', None)
            return portal_membership.getPersonalPortrait(username).absolute_url();

    def anonymous_discussion_allowed(self):
        # Check if anonymous comments are allowed in the registry
        registry = queryUtility(IRegistry)
        settings = registry.for_interface(IDiscussionSettings)
        return settings.anonymous_comments

    def show_commenter_image(self):
        # Check if showing commenter image is enabled in the registry
        registry = queryUtility(IRegistry)
        settings = registry.for_interface(IDiscussionSettings)
        return settings.show_commenter_image

    def is_anonymous(self):
        return self.portal_state.anonymous()

    def login_action(self):
        return '%s/login_form?came_from=%s' % (self.navigation_root_url, url_quote(self.request.get('URL', '')),)

    def format_time(self, time):
        # We have to transform Python datetime into Zope DateTime
        # before we can call toLocalizedTime.
        util = getToolByName(self.context, 'translation_service')
        zope_time = DateTime(time.year, time.month, time.day, time.hour, time.minute, time.second)
        return util.toLocalizedTime(zope_time, long_format=True)

class AddComment(BrowserView):
    """Add a comment to a conversation
    """

    def __call__(self):

        if self.request.has_key('form.button.AddComment'):

            context = aq_inner(self.context)

            subject = self.request.get('subject')
            text = self.request.get('body_text')
            author_username = self.request.get('author_username')
            author_email = self.request.get('author_email')

            # Check the form input
            if author_username == '':
                IStatusMessage(self.request).addStatusMessage(\
                    _("Username field is empty."),
                    type="info")
                return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
            if author_email == '':
                IStatusMessage(self.request).addStatusMessage(\
                    _("Email field is empty."),
                    type="info")
                return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
            if subject == '':
                IStatusMessage(self.request).addStatusMessage(\
                    _("Subject field is empty."),
                    type="info")
                return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
            if text == '':
                IStatusMessage(self.request).addStatusMessage(\
                    _("Comment field is empty."),
                    type="info")
                return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())

            # The add-comment view is called on the conversation object
            conversation = context

            # Create the comment
            comment = CommentFactory()
            comment.title = subject
            comment.text = text

            portal_membership = getToolByName(context, 'portal_membership')

            if portal_membership.isAnonymousUser():
                comment.creator = author_username
                comment.author_name = author_username
                comment.author_email = author_email
                comment.creation_date = comment.modification_date = datetime.now()
            else:
                member = portal_membership.getAuthenticatedMember()
                fullname = member.getProperty('fullname')
                if fullname == '' or None:
                    comment.creator = member.id
                else:
                    comment.creator = fullname
                comment.author_username = member.getUserName()
                comment.author_name = member.getProperty('fullname')
                comment.author_email = member.getProperty('email')
                comment.creation_date = comment.modification_date = datetime.now()

            # Add comment to the conversation
            comment_id = conversation.addComment(comment)

            # Redirect to comment (inside a content object page)
            #self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url() + '#comment-' + str(comment_id))
            self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url() + '#' + str(comment_id))

class ReplyToComment(BrowserView):
    """Reply to a comment
    """

    def __call__(self):

        context = aq_inner(self.context)

        if self.request.has_key('form.button.AddComment'):

            reply_to_comment_id = self.request.get('form.reply_to_comment_id')

            subject = self.request.get('subject')
            text = self.request.get('body_text')
            author_username = self.request.get('author_username')
            author_email = self.request.get('author_email')

            # Check the form input
            if author_username == '':
                IStatusMessage(self.request).addStatusMessage(\
                    _("Username field is empty."),
                    type="info")
                return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
            if author_email == '':
                IStatusMessage(self.request).addStatusMessage(\
                    _("Email field is empty."),
                    type="info")
                return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
            if subject == '':
                IStatusMessage(self.request).addStatusMessage(\
                    _("Subject field is empty."),
                    type="info")
                return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())
            if text == '':
                IStatusMessage(self.request).addStatusMessage(\
                    _("Comment field is empty."),
                    type="info")
                return self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url())

            # The add-comment view is called on the conversation object
            conversation = context

            # Fetch the comment we want to reply to
            comment_to_reply_to = conversation.get(reply_to_comment_id)

            replies = IReplies(comment_to_reply_to)

            # Create the comment
            comment = CommentFactory()
            comment.title = subject
            comment.text = text

            portal_membership = getToolByName(context, 'portal_membership')

            if portal_membership.isAnonymousUser():
                comment.creator = author_username
                comment.author_name = author_username
                comment.author_email = author_email
                comment.creation_date = comment.modification_date = datetime.now()
            else:
                member = portal_membership.getAuthenticatedMember()
                fullname = member.getProperty('fullname')
                if fullname == '' or None:
                    comment.creator = member.id
                else:
                    comment.creator = fullname
                comment.author_username = member.getUserName()
                comment.author_name = member.getProperty('fullname')
                comment.author_email = member.getProperty('email')
                comment.creation_date = comment.modification_date = datetime.now()

            # Add the reply to the comment
            new_re_id = replies.addComment(comment)

            # Redirect to comment (inside a content object page)
            #self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url() + '#comment-' + str(reply_to_comment_id))
            # Todo: Temporarily remove the "#comment-" to fix a bug
            # in CMFPlone/skins/plone_ecmascript/form_tabbing.js
            self.request.response.redirect(aq_parent(aq_inner(context)).absolute_url() + '#' + str(reply_to_comment_id))