# Copyright (c) 2002-2009 Infrae. All rights reserved.
# See also LICENSE.txt
from zope import component
from zope.schema.interfaces import IVocabularyFactory
from zope.publisher.browser import applySkin

# the default Zope 2 traverser
from ZPublisher.BaseRequest import DefaultPublishTraverse
from zope.traversing.adapters import DefaultTraversable
from zope.traversing.interfaces import ITraversable
from zope.traversing import namespace

from Products.SilvaLayout import interfaces


class SkinSetterMixin(object):
    def _setSkin(self, request):
        """Set skin if necessary"""
        from_request = request.get('skin_from_request')
        if from_request:
            skin = request.getPresentationSkin()
            request.set('resourcebase', self.context.aq_inner)
            return adapters.Traverser.traverse(self, path, default, request)
        try:
            metadata = interfaces.IMetadata(self.context)
        except TypeError, e:
            request.set('resourcebase', self.context.aq_inner)
        else:
            try:
                skin = metadata('silva-layout', 'skin')
            except AttributeError:
                # AttributeError means that the silva-layout metadata set
                # was not installed, so just bail out without setting any
                # skin
                return

            # Skin name can be an empty string in case
            # its value was set to be 'acquired'.
            if skin:
                vocab = component.getUtility(IVocabularyFactory,
                                             name='Browser Skins')
                skin_iface = vocab(None).getTermByToken(skin).value
                if not skin_iface.providedBy(request):
                    # simply override any previously set skin
                    applySkin(request, skin_iface)
                    # set the base url for resources
                    request.set('resourcebase', self.context.aq_inner)


class SkinnyTraverser(DefaultPublishTraverse, SkinSetterMixin):
    def publishTraverse(self, request, name):
        self._setSkin(request)
        return super(SkinnyTraverser, self).publishTraverse(request, name)

    def browserDefault(self, request):
        self._setSkin(request)
        # We only reply to GET and POST requests, others are delegated
        # to the object.
        if request.method in ('GET', 'POST',):
            return super(SkinnyTraverser, self).browserDefault(request)
        return self.context, ()


class SkinnyTraversable(SkinSetterMixin):
    def traverse(self, name, furtherPath):
        self._setSkin(self.request)
        return super(SkinnyTraversable, self).traverse(name, furtherPath)


class ResourceSkinnyTraversable(SkinnyTraversable, namespace.resource):
    pass


class ViewSkinnyTraversable(SkinnyTraversable, namespace.view):
    pass

