"""
Overlay to provide multilanguage / versionion for all types objects
"""

from Acquisition import aq_base, aq_inner, aq_chain, aq_parent, ImplicitAcquisitionWrapper

from OFS.ObjectManager import ObjectManager
from Products.CMFCore.utils import _verifyActionPermissions, _checkPermission
from Products.CMFCore.CMFCorePermissions import View, ManageProperties, ListFolderContents, ModifyPortalContent
from Products.CMFCore.CMFCorePermissions import AddPortalFolders, AddPortalContent
from Products.CMFDefault.SkinnedFolder import SkinnedFolder
from AccessControl import Permissions, getSecurityManager, ClassSecurityInfo
from Products.CMFCore import CMFCorePermissions
from Globals import InitializeClass

from Products.CMFTypes.Referenceable import Referenceable
from Products.CMFPlone.PloneFolder import PloneFolder, _getViewFor

factory_type_information = { 'id'             : 'I18NLayer'
                             , 'meta_type'      : 'I18NLayer'
                             , 'description'    : """ """
                             , 'icon'           : 'document_icon.gif'
                             , 'product'        : 'CMFTypes'
                             , 'factory'        : 'addI18NLayer'
                             , 'filter_content_types' : 0
                             , 'immediate_view' : 'folder_listing'
                             , 'actions'        :
                                ( { 'id'            : 'view'
                                  , 'name'          : 'View'
                                  , 'action'        : ''
                                  , 'permissions'   :
                                     (CMFCorePermissions.View,)
                                  , 'category'      : 'folder'
                                  }
                                , { 'id'            : 'folderlisting'
                                  , 'name'          : 'Folder Listing'
                                  , 'action'        : 'folder_listing'
                                  , 'permissions'   :
                                     (Permissions.access_contents_information,)
                                  , 'category'      : 'folder'
                                  }
                                , { 'id'            : 'edit'
                                  , 'name'          : 'Edit'
                                  , 'action'        : 'folder_edit_form'
                                  , 'permissions'   :
                                     (CMFCorePermissions.ManageProperties,)
                                  , 'category'      : 'folder'
                                  }
                                )
                             }

_marker = []


class I18NContentBase:

    def __init__(self, layer, REQUEST):

    	self.layer=layer
	self.REQUEST=REQUEST

	available_languages=self.getFilteredLanguageMap().keys()
	self.languages=self.getLanguagesFromRequest() + list(available_languages)

    def Layer(self):
    	return self.layer

    def Languages(self):
    	return self.languages

    def getLanguagesFromRequest(self):

    	language=self.REQUEST.cookies.get('I18N_CONTENT_LANGUAGE', None)

	accept=self.REQUEST.get('HTTP_ACCEPT_LANGUAGE','')
	accept=accept.split(',')
	accept=map(lambda x: x.split(';')[0].strip(), accept)

	default_language=self.Layer().portal_properties.site_properties.default_language

	languages=[language,]+accept+[default_language,]

	return languages

    def getObject(self):

    	# returns the object holding language information
	# for language self.language

	# ovewrite for each implementation
	raise "NotImplementedError"

    def getFilteredLanguageMap(self):

    	# returns a language code to id mapping
	raise "NotImplementedError"

    def setServed(self, lang):
    	self.served_language=lang


    def Served(self):
    	try: return self.served_language
	except: return None


    def existingLanguages(self):

        existing_languages=()
	for code, name in self.Layer().availableLanguages():
	    existing_languages=existing_languages+(code,)
	return existing_languages


class I18NContentLayer(I18NContentBase):

    def getFilteredLanguageMap(self):

    	# do this with a catalog pathindex search to
	# avoid looking up of each object for permission checks

	layer=self.Layer()
	catalog = layer.portal_catalog
	available_languages=self.existingLanguages()

	query={}
	path='/'.join(layer.getPhysicalPath())
	query.update({'path':[path,]})

	# print "query", query
	result=catalog(query)

	objs={}
	for r in result:
	    id = r.getPath().split('/')[-1]
	    if id in available_languages:
            	objs.update({id: id})

	return objs

    def getObject(self):

    	layer=self.Layer()
    	base = aq_base(layer)

    	for lang in self.Languages():

	    if hasattr(base, lang):
	    	self.setServed(lang)
	    	return getattr(layer, lang)

	if not _checkPermission(ModifyPortalContent, layer):
	    raise "Unauthorized"

	return None




