from AccessControl import ClassSecurityInfo
from OFS.SimpleItem import SimpleItem
from Globals import InitializeClass
from Products.ZCatalog.CatalogPathAwareness import CatalogPathAware
from DateTime import DateTime

from Products.Silva import SilvaPermissions
from Products.SilvaMetadata.Exceptions import BindingError

from interfaces import IVersion

class Version(SimpleItem):

    __implements__ = IVersion

    security = ClassSecurityInfo()

    object_type = 'versioned_content'
    _title = '[No title yet]'
    
    def __init__(self, id, title):
        self.id = id
        self._title = title
        self._v_creation_datetime = DateTime()
        
    def manage_afterAdd(self, item, container):
        Version.inheritedAttribute('manage_afterAdd')(
            self, item, container)
        timings = {}
        ctime = getattr(self, '_v_creation_datetime', None)
        if ctime is None:
            return
        try:
            binding = self.service_metadata.getMetadata(self)
        except BindingError:
            return
        if binding is None:
            return
        for elem in ('creationtime', 'modificationtime'):
            old = binding.get('silva-extra', element_id=elem)
            if old is None:
                timings[elem] = ctime
        binding.setValues('silva-extra', timings)
            
    security.declareProtected(
        SilvaPermissions.ChangeSilvaContent, 'set_title')
    def set_title(self, title):
        """Set title of version.
        """
        # FIXME: Ugh. I get unicode from formulator but this will not validate
        # when using the metadata system. So first make it into utf-8 again..
        # XXX Could set it directly with _setData instead?
        title = title.encode('utf-8')
        binding = self.service_metadata.getMetadata(self)
        binding.setValues(
            'silva-content', {'maintitle': title})

    security.declareProtected(
        SilvaPermissions.AccessContentsInformation, 'get_title')
    def get_title(self):
        """get title of version.
        """
        binding = self.service_metadata.getMetadata(self)
        return binding.get(
            'silva-content', element_id='maintitle')

    security.declareProtected(
        SilvaPermissions.AccessContentsInformation, 'get_short_title')
    def get_short_title(self):
        """Get the title of the version.
        """
        binding = self.service_metadata.getMetadata(self)
        short_title = binding.get(
            'silva-content', element_id='shorttitle')
        if not short_title:
            return self.get_title()
        return short_title
        
    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'version_status')
    def version_status(self):
        """Returns the status of the current version
        Can be 'unapproved', 'approved', 'public', 'last_closed' or 'closed'
        """
        status = None
        unapproved_version = self.get_unapproved_version(0)
        approved_version = self.get_approved_version(0)
        public_version = self.get_public_version(0)
        previous_versions = self.get_previous_versions()
        if unapproved_version and unapproved_version == self.id:
            status = "unapproved"
        elif approved_version and approved_version == self.id:
            status = "approved"
        elif public_version and public_version == self.id:
            status = "public"
        else:
            if previous_versions and previous_versions[-1] == self.id:
                status = "last_closed"
            elif self.id in previous_versions:
                status = "closed"
            else:
                # this is a completely new version not even registered
                # with the machinery yet
                status = 'unapproved' 
        return status

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'object_path')
    def object_path(self):
        """Returns the physical path of the object
        (for identification-purposes)
        """
        return self.aq_inner.aq_parent.getPhysicalPath()

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'version')
    def version(self):
        """Returns the version
        """
        return (self.id,
                self.publication_datetime(),
                self.expiration_datetime())

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'object')
    def object(self):
        """Returns the object this version belongs to
        """
        return self.aq_inner.aq_parent


    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'object')
    def get_version(self):
        """Returns itself. Used by acquisition to get the
           neared version.
        """
        return self.aq_inner


    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'publication_datetime')
    def publication_datetime(self):
        """Returns the publication_datetime of this version (if any)
        """
        status = self.version_status()
        if status == 'closed' or status == 'last_closed':
            return None
        else:
            return getattr(self,
                           'get_%s_version_publication_datetime' % status)(0)

    security.declareProtected(SilvaPermissions.AccessContentsInformation,
                              'expiration_datetime')
    def expiration_datetime(self):
        """Returns the expiration_datetime of this version (if any)
        """
        status = self.version_status()
        if status == 'closed' or status == 'last_closed':
            return None
        else:
            return getattr(self,
                           'get_%s_version_expiration_datetime' % status)(0)

InitializeClass(Version)

class CatalogedVersion(Version):
    """Base class for cataloged version objects"""

    def getPath(self):
        return '/'.join(self.getPhysicalPath())
    
    def index_object(self):
        """Index"""
        catalog = getattr(self, 'service_catalog', None)
        if catalog is not None:
            catalog.catalog_object(self, self.getPath())

    def unindex_object(self):
        """Unindex"""
        catalog = getattr(self, 'service_catalog', None)
        if catalog is not None:
            catalog.uncatalog_object(self.getPath())

    def reindex_object(self):
        """Reindex."""
        catalog = getattr(self, 'service_catalog', None)
        if catalog is None:
            return 
        path = self.getPath()
        catalog.uncatalog_object(path)
        catalog.catalog_object(self, path)
        
    
InitializeClass(CatalogedVersion)

