# -*- coding: UTF-8 -*-
#    This file is part of arena.
#
#    arena is free software: you can redistribute it and/or modify it
#    under the terms of the GNU General Public License as published by the
#    Free Software Foundation; either version 3 of the License or, at your
#    option, any later version.
#
#    arena is distributed in the hope that it will be useful, but
#    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABLITY
#    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
#    License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with arena.  If not, see <http://www.gnu.org/licenses/>.

## @file
#  This file defines and implements a content mediator that is used to create 
#  and edit posts.
from Plugins.Application.Viewpoints import AViewpointError, AViewpoint
from Local.Configuration import Site

from Custom.UI.Views import AnArenaView
from Custom.UI.Posts import AnArenaPost
from Custom.Application.Engines import AnArenaEngine
from Library.Base.Exceptions import AnException
from Library.User.Subscriptions import Right
from cgi import MiniFieldStorage
import time

## The name of the query key that specifies the action the user desires
pstActionQueryKey = "undertaking"
## The name of the query key that specifies WHICH post to edit or update
pstPostIDKey = "id"
## The value of the query key that specifies the user wishes to edit an existing post
pstEditAction = "edit"
## The value of the query key that specifies the user wishes to publish a post
pstPublishAction = "publish"
## The value of the query key that specifies the user wishes to delete a post
pstDeleteAction = "delete"

## The name of the view used to edit posts
pstEditViewName = "post/edit"
## The template used when a non-fatal error condition occurs
pstEditErrorTemplateName = "error.tpl.html"
## The template used to allow editing of a new or existing post
pstEditTemplateName = "edit.tpl.html"

## The format of the error message used when no post ID is provided for editing
peMissingPostID = "failed to {} post because no post ID was specified"
## The format of the error message used when the user does not have the right to
#  update a post
peInsufficientRights = "failed to {} post because the current user belongs " + \
    "to no group that provides sufficient rights"

## Represents an error that may occur within the posting module itself
class APostingError(AViewpointError):
    pass
    
## An engine used to create and edit posts
class APoster(AViewpoint):
    ## Edit an existing post
    def editPost(Self):
        template = pstEditErrorTemplateName
        
        if pstPostIDKey not in Self.Request:
            raise Self._Log.log(APostingError(peMissingPostID, "edit"), False)
            
        # Do NOT parse the post if it is to be edited.  The post can only be
        # edited if the user has the right to edit it, however.
        if Self._User.has(Right.toEdit, Self._Channel.name()):
            # Display the view
            template = pstEditTemplateName            

        # Display the view
        Self._View = AnArenaView(Self)
        Self._View.fetch(template) 
        
    ## Publish a post
    def publishPost(Self):
        template = pstEditErrorTemplateName
        
        # Ensure that the user has the right to publish posts in this channel
        if Self._User.has(Right.toEdit, Self._Channel.name()):
            
            # If an ID is given, then retrieve the post
            if "id" in Self.Request:
                for Post in Self._Channel.Posts():
                  break
                
                # Update the post
                Post.update()
                  
            else:
                Post = AnArenaPost.new(Self._Source, Log=Self._Log, Engine=Self)

                # Publish the post
                Post.publish()
                
            Post.readOnly = False
            Post.flush()

            # Ensure the user is redirected to the full view of their post
            Self.Request.query["title"] = \
                MiniFieldStorage("title", Post["title"])            
            
            # If the user is saving a draft, then we return them to the editing
            # view
            if ("draft" in Self.Request) and \
              (Self.Request["draft"].value.lower() == "y"):
                  template = pstEditTemplateName
                  # Reload the channel
                  Self.openChannel()
                  
            else:
                template = ""           
                Self.Request.query["view"] = \
                    MiniFieldStorage("view", "post/single")
            
            del Post
            
        Self._View = AnArenaView(Self)
        Self._View.fetch(template)
    
    ## Display the view to the user
    def beginView(Self, *theseTemplates):
        if pstActionQueryKey in Self.Request:
            Self.Request.query["view"] = MiniFieldStorage("view", 
                pstEditViewName)
            action = Self.Request[pstActionQueryKey].value
            action = action.lower()
            Self.Request[pstActionQueryKey].value = action
            
            # Does the user wish to update an existing post?
            if action == pstEditAction:
                Self.editPost()
                
            elif action == pstPublishAction:
                Self.publishPost()
                
            elif action == pstDeleteAction:
                Self.deletePost()
                
            else:
                #  Display the necessary view
                Self._View = AnArenaView(Self)
                Self._View.fetch()
                
        else:
            Self._View = AnArenaView(Self)
            Self._View.fetch()
