import os, sys

from zope.interface import implements
from zope import component

from Globals import InitializeClass
from AccessControl import ClassSecurityInfo, getSecurityManager

from Products.Silva.Asset import Asset
from Products.Silva import SilvaPermissions
from Products.Formulator.Form import ZMIForm
from Products.Formulator.XMLToForm import XMLToForm
from Products.Formulator.Errors import FormValidationError

from Products.SilvaLayout.interfaces import ILayoutConfiguration, ILayoutConfigurationForm

class LayoutConfiguration(Asset):
    """Configuration object for layout.

    Layouts can access attributes on the configuration object.
    """
    security = ClassSecurityInfo()

    meta_type = "Silva Layout Configuration"
    
    implements(ILayoutConfiguration)

    def __init__(self, id):
        self.id = id
        self.skin_id = None

    security.declareProtected(SilvaPermissions.ChangeSilvaContent,
                              'forms')
    def forms(self):
        """A list of forms that we can edit for this skin.
        """
        #vocab = component.getUtility(IVocabularyFactory,
        # name='Browser Skins')
        #skin_iface = vocab(None).getTermByToken(self.skin_id).value
        for name, form in component.getAdapters(
            (self,), ILayoutConfigurationForm):
            if form.skin_id == self.skin_id:
                yield form.get_form().__of__(self)

    security.declareProtected(SilvaPermissions.ChangeSilvaContent,
                              "stored_values")
    def stored_values(self):
        stored_values = {}
        for form in self.forms():
            for field_id in form.get_field_ids():
                if hasattr(self, field_id):
                    stored_values[field_id] = getattr(
                        self, field_id)
        return stored_values

    security.declareProtected(SilvaPermissions.ChangeSilvaContent,
                              "set_skin_id")
    def set_skin_id(self, skin_id):
        self.skin_id = skin_id
        
    def set_values_from_request(self, request):
        all_errors = {}
        for form in self.forms():
            try:
                result = form.validate_all(request.form)
            except FormValidationError, e:
                all_errors[form.name] = errors = {}
                for error in e.errors:
                    errors[error.field_id] = error.error_text
            else:
                self._store_data(result)
        return all_errors
        
    def _store_data(self, data):
        for datum in data:
            if not data[datum]:
                delattr(self, datum)
                continue
            setattr(self, datum, data[datum])
        
InitializeClass(LayoutConfiguration)

class FormInfo(object):
    implements(ILayoutConfigurationForm)
    
    form = None
    
    def __init__(self, context):
        path = self.get_package_path()
        self.filename = os.path.join(path, self.form_path)
        if not os.path.isfile(self.filename):
            raise ValueError("No such file", self.filename)
        
    def get_form(self):
        if self.form is not None:
            return self.form
        file = open(self.filename, 'rb')
        try:
            data = file.read()
        finally:
            file.close()
        self.form = ZMIForm('form', 'Form', unicode_mode=True)
        # update the form with the xml data
        XMLToForm(data, self.form)
        return self.form
        
    def get_package_path(self):
        return os.path.dirname(sys.modules[self.__module__].__file__)


