# Copyright (c) 2004 Guido Wesdorp. All rights reserved.
# See also LICENSE.txt
# $Id: SilvaBlog.py,v 1.14 2004/06/04 19:29:36 johnny Exp $

# Zope3 imports
from zope.interface import implements

# Zope imports
from Globals import InitializeClass
from DateTime import DateTime
from AccessControl import ClassSecurityInfo
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2

# Silva imports
from Products.SilvaMetadata.Compatibility import registerTypeForMetadata
from Products.Silva import SilvaPermissions
from Products.Silva.helpers import add_and_edit
from Products.Silva.SilvaObject import SilvaObject
#from Products.Silva.Folder import Folder
from Products.Silva.Publication import Publication
from Products.Silva.interfaces import IContainer 
from Products.Silva import mangle
from Products.Silva.adapters.renderable import getRenderableAdapter

# Silva Blog imports
from Products.SilvaBlog.install_blog import setup_catalog
from Products.SilvaBlog.interfaces import\
        ISilvaBlog, ISilvaBlogArticle, IBlogCategory, IRSSFeed, IBlog
icon = "www/silvablog.png"

# this is nasty... a bit of a trick to get SilvaObject's methods
# get called before SimpleItem's, but BTreeFolder2's before Folder's
class SilvaBlog(BTreeFolder2, Publication):
    """Silva Blog
      
       >>> from zope.interface.verify import verifyClass
       >>> verifyClass(ISilvaBlog, SilvaBlog)
       True
    """

    security = ClassSecurityInfo()
    meta_type = 'Silva Blog'
    implements(ISilvaBlog)

    def __init__(self, id):
        Publication.__init__(self, id)
        BTreeFolder2.__init__(self, id)
        self._initBTrees()
        self.comments_allowed = 1
    
    def manage_afterAdd(self, *args, **kwargs):
       Publication.manage_afterAdd(self, *args, **kwargs)

    def manage_beforeDelete(self, *args, **kwargs):
       Publication.manage_beforeDelete(self, *args, **kwargs)

    def manage_afterClone(self, *args, **kwargs):
       Publication.manage_afterClone(self, *args, **kwargs)

    def get_silva_addables_allowed_in_publication(self):
        # maybe we can return assets as well later...
        return ['Silva Image', 
                'Silva Blog Article']

    def to_xml(self, *args, **kwargs):
        Publication.to_xml(self, *args, **kwargs)
    
    # Accessors
    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                                'get_current_items')
    def get_current_items(self, month=None, year=None):
        """get the current items for this blog"""
        adapter = IBlog(self)
        return adapter.get_current_items(month, year)
    
    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                                'get_categories')
    def get_categories(self):
        """ returns the categories the article is published under,
            u'' otherwise
        """
        adapter = IBlogCategory(self)
        return adapter.get_categories()
    
    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                                'get_articles_for_category')
    def get_articles_for_category(self, category=None):
        """ return a list of ISilvaBlogArticle objects published under
            subject otherwise return all ISilvaBlogArticles
        """
        result = []
        if category is None:
            return self.get_current_items()
        
        brains = self.service_catalog({'silva-extrakeywords':category})
        for b in brains:
            obj = b.getObject()
            if ISilvaBlogArticle.providedBy(obj):
                result.append(obj)

        return result
        
    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                                'get_editable_items')
    def get_editable_items(self, month=None, year=None):
        """get the current items for this blog
           returns list of tuples (obj, publication_datetime)
        """
        adapter = IBlog(self)
        return adapter.get_editable_items(month, year)
    
    ##############################
    # viewcode for tabedit
    #

    # method overridden from ViewCode, will provide a handy set of dicts 
    # for tab_edit
    security.declareProtected(SilvaPermissions.ReadSilvaContent,
                              'get_processed_items')
    def get_processed_items(self, month=None, year=None):
        """helper method overridden from ViewCode for tab_edit to
           provide a set of dicts
        """
        adapter = IBlog(self)
        return adapter.get_processed_items(month, year)

    security.declareProtected(SilvaPermissions.ChangeSilvaContent, 
                                'get_processed_status_tree')
    def get_processed_status_tree(self, status, offset, limit=25):
        if status == 'closed':
            status = ['closed', 'last_closed']
        query = {'meta_type': 'Silva Blog Article', 
                'get_version_status': status,
                'sort_on': 'get_modification_datetime',
                'sort_order': 'descending',
                'path': '/'.join(self.getPhysicalPath()),
                }
        objs = [obj.getObject().object() 
                  for obj in self.blog_catalog(query)[offset:offset+limit]]
        ret = []
        for obj in objs:
            infodict = {}
            ret.append(infodict)
            
            infodict['id'] = mangle.String.truncate(obj.id, 22)

            # do not smash the smi because one object is broken
            if obj.meta_type[:6] == 'Broken':
                infodict['meta_type'] = obj.meta_type
                infodict['title_html'] = 'Broken content object'
                for key in ('absolute_url', 'icon', \
                            'implements_content', 'implements_container',
                            'implements_versioning'):
                    infodict[key]=''
                continue

            infodict['title'] = obj.get_title_editable()
            infodict['meta_type'] = obj.meta_type
            infodict['absolute_url'] = obj.absolute_url()
            infodict['icon'] = self.render_icon(obj)            
            
            infodict['implements_content'] = obj.implements_content()
            if infodict['implements_content']:
                infodict['is_default'] = obj.is_default()
                infodict['container_meta_type'] = \
                          obj.get_container().meta_type

            infodict['implements_container'] = obj.implements_container()

            infodict['implements_versioning'] = obj.implements_versioning()
            if infodict['implements_versioning']:
                status, style, public_status = obj.get_object_status()
                infodict['status'] = status
                infodict['status_style'] = style
                infodict['public_status'] = public_status
                infodict['ref'] = self.create_ref(obj)

                datetime = obj.get_next_version_publication_datetime()
                if datetime:
                    str_datetime = mangle.DateTime(datetime).toShortStr()
                    infodict['next_version_publication_datetime'] = \
                                str_datetime

                datetime = obj.get_public_version_publication_datetime()
                if datetime:
                    str_datetime = mangle.DateTime(datetime).toDateStr()
                    infodict['public_version_publication_datetime'] = \
                                str_datetime

                datetime = obj.get_next_version_expiration_datetime()
                if datetime:
                    str_datetime = mangle.DateTime(datetime).toShortStr()
                    infodict['next_version_expiration_datetime'] = \
                                str_datetime
                    
                datetime = obj.get_public_version_expiration_datetime()
                if datetime:
                    str_datetime = mangle.DateTime(datetime).toDateStr()
                    infodict['public_version_expiration_datetime'] = \
                                str_datetime
        return ret

    security.declareProtected(SilvaPermissions.ChangeSilvaContent, 
                                'set_blog_prefs')
    def set_blog_prefs(self, comments_allowed):
        """ set blog preferences """
        if comments_allowed == 1:
            self.comments_allowed = 1
        else:
            self.comments_allowed = 0
        return
    
    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                                'get_recent_article')
    def get_recent_article(self):
        """ get the last, published blog article """
        items = self.get_current_items()
        if items:
            return items[0]

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                                'get_archive')
    def get_archive(self):
        """returns a dictionary with:
            keys: years
            values: months (list)
           under which articles are published
        """
        result = {}
        query = {'meta_type': 'Silva Blog Entry Version', 
                 'version_status': 'public'
                 }
        brains = self.blog_catalog(query)
        objs = [obj.getObject() for obj in brains]
        for obj in objs:
            datetime = obj.publication_datetime()
            year = datetime.year()
            month = datetime.month()
            if not result.has_key(year):
                result[year] = [month]
            elif month not in result[year]:
                result[year].append(month)

        return result

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                                'get_months')
    def get_archived_months(self, currentyear):
        """Returns a list of tuples in which months articles where published"""
        result = []
        archive = self.get_archive()
        archived_months = archive.get(currentyear, [])
        for m in range(1, 13):
            dt = DateTime("1970/%s/01" % str(m))
            month = dt.Month()
            if m in archived_months:
              result.append((1, month))
            else:
              result.append((0, month))
        return result 

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                                'get_blog')
    def get_blog(self):
        """returns self"""
        return self
    
    # code copied from SilvaNews.NewsViewer
    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'rss')
    def rss(self, REQUEST=None):
        """Return the contents of this viewer as an RSS/RDF (RSS 1.0) feed"""
        adapter = IRSSFeed(self)
        return adapter.rss(REQUEST)

InitializeClass(SilvaBlog)

def manage_addSilvaBlog(self, id, title, REQUEST=None):
    """adds a SilvaBlog product in the ZMI"""
    if not mangle.Id(self, id).isValid():
        return
    o = SilvaBlog(id)
    self._setObject(id, o)
    object = getattr(self, id)
    object.set_title(title)
    # setup routines
    setup_catalog(object)
    add_and_edit(self, id, REQUEST)
    return ''

manage_addSilvaBlogForm = PageTemplateFile("www/silvaBlogAdd", 
                                    globals(),
                                    __name__='manage_addSilvaBlogForm')

registerTypeForMetadata(SilvaBlog.meta_type)

