"""
$Id: __init__.py 1074 2005-04-05 02:38:02Z sidnei $
"""

from AccessControl import getSecurityManager

from Products.Five.browser import BrowserView as View
from Products.CMFCore.utils import getToolByName
from Products.Archetypes.Renderer import renderer

class AddView(View):

    _factory = None
    _portal_type = None
    _content_name = None

    def setMessage(self, message):
        self.request.set('portal_status_message', message)

    def _createStub(self):
        """
        Create stub object against which to render the schema widgets.
        """
        instance = self._factory('')
        wrapped = instance.__of__(self.context)
        # set current user as the owner to get reasonable permissions
        user = getSecurityManager().getUser()
        if user.getId() is not None: # i.e. not anonymous
            wrapped.changeOwnership(user)
            wrapped.manage_setLocalRoles(user.getId(), ('Owner',))
        wrapped.initializeArchetype()
        return wrapped

    # Allow access to the object stub via traversal
    object_stub = property(_createStub)

    def _setupView(self, fieldset=None):
        request = self.request

        stub = self._createStub()
        self._stub = [stub]

        self.schema = stub.Schema()
        self.schemata = stub.Schemata()
        self.type_title = stub.getTypeInfo().title_or_id()
        self.type_id = self._portal_type
        schematas = self.schemata
        fieldsets = [key for key in schematas.keys()
                     if (key != 'metadata') and
                     (schematas[key].editableFields(stub))]
        self.fieldsets = fieldsets
        default_fieldset = ((not schematas or
                             schematas.has_key('default'))
                            and 'default' or fieldsets[0])
        if fieldset is None:
            fieldset = request.get('fieldset', default_fieldset)
        else:
            request.set('fieldset', fieldset)
        # XXX This assertion can fail if a validation failure occurs
        # in a fieldset that the user is not allowed to access.
        assert fieldset in fieldsets, (fieldset, fieldsets, self.errors)
        self.fieldset = fieldset
        self.fields = schematas[fieldset].editableFields(stub)
        self.fieldNames = tuple([f.getName() for f in self.fields])

        self.helper_css = self._getUniqueWidgetAttr(self.fields, 'helper_css')
        self.helper_js = self._getUniqueWidgetAttr(self.fields, 'helper_js')

    def _getUniqueWidgetAttr(self, fields, attr):
        order = []
        for f in fields:
            widget = f.widget
            helper = getattr(widget, attr, None)
            # We expect the attribute value to be a iterable.
            if helper:
                [order.append(item) for item in helper
                if item not in order]

        return order

    def update(self):
        request = self.request
        self.errors = {}

        self._setupView()

        if not request.get('form.submitted'):
            return

	if request.get('form.button.cancel', None):
            response = self.request.RESPONSE
            response.redirect(self.cancelURL(), lock=1)
	    return
	    
        stub = self._stub[0]
        self.errors = stub.validate(REQUEST=self.request, errors={})

        if self.errors:
            # Abort transaction just to make sure
            import transaction as txn
            txn.abort()
            self.setMessage('Please correct the indicated errors.')
            return
        if request.get('id'):
            self._content_name = self.request['id']
        else:
            # XXX Could use INameChooser
            chooser = self.context.generateUniqueId
            self._content_name = chooser(type_name=self._portal_type)
        instance = self.createAndAdd()

        # Now, validate whole created object integrity. This could
        # potentially happen earlier if we pass the right arguments
        # into validate.
        self.errors = instance.validate(REQUEST=None, errors={},
                                        data=1, metadata=1)
        if self.errors:
            for key in self.errors.keys():
                # Set current fieldset to the
                for name, schemata in self.schemata.items():
                    if schemata.has_key(key):
                        self._setupView(fieldset=name)
            # Abort transaction just to make sure
            import transaction as txn
            txn.abort()
            self.setMessage('Please correct the indicated errors.')
            return

        self.setMessage('Your changes have been saved.')

        if hasattr(self.request, 'RESPONSE'):
            response = self.request.RESPONSE
            response.redirect(self.nextURL(instance), lock=1)

        return instance

    def createAndAdd(self):
        # XXX Factory might change the name. A fix has been checked in
        # to CMF to return the id, if changed, from invokeFactory.
        name = self.context.invokeFactory(self._portal_type, self._content_name)
        if name is None:
            name = self._content_name
        instance = self.context._getOb(name)
        # Fetch the values from request and store them.
        instance.processForm()
        return instance

    def nextURL(self, instance):
        fieldsets = self.fieldsets
        schematas = self.schemata
        if fieldsets and len(fieldsets) > 1:
            default_fieldset = (schematas.has_key('default')
                                 and 'default' or fieldsets[0])
            # The next fieldset is either the first or second depending if
            # the first was the default.
            next_fieldset = (fieldsets[0] == default_fieldset and
                             fieldsets[1] or fieldsets[0])
            return (instance.getActionInfo('object/edit')['url'] +
                                                 '?fieldset=%s'%next_fieldset)
        return instance.getActionInfo('object/view')['url']

    def cancelURL(self):
	"""
	   On cancel redirect to the referring url, otherwise to the container
	"""
	# This should be replaced with the new i18nable status message stuff
	message = '?portal_status_message=' \
	          'Your new %s has been cancelled.'%self.type_title
	request = self.request
	referrer = request.get('ORIG_REFERRER', None)
	# Don't redirect back to the current page
	if referrer is not None and referrer != request.get('ACTUAL_URL'):
	    return referrer+message
        # Return to the view of the context object if no referrer is available
        return self.context.getActionInfo('object/view')['url']+message

    def widget(self, field_name, mode="view", field=None, **kwargs):
        """Returns the rendered widget
        """
        if field is None:
            field = self.schema[field_name]
        widget = field.widget
        return renderer.render(field_name, mode, widget,
                               self._stub[0], field=field, **kwargs)


