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

from os.path import join, dirname, abspath, basename, splitext, exists
from zope.app.form.browser.metaconfigure import BaseFormDirective

# XXX Should eventually fix those imports as they are too bound to
# Five internals.
from Products.Five.security import protectClass
from Products.Five.security import initializeClass
try:
    from Products.Five.browserconfigure import makeClassForTemplate
    from Products.Five.browserconfigure import _handle_for
    from Products.Five.pagetemplatefile import ZopeTwoPageTemplateFile
except ImportError:
    from Products.Five.browser.metaconfigure import makeClassForTemplate
    from Products.Five.browser.metaconfigure import _handle_for
    from Products.Five.browser.pagetemplatefile import ZopeTwoPageTemplateFile

#from zope.component.servicenames import Presentation
from zope.app.component.metaconfigure import handler
from zope.publisher.interfaces.browser import IBrowserRequest
from zope.interface import Interface

from Products.Fate.meta.view import EditView, AddView
from Products.Archetypes.ArchetypeTool import getType
from Products.Archetypes.Schema import Schemata, OrderedDict

from Products.CMFFormController.ControllerBase import ControllerBase

readActionMetadata = ControllerBase._read_action_metadata.im_func
readValidatorMetadata = ControllerBase._read_validator_metadata.im_func

def getSchemata(schema):
    schemata = OrderedDict()
    for f in schema.fields():
        sub = schemata.get(f.schemata)
        if sub is None:
            schemata[f.schemata] = sub = Schemata(name=f.schemata)
        sub.addField(f)
    return schemata

def _handle_view(directive, class_):
    _context = directive._context
    for_ = directive.for_
    name = directive.name
    layer = directive.layer
    permission = directive.permission

    _handle_for(_context, for_)

    _context.action(
        discriminator = ('view', (for_, layer), name, IBrowserRequest),
        callable = handler,
##         args = (Presentation, 'provideAdapter',
##                 IBrowserRequest, class_, name, [for_], Interface, layer,
##                 _context.info),
##          )
        args = ('provideAdapter', 
                (for_, layer), IBrowserRequest, name, class_, 
                _context.info),
         )        
        
    _context.action(
        discriminator = ('five:protectClass', class_),
        callable = protectClass,
        args = (class_, permission)
        )
    _context.action(
        discriminator = ('five:initialize:class', class_),
        callable = initializeClass,
        args = (class_,)
        )

def _handle_form_controller(template, class_):
    metadata = '%s.metadata', template
    if not exists(metadata):
        return
    tid = splitext(basename(template))[0]
    readActionMetadata(class_, tid, metadata)
    readValidatorMetadata(class_, tid, metadata)
    class_.template_id = tid

class AddFormDirective(BaseFormDirective):

    view = AddView
    default_template = abspath(join(dirname(__file__), 'add.pt'))
    schema = ()
    fields = None

    # default add form information
    factory = None
    product = None
    meta_type = None
    portal_type = None

    def _handle_arguments(self):
        try:
            type_info = getType(self.meta_type, self.product)
        except KeyError:
            raise ValueError, ("No archetype registered "
                               "under the meta_type %s "
                               "for %s" % (self.meta_type, self.product))

        if self.factory is None:
            self.factory = type_info['klass']

        if self.portal_type is None:
            self.portal_type = type_info['portal_type']

        if not self.schema:
            self.schema = type_info['schema']

    def __call__(self):
        self._handle_arguments()

        # XXX The following attributes probably don't have a meaningful
        # value right now.
        # - fields
        # - schema
        class_ = makeClassForTemplate(self.template, bases=self.bases)

        # XXX _schema, schemata and fieldNames may be overriden at runtime.
        class_.schema = self.schema
        class_.schemata = getSchemata(self.schema)
        class_.fieldNames = self.fields

        class_.label = self.label
        class_._factory = self.factory
        class_._product = self.product
        class_._meta_type = self.meta_type
        class_._portal_type = self.portal_type

        class_.generated_form = ZopeTwoPageTemplateFile(self.default_template)

        _handle_view(self, class_)
        _handle_form_controller(self.template, class_)

class EditFormDirective(BaseFormDirective):

    view = EditView
    default_template = abspath(join(dirname(__file__), 'edit.pt'))
    schema = ()
    fields = None

    def __call__(self):

        class_ = makeClassForTemplate(self.template, bases=self.bases)
        # XXX _schema, schemata and fieldNames will be setup at runtime.
        class_.label = self.label
        class_.generated_form = ZopeTwoPageTemplateFile(self.default_template)

        _handle_view(self, class_)
        _handle_form_controller(self.template, class_)