class I18NLayer ( PloneFolder, Referenceable ):

    """ container object which transparently wrapps multiple
        subobjects as language representations
    """

    meta_type = portal_tyle = 'I18NLayer'
    isPrincipiaFolderish=0

    security = ClassSecurityInfo()


    def __init__(self, oid, **kwargs):
	""" """
	PloneFolder.__init__(self, oid)

    security.declarePrivate('retrieveContentLayer')
    def retrieveContentLayer(self, REQUEST=None):
	""" """
	# get request
	if not REQUEST: REQUEST=self.REQUEST
	# make new contentlayer instance
	return I18NContentLayer(self, REQUEST)

    security.declarePublic('retrieveLanguageContent')
    def retrieveLanguageContent(self, REQUEST=None):
	""" """
    	return self.retrieveContentLayer(REQUEST).getObject()

    security.declarePublic('retrieveI18NContentLayer')
    def retrieveI18NContentLayerURL(self, REQUEST=None):
    	""" """
    	return self.absolute_url()

    security.declarePublic('retrieveFilteredLanguages')
    def retrieveFilteredLanguages(self, REQUEST=None):
    	""" """
	return self.retrieveContentLayer(REQUEST).getFilteredLanguageMap()

    security.declarePublic('retrieveExistingLanguages')
    def retrieveExistingLanguages(self, REQUEST=None):
	""" """
    	return self.retrieveExistingLanguages()

    security.declarePrivate('mapCore')
    def mapCore(self, name, *args, **kw):
	"""
	maps methods on the given language object
	"""

    	ob = self.retrieveLanguageContent()
	if ob is not None:
	    if hasattr(aq_base(ob), name):
	        method = getattr(ob, name)
	    else:
	        raise "AttributeError", name
	else:
	    method=getattr(PloneFolder, name)
	    args=(self,)+args

	if callable(method): return apply(method, args, kw)
	else: return method


    def __call__(self):
        '''
        Invokes the default view.
        '''
	ob = self.retrieveLanguageContent()
	if not ob: ob=self

        view = _getViewFor(ob, 'view', 'folderlisting')
        if getattr(aq_base(view), 'isDocTemp', 0):
            return apply(view, (self, self.REQUEST))
        else:
             return view()

    view = index_html = __call__

    security.declarePublic('title_or_id')
    def title_or_id(self):
    	""" """
    	return self.mapCore('title_or_id')

    security.declarePublic('get_size')
    def get_size(self):
    	"""
	WebDAV needs this
	"""
    	try: return self.mapCore('get_size')
	except: return None

    getSize=get_size

    security.declarePublic('getIcon')
    def getIcon(self, relative_to_portal=0):
    	""" """
    	return self.mapCore('getIcon', relative_to_portal=relative_to_portal)

    security.declarePublic('Title')
    def Title(self):
    	""" """
    	return self.mapCore('Title')

    security.declarePublic('Creator')
    def Creator(self):
    	""" """
        return self.mapCore('Creator')

    security.declarePublic('Subject')
    def Subject(self):
    	""" """
        return self.mapCore('Subject')

    security.declarePublic('Publisher')
    def Publisher(self):
    	""" """
        return self.mapCore('Publisher')

    security.declarePublic('Description')
    def Description(self):
    	""" """
        return self.mapCore('Description')

    security.declarePublic('Contributors')
    def Contributors(self):
    	""" """
        return self.mapCore('Contributors')

    security.declarePublic('Date')
    def Date(self):
    	""" """
    	return self.mapCore('Date')

    security.declarePublic('CreationDate')
    def CreationDate(self):
    	""" """
        return self.mapCore('CreationDate')

    security.declarePublic('EffectiveDate')
    def EffectiveDate(self):
    	""" """
        return self.mapCore('EffectiveDate')

    security.declarePublic('ExpirationDate')
    def ExpirationDate(self):
    	""" """
        return self.mapCore('ExpirationDate')

    security.declarePublic('ModificationDate')
    def ModificationDate(self):
    	""" """
        return self.mapCore('ModificationDate')

    security.declarePublic('Type')
    def Type(self):
    	""" """
        return self.mapCore('Type')

    security.declarePublic('Format')
    def Format(self):
    	""" """
        return self.mapCore('Format')

    security.declarePublic('Identifier')
    def Identifier(self):
    	""" """
        return self.mapCore('Identifier')

    security.declarePublic('Language')
    def Language(self):
    	""" """
        return self.retrieveContentLayer().Served()

    security.declarePublic('Rights')
    def Rights(self):
    	""" """
        return self.mapCore('Rights')

    def content_type(self):
	"""
	WebDAV needs this
	"""
    	try: return self.Format()
	except: return 'application/unknown'

    security.declarePublic('isEffective')
    def isEffective(self, date):
    	""" """
    	return self.mapCore('isEffective', date)

    security.declarePublic('created')
    def created(self):
    	""" """
        return self.mapCore('created')

    security.declarePublic('effective')
    def effective(self):
    	""" """
        return self.mapCore('effective')

    security.declarePublic('expires')
    def expires(self):
    	""" """
        return self.mapCore('expires')

    security.declarePublic('modified')
    def modified(self):
    	""" """
        return self.mapCore('modified')



def addI18NLayer(self, id, REQUEST=None):
    """ adds an i18n Layer Object container """
    o = I18NLayer(id)
    self._setObject(id, o)
    if REQUEST is not None:
        REQUEST['RESPONSE'].redirect( sf.absolute_url() + '/manage_main' )


InitializeClass(I18NLayer)