class EditView(View):

    def setMessage(self, message):
        self.request.set('portal_status_message', message)

    def _setupView(self, fieldset=None):
        request = self.request

        self.schema = self.context.Schema()
        self.schemata = self.context.Schemata()
        self.type_title = self.context.getTypeInfo().title_or_id()
        schematas = self.schemata
        fieldsets = [key for key in schematas.keys()
                     if (key != 'metadata') and
                     (schematas[key].editableFields(self.context))]
        self.fieldsets = fieldsets
        default_fieldset = ((not schematas or
                             schematas.has_key('default'))
                            and 'default' or fieldsets[0])
        if fieldset is None:
            fieldset = request.get('fieldset', default_fieldset)
        else:
            request.set('fieldset', fieldset)
        # XXX This assertion can fail if a validation failure occurs
        # in a fieldset that the user is not allowed to access.
        assert fieldset in fieldsets, (fieldset, fieldsets, self.errors)
        self.fieldset = fieldset
        self.fields = schematas[fieldset].editableFields(self.context)
        self.fieldNames = tuple([f.getName() for f in self.fields])

    def update(self):
        request = self.request
        self.errors = {}

        self._setupView()

        if not request.get('form.submitted'):
            return

        self.errors = self.context.validate(REQUEST=self.request, errors={})

        if self.errors:
            # Abort transaction just to make sure
            import transaction as txn
            txn.abort()
            self.setMessage('Please correct the indicated errors.')
            return

        self.context.processForm()

        # Now, validate whole object integrity. This could potentially
        # happen earlier if we pass the right arguments into validate.
        self.errors = self.context.validate(REQUEST=None, errors={},
                                            data=1, metadata=1)
        if self.errors:
            for key in self.errors.keys():
                # Set current fieldset to the
                for name, schemata in self.schemata.items():
                    if schemata.has_key(key):
                        self._setupView(fieldset=name)
            # Abort transaction just to make sure
            import transaction as txn
            txn.abort()
            self.setMessage('Please correct the indicated errors.')
            return

        self.setMessage('Your changes have been saved.')

        if hasattr(self.request, 'RESPONSE'):
            response = self.request.RESPONSE
            response.redirect(self.nextURL(self.context), lock=1)

        return self.context

    def nextURL(self, instance):
        # XXX Lookup the view action later, or setup browserDefault.
        return instance.absolute_url() + '/view'

    def widget(self, field_name, mode="view", field=None, **kwargs):
        """Returns the rendered widget
        """
        if field is None:
            field = self.schema[field_name]
        widget = field.widget
        return renderer.render(field_name, mode, widget,
                               self.context, field=field, **kwargs)
