from Acquisition import aq_parent, aq_inner
from Products.CMFCore.permissions import ManagePortal
from Products.CMFDefault.PropertiesTool import PropertiesTool as BaseTool

from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from OFS.Folder import Folder
from App.class_init import InitializeClass
from zope.interface import implements

from OFS.PropertyManager import PropertyManager
from OFS.SimpleItem import SimpleItem
from AccessControl import ClassSecurityInfo
from Products.CMFPlone.PloneBaseTool import PloneBaseTool
from Products.CMFPlone.interfaces \
    import IPropertiesTool, ISimpleItemWithProperties


class PropertiesTool(PloneBaseTool, Folder, BaseTool):

    id = BaseTool.id
    toolicon = 'skins/plone_images/topic_icon.png'

    meta_type = 'Plone Properties Tool'
    meta_types = ((
        {'name': 'Plone Property Sheet',
         'action': 'manage_addPropertySheetForm'},
        ))

    implements(IPropertiesTool)

    manage_options = ((Folder.manage_options[0], ) +
                        BaseTool.manage_options)

    manage_addPropertySheetForm = PageTemplateFile('www/addPropertySheet',
                                                   globals())

    security = ClassSecurityInfo()

    def all_meta_types(self, interfaces=None):
        return self.meta_types

    def title(self):
        """ Return BaseTool title
        """
        return BaseTool.title(self)

    security.declareProtected(ManagePortal, 'addPropertySheet')
    def addPropertySheet(self, id, title='', propertysheet=None):
        # Add a new PropertySheet.
        o = SimpleItemWithProperties(id, title)

        # copy the propertysheet values onto the new instance
        if propertysheet is not None:
            if not hasattr(propertysheet, 'propertyIds'):
                raise TypeError('propertysheet needs to be a PropertyManager')

            for property in propertysheet.propertyMap():
                pid = property.get('id')
                ptype = property.get('type')
                pvalue = propertysheet.getProperty(pid)
                if not hasattr(o, pid):
                    o._setProperty(pid, pvalue, ptype)

        self._setObject(id, o)

    security.declareProtected(ManagePortal, 'manage_addPropertySheet')
    def manage_addPropertySheet(self, id, title='',
                                propertysheet=None, REQUEST=None):
        """ Add a instance of a Property Sheet if handed a
        propertysheet put the properties into new propertysheet.
        """
        self.addPropertySheet(id, title, propertysheet)

        if REQUEST is not None:
            return self.manage_main()

    #
    #   'portal_properties' interface methods
    #
    security.declareProtected(ManagePortal, 'editProperties')
    def editProperties(self, props):
        # Change portal settings.
        aq_parent(aq_inner(self)).manage_changeProperties(props)
        if hasattr(self, 'propertysheets'):
            ps = self.propertysheets
            if hasattr(ps, 'props'):
                ps.props.manage_changeProperties(props)


PropertiesTool.__doc__ = BaseTool.__doc__

InitializeClass(PropertiesTool)


class SimpleItemWithProperties (PropertyManager, SimpleItem):
    """
    A common base class for objects with configurable
    properties in a fixed schema.
    """

    implements(ISimpleItemWithProperties)

    def __init__(self, id, title=''):
        self.id = id
        self.title = title

    meta_type = 'Plone Property Sheet'

    manage_options = (PropertyManager.manage_options
                     + SimpleItem.manage_options)

InitializeClass(SimpleItemWithProperties)
