#-*- mode: python; mode: fold -*-
# $Id: Widgets.py 2187 2007-09-07 15:15:36Z joachim $
from cgi import escape
from types import *
import Globals
from Globals import InitializeClass
from ZPublisher.HTTPRequest import FileUpload
##from Products.CPSSchemas.Widget import CPSWidgetType
from Products.CMFCore.utils import getToolByName
from Products.CPSSchemas.BasicWidgets import CPSBooleanWidget, CPSWidget, CPSStringWidget, CPSEmailWidget,CPSImageWidget
from Products.CPSSchemas.BasicWidgets import CPSFileWidget
from Products.CPSSchemas.BasicWidgets import renderHtmlTag,CPSSelectWidget, CPSStringWidget
from Products.CPSSchemas.ExtendedWidgets import CPSDateTimeWidget
from Products.CPSSchemas.Widget import widgetRegistry
from Products.CPSUtil.file import PersistableFileUpload
from Products.CPSUtil.id import generateFileName
##from Products.CPSSchemas.WidgetTypesTool import WidgetTypeRegistry
from DateTime.DateTime import DateTime
from AccessControl import getSecurityManager
from Products.WAeUP_SRP.Students import getStudentByRegNo
from Products.WAeUP_SRP.Academics import makeCertificateCode
#from Products.ExtFile.ExtFile import ExtFile
import logging,os,re
import operator
p_home = Globals.package_home(globals())
i_home = Globals.INSTANCE_HOME

#from zLOG import LOG, DEBUG

class CPSSelectWidgetForRecord(CPSSelectWidget): ###(
    """Select widget. with record names"""
    meta_type = 'Select Widget for Records'

    field_types = ('CPS String Field',)
    field_inits = ({'is_searchabletext': 1,},)

    _properties = CPSSelectWidget._properties + (
        {'id': 'record_id', 'type': 'string', 'mode': 'w',
         'label': 'Record Id', 'is_required' : 1},
        )

    def render(self, mode, datastructure, **kw):
        """Render in mode from datastructure."""
        value = datastructure[self.getWidgetId()]
        vocabulary = self._getVocabulary(datastructure)
        portal = getToolByName(self, 'portal_url').getPortalObject()
        cpsmcat = portal.translation_service
        if mode == 'view':
            if self.translated:
                return escape(cpsmcat(vocabulary.getMsgid(value, value)).encode('ISO-8859-15', 'ignore'))
            else:
                return escape(vocabulary.get(value, value))
        elif mode == 'edit':
            html_widget_id = self.getHtmlWidgetId()
            res = renderHtmlTag('select',
                                name='%s.%s:records' % (self.record_id,html_widget_id),
                                id=html_widget_id)
            in_selection = 0
            for k, v in vocabulary.items():
                if self.translated:
                    kw = {'value': k,
                          'contents': cpsmcat(vocabulary.getMsgid(k, k)).encode('ISO-8859-15', 'ignore')
                          }
                else:
                    kw = {'value': k, 'contents': v}
                if value == k:
                    kw['selected'] = 'selected'
                    in_selection = 1
                res += renderHtmlTag('option', **kw)
            if value and not in_selection:
                kw = {'value': value, 'contents': 'invalid: '+ str(value),
                      'selected': 'selected'}
                res += renderHtmlTag('option', **kw)
            res += '</select>'
            return res
        raise RuntimeError('unknown mode %s' % mode)

InitializeClass(CPSSelectWidgetForRecord)

widgetRegistry.register(CPSSelectWidgetForRecord)

###)

class CPSStringWidgetForRecord(CPSStringWidget): ###(
    """String widget."""
    meta_type = 'String Widget For Record'

    field_types = ('CPS String Field',)
    field_inits = ({'is_searchabletext': 1,},)
    _properties = CPSStringWidget._properties + (
        {'id': 'record_id', 'type': 'string', 'mode': 'w',
         'label': 'Record Id', 'is_required' : 1},
        )

    def render(self, mode, datastructure, **kw):
        """Render in mode from datastructure."""
        value = datastructure[self.getWidgetId()]
        if mode == 'view':
            return escape(value)
        elif mode == 'edit':
            # XXX TODO should use an other name than kw !
            # XXX change this everywhere
            html_widget_id = self.getHtmlWidgetId()
            kw = {'type': 'text',
                  'id'  : html_widget_id,
                  'name': '%s.%s:records' % (self.record_id,html_widget_id),
                  'value': escape(value),
                  'size': self.display_width,
                  }
            if self.size_max:
                kw['maxlength'] = self.size_max
            return renderHtmlTag('input', **kw)
        raise RuntimeError('unknown mode %s' % mode)

InitializeClass(CPSStringWidgetForRecord)

widgetRegistry.register(CPSStringWidgetForRecord)

###)

class CertificateCourseIdWidget(CPSStringWidget): ###(
    """ CertificateCourseId Widget"""
    meta_type = "CertificateCourseId Widget"

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""

        valid = CPSStringWidget.validate(self, datastructure, **kw)
        if not valid:
            return 0
        else:
            widget_id = self.getWidgetId()
            value = datastructure[widget_id].upper()
            err = 0
            c_ids = [c.id for c in self.portal_catalog({'meta_type': "Course"})]
            if hasattr(self.aq_parent,value):
                err = 'Course already exists'
            elif value not in c_ids:
                err = 'Course does not exist'
            if err:
                datastructure.setError(widget_id, err)
            else:
                datamodel = datastructure.getDataModel()
                datamodel[self.fields[0]] = value

            return not err

InitializeClass(CertificateCourseIdWidget)

widgetRegistry.register(CertificateCourseIdWidget)
###)

class CourseIdWidget(CPSStringWidget): ###(
    """ CourseId Widget"""
    meta_type = "CourseId Widget"

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""

        valid = CPSStringWidget.validate(self, datastructure, **kw)
        if not valid:
            return 0
        else:
            widget_id = self.getWidgetId()
            value = datastructure[widget_id].upper()
            err = 0
            res = self.portal_catalog(meta_type= "Course",id = value)
            if len(res) > 0:
                err = 'Course already exists'
            if err:
                datastructure.setError(widget_id, err)
            else:
                datamodel = datastructure.getDataModel()
                datamodel[self.fields[0]] = value

            return not err

InitializeClass(CourseIdWidget)

widgetRegistry.register(CourseIdWidget)


###)

class WAeUPStudyModeWidget(CPSSelectWidget): ###(
    """WAeUP StudyMode Widget."""
    meta_type = 'WAeUP StudyMode Widget'
    vocabulary = 'entry_modes'

    def _getStudyModes(self):
        voc = getattr(self.portal_vocabularies,self.vocabulary)
        d = {}
        for k,v in voc.items():
            d[k] = v
        return d

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        widget_id = self.getWidgetId()
        value = datastructure[widget_id]
        try:
            v = str(value)
        except ValueError:
            datastructure.setError(widget_id, "'%s' not a valid session key" % value)
            return 0
        studymodes = self._getStudyModes()
        if not value:
            v = value = 'ume_ft'
        #import pdb;pdb.set_trace()
        if not studymodes.has_key(value):
            datastructure.setError(widget_id, "'%s' not a valid session key" % v)
            return 0
        if self.is_required and not len(v):
            datastructure.setError(widget_id, "session key required")
            return 0

        datamodel = datastructure.getDataModel()
        datamodel[self.fields[0]] = v
        return 1

    def render(self, mode, datastructure, **kw):
        """Render in mode from datastructure."""
        value = datastructure[self.getWidgetId()]
        studymodes = self._getStudyModes()
        if mode == 'view':
            return escape(studymodes.get(value, value))
        elif mode == 'edit':
            html_widget_id = self.getHtmlWidgetId()
            res = renderHtmlTag('select', name=html_widget_id, id=html_widget_id)
            in_selection = 0
            vocabulary_items = studymodes.items()
            if self.sorted:
                vocabulary_items.sort(key=operator.itemgetter(1))
            for k, v in vocabulary_items:
                kw = {'value': k, 'contents': v}
                if value == k:
                    kw['selected'] = 'selected'
                    in_selection = 1
                res += renderHtmlTag('option', **kw)
            if value and not in_selection:
                kw = {'value': value, 'contents': 'invalid: '+ str(value),
                      'selected': 'selected'}
                res += renderHtmlTag('option', **kw)
            res += '</select>'
            return res
        raise RuntimeError('unknown mode %s' % mode)

InitializeClass(WAeUPStudyModeWidget)

widgetRegistry.register(WAeUPStudyModeWidget)

###)

class WAeUPSessionWidget(CPSSelectWidget): ###(
    """WAeUP Session Widget."""
    meta_type = 'WAeUP Session Widget'

    def _getSessions(self):
        current_year = DateTime().year()
        d = {'-1': 'N/A'}
        for y in range(current_year - 9,current_year + 1):
            d['%s' % str(y)[-2:]] = '%4d/%4d' % (y,y+1)
        return d

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        widget_id = self.getWidgetId()
        value = datastructure[widget_id]
        try:
            v = str(value)
        except ValueError:
            datastructure.setError(widget_id, "'%s' not a valid session key" % value)
            return 0

        if len(v) == 1:
            v = value = '0%c' % v
        elif not value:
            v = value = self.getSessionId()[-2:]
        #import pdb;pdb.set_trace()
        sessions = self._getSessions()
        if not sessions.has_key(value):
            datastructure.setError(widget_id, "'%s' not a valid session key" % v)
            return 0
        if self.is_required and not len(v):
            datastructure.setError(widget_id, "session key required")
            return 0

        datamodel = datastructure.getDataModel()
        datamodel[self.fields[0]] = v
        return 1

    def render(self, mode, datastructure, **kw):
        """Render in mode from datastructure."""
        value = datastructure[self.getWidgetId()]
        sessions = self._getSessions()
        if mode == 'view':
            return escape(sessions.get(value, value))
        elif mode == 'edit':
            html_widget_id = self.getHtmlWidgetId()
            res = renderHtmlTag('select', name=html_widget_id, id=html_widget_id)
            in_selection = 0
            vocabulary_items = sessions.items()
            if self.sorted:
                vocabulary_items.sort(key=operator.itemgetter(0))
            for k, v in vocabulary_items:
                kw = {'value': k, 'contents': v}
                if value == k:
                    kw['selected'] = 'selected'
                    in_selection = 1
                res += renderHtmlTag('option', **kw)
            if value and not in_selection:
                kw = {'value': value, 'contents': 'invalid: '+ str(value),
                      'selected': 'selected'}
                res += renderHtmlTag('option', **kw)
            res += '</select>'
            return res
        raise RuntimeError('unknown mode %s' % mode)

InitializeClass(WAeUPSessionWidget)

widgetRegistry.register(WAeUPSessionWidget)

###)

class WAeUPLevelWidget(CPSSelectWidget): ###(
    """WAeUP Level Widget."""
    meta_type = 'WAeUP Level Widget'

    def _getLevels(self):
        d = {'000':'N/A'}
        for y in range(100,800,100):
            d['%s' % str(y)] = 'Year %1d (%3d Level)' % (y/100,y)
        return d

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        widget_id = self.getWidgetId()
        value = datastructure[widget_id]
        try:
            v = str(value)
        except ValueError:
            datastructure.setError(widget_id, "'%s' not a valid level key" % value)
            return 0

        if not value:
            v = value = '100'
        #import pdb;pdb.set_trace()
        levels = self._getLevels()
        if not levels.has_key(value):
            datastructure.setError(widget_id, "'%s' not a valid level" % v)
            return 0
        if self.is_required and not len(v):
            datastructure.setError(widget_id, "level key required")
            return 0

        datamodel = datastructure.getDataModel()
        datamodel[self.fields[0]] = v
        return 1

    def render(self, mode, datastructure, **kw):
        """Render in mode from datastructure."""
        value = datastructure[self.getWidgetId()]
        levels = self._getLevels()
        if mode == 'view':
            return escape(levels.get(value, value))
        elif mode == 'edit':
            html_widget_id = self.getHtmlWidgetId()
            res = renderHtmlTag('select', name=html_widget_id, id=html_widget_id)
            in_selection = 0
            vocabulary_items = levels.items()
            if self.sorted:
                vocabulary_items.sort(key=operator.itemgetter(0))
            for k, v in vocabulary_items:
                kw = {'value': k, 'contents': v}
                if value == k:
                    kw['selected'] = 'selected'
                    in_selection = 1
                res += renderHtmlTag('option', **kw)
            if value and not in_selection:
                kw = {'value': value, 'contents': 'invalid: '+ str(value),
                      'selected': 'selected'}
                res += renderHtmlTag('option', **kw)
            res += '</select>'
            return res
        raise RuntimeError('unknown mode %s' % mode)

InitializeClass(WAeUPLevelWidget)

widgetRegistry.register(WAeUPLevelWidget)

###)

class WAeUPVerdictWidget(CPSSelectWidget): ###(
    """WAeUP Verdict Widget."""
    meta_type = 'WAeUP Verdict Widget'

    # XXX make a menu for the vocabulary.
    vocabulary = 'verdicts'

    # Associating the widget label with an input area to improve the widget
    # accessibility.
    has_input_area = True

    def _getVerdicts(self,datastructure):
        voc = getattr(self.portal_vocabularies,self.vocabulary)
        d = {}
        for k,v in voc.items():
            d[k] = v
        return d

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        widget_id = self.getWidgetId()
        value = datastructure[widget_id]
        try:
            v = str(value)
        except ValueError:
            datastructure.setError(widget_id, "'%s' not a valid verdict key" % value)
            return 0
        #import pdb;pdb.set_trace()
        verdicts = self._getVerdicts(datastructure)
        if not value:
            v = value = verdicts['N/A']
        if not verdicts.has_key(value):
            datastructure.setError(widget_id, "'%s' not a valid verdict key" % v)
            return 0
        if self.is_required and not len(v):
            datastructure.setError(widget_id, "verdict required")
            return 0

        datamodel = datastructure.getDataModel()
        datamodel[self.fields[0]] = v
        return 1

    def render(self, mode, datastructure, **kw):
        """Render in mode from datastructure."""
        value = datastructure[self.getWidgetId()]
        verdicts = self._getVerdicts(datastructure)
        if mode == 'view':
            return escape(verdicts.get(value, value))
        elif mode == 'edit':
            html_widget_id = self.getHtmlWidgetId()
            res = renderHtmlTag('select', name=html_widget_id, id=html_widget_id)
            in_selection = 0
            vocabulary_items = verdicts.items()
            if self.sorted:
                vocabulary_items.sort(key=operator.itemgetter(1))
            for k, v in vocabulary_items:
                kw = {'value': k, 'contents': v}
                if value == k:
                    kw['selected'] = 'selected'
                    in_selection = 1
                res += renderHtmlTag('option', **kw)
            if value and not in_selection:
                kw = {'value': value, 'contents': 'invalid: '+ str(value),
                      'selected': 'selected'}
                res += renderHtmlTag('option', **kw)
            res += '</select>'
            return res
        raise RuntimeError('unknown mode %s' % mode)

InitializeClass(WAeUPVerdictWidget)

widgetRegistry.register(WAeUPVerdictWidget)

###)

class WAeUPLGAWidget(CPSSelectWidget): ###(
    """WAeUP LGA Widget."""
    meta_type = 'WAeUP LGA Widget'
    _properties = CPSSelectWidget._properties + (
        {'id': 'state_field', 'type': 'string', 'mode': 'w',
         'label': 'Name of the state field'},
         {'id': 'lga_field', 'type': 'string', 'mode': 'w',
         'label': 'Name of the LGA Field (without state)'},
         )
    state_field = "state"
    lga_field = "lga"

    # XXX make a menu for the vocabulary.
    vocabulary = 'local_gov_areas'

    # Associating the widget label with an input area to improve the widget
    # accessibility.
    has_input_area = True

    def _getLGAs(self):
        voc = getattr(self.portal_vocabularies,self.vocabulary)
        states = []
        lgas  = []
        d = {}
        for k,v in voc.items():
            parts = v.split(' / ')
            if len(parts) == 1:
                state = parts[0].lower()
                lga = ""
            elif len(parts) == 2:
                state = parts[0].lower()
                lga = "_".join(re.split('\W+',parts[1].lower()))
            else:
                continue
            if state not in states:
                states.append(state)
            if lga not in lgas:
                lgas.append(lga)
            d[k] = v

        return (d,states,lgas)

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        widget_id = self.getWidgetId()
        value = datastructure[widget_id]
        #import pdb;pdb.set_trace()
        try:
            v = str(value)
        except ValueError:
            datastructure.setError(widget_id, "'%s' not a valid lga key" % value)
            return 0
        v = v.lower()
        combined,states,lgas = self._getLGAs()
        one_field = False
        if len(v) == 0:
            pass
        elif not self.state_field and not self.lga_field:
            one_field = True
            if v not in combined.keys():
                datastructure.setError(widget_id, "'%s' not a valid lga key" % v)
                return 0
        else:
            if widget_id == self.state_field:
                if v not in states:
                    datastructure.setError(widget_id, "'%s' not a valid state" % v)
                    return 0
            elif widget_id == self.lga_field:
                if "_".join(re.split('\W+',v)) not in lgas:
                    datastructure.setError(widget_id, "'%s' not a valid lga" % v)
                    return 0
                if datastructure[self.state_field]:
                    v = datastructure[self.state_field] + '_' + v

        if self.is_required and not len(v):
            datastructure.setError(widget_id, "lga required")
            return 0

        datamodel = datastructure.getDataModel()
        if one_field:
            datamodel[self.fields[0]] = v
        else:
            state = datastructure[self.state_field].lower()
            lga = "_".join(datastructure[self.lga_field].lower().split())
            datamodel[self.fields[0]] =   state + "_" + lga
        return 1

    def render(self, mode, datastructure, **kw):
        """Render in mode from datastructure."""
        w_id = self
        value = datastructure[self.getWidgetId()]
        lgas,x,y = self._getLGAs(datastructure)
        if mode == 'view':
            return escape(lgas.get(value, value))
        elif mode == 'edit':
            html_widget_id = self.getHtmlWidgetId()
            res = renderHtmlTag('select', name=html_widget_id, id=html_widget_id)
            in_selection = 0
            vocabulary_items = lgas.items()
            # if self.sorted:
            #     vocabulary_items.sort(key=operator.itemgetter(1))
            for k, v in vocabulary_items:
                kw = {'value': k, 'contents': v}
                if value == k:
                    kw['selected'] = 'selected'
                    in_selection = 1
                res += renderHtmlTag('option', **kw)
            if value and not in_selection:
                kw = {'value': value, 'contents': 'invalid: '+ str(value),
                      'selected': 'selected'}
                res += renderHtmlTag('option', **kw)
            res += '</select>'
            return res
        raise RuntimeError('unknown mode %s' % mode)

InitializeClass(WAeUPLGAWidget)

widgetRegistry.register(WAeUPLGAWidget)

###)

class WAeUPReservedRoomsWidget(CPSStringWidget): ###(
    """ WAeUPReservedRooms Widget"""
    meta_type = "WAeUPReservedRooms Widget"

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        import re
        valid = CPSStringWidget.validate(self, datastructure, **kw)
        if not valid:
            return 0
        else:
            widget_id = self.getWidgetId()
            value = datastructure[widget_id]
            err = 0
            try:
                reserved = [(r.split('/')[0],int(r.split('/')[1])) for r in re.split(',|\.| ',value)
                                     if r]
            except (ValueError,IndexError),msg:
                err = str(msg)
            if err:
                datastructure.setError(widget_id, err)
            else:
                datamodel = datastructure.getDataModel()
                datamodel[self.fields[0]] = value
            return not err

InitializeClass(WAeUPReservedRoomsWidget)

widgetRegistry.register(WAeUPReservedRoomsWidget)
###)

class WAeUPIdWidget(CPSStringWidget): ###(
    """ WAeUPId Widget"""
    meta_type = "WAeUPId Widget"

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""

        valid = CPSStringWidget.validate(self, datastructure, **kw)
        id_pat_str = r"\S"
        inv_id_pat = re.compile(r"^%s$" % id_pat_str)
        if not valid:
            return 0
        else:
            portal_type_query = {'query':['Faculty',
                                          'Department',
                                          'Course',
                                          'Certificate',
                                          'CertificateCourse',]}
            widget_id = self.getWidgetId()
            value = datastructure[widget_id]  #.upper()  is not necessary here because it's also done in waeup_document_create_do
            err = 0
            mapping = {}
            if len(value.split()) > 1:
                err = 'Invalid Id, Id contains space(s).'
            elif self.portal_catalog(portal_type=portal_type_query,id=value):
                brain = self.portal_catalog(portal_type=portal_type_query,id=value)[0]
                err = 'An ${portal_type} object with the Id ${id} already exists at ${path}.'
                mapping = {'portal_type': brain.portal_type,
                           'id': value,
                           'path': brain.getPath(),
                           }
            if err:
                datastructure.setError(widget_id, err, mapping)
            else:
                datamodel = datastructure.getDataModel()
                datamodel[self.fields[0]] = value

            return not err

InitializeClass(WAeUPIdWidget)

widgetRegistry.register(WAeUPIdWidget)


###)

class StudyCourseWidget(CPSStringWidget): ###(
    """ StudyCourse Widget"""
    meta_type = "StudyCourse Widget"

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        #from Products.zdb import set_trace
        #set_trace()
##        valid = CPSStringWidget.validate(self, datastructure, **kw)
##        if not valid:
##            return 0
        widget_id = self.getWidgetId()
        value = makeCertificateCode(datastructure[widget_id]).upper()
        id_pat_str = r"\S"
        inv_id_pat = re.compile(r"^%s$" % id_pat_str)
        err = 0
        if len(value.split()) > 1:
            err = 'Invalid Id, Id contains space(s).'
        elif not self.portal_catalog(portal_type='Certificate',id=value):
            err = 'No such certificate'
        if err:
            datastructure.setError(widget_id, err)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = value
        return not err

InitializeClass(StudyCourseWidget)

widgetRegistry.register(StudyCourseWidget)
###)

class JambRegNoWidget(CPSStringWidget): ###(
    """ JambRegNo Widget"""
    meta_type = "JambRegNo Widget"
    _properties = CPSStringWidget._properties + (
        {'id': 'catalog', 'type': 'string', 'mode': 'w',
         'label': 'Catalog to search'},
         {'id': 'reference', 'type': 'string', 'mode': 'w',
         'label': 'Reference Field'},
         )
    #catalog = "portal_pumeresults" #the catalog to search for jamb_reg_no
    reference = ""
    digits = 8
    digits_str = "N"*digits
    letters = 2
    letters_str = "L"*letters
    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        valid = CPSStringWidget.validate(self, datastructure, **kw)
        reg_no_catalog = getattr(self,self.catalog)
        widget_id = self.getWidgetId()
        value = datastructure[widget_id].upper()
        err = 0
        #import pdb;pdb.set_trace()
        if kw.has_key('mode'):
            mode = kw['mode']
        else:
            mode = "edit"
        if not valid:
            err = 'Invalid registration number'
        elif self.reference == '':
            #s = getStudentByRegNo(self,value)
            pume = reg_no_catalog(jamb_reg_no = value)
            if len(pume) < 1:
                err = 'No student record with this registration number'
            else:
                datastructure['pume'] = pume[0]
        elif mode == 'add':
            pass
        elif self.reference != '' and self.catalog == "applicants_catalog":
            res = reg_no_catalog.searchResults({"%s" % self.reference: value})
            if len(res) != 1:
                err = 'No record with this registration number'
            else:
                datastructure['record'] = res[0]
        else:
            record = datastructure[self.reference]
            #jamb_reg_no = getattr(record,widget_id)
            jamb_reg_no = record.Entryregno
            if jamb_reg_no != value:
                err = 'Registration number does not match.'
        if err:
            datastructure.setError(widget_id, err)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = value
        return not err

InitializeClass(JambRegNoWidget)

widgetRegistry.register(JambRegNoWidget)
###)

class SecretWidget(CPSStringWidget): ###(
    """ Secret Widget"""
    meta_type = "Secret Widget"
    _properties = CPSStringWidget._properties + (
        {'id': 'reference', 'type': 'string', 'mode': 'w',
         'label': 'Reference Record'},
         {'id': 'check_fields', 'type': 'tokens', 'mode': 'w',
         'label': 'Fields to check'},
         )
    reference = "student"
    matric_no_catalog = 'returning_import'
    check_fields = ("Firstname", "Middlename","Lastname")
    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        logger = logging.getLogger('Widgets.SecretWidget.validate')
        valid = CPSStringWidget.validate(self, datastructure, **kw)
        widget_id = self.getWidgetId()
        value = datastructure[widget_id].upper()
        err = 0
        record = datastructure.get(self.reference,None)
        #import pdb;pdb.set_trace()
        if not valid or len(value) < 2:
            err = 'Invalid string'
        elif not record or datastructure.errors:
            err = 0
        else:
            found = False
            cvs = []
            for field in self.check_fields:
                cv = getattr(record,field).upper()
                if len(cv.split()) > 1:
                    for splited in cv.split():
                        cvs.append(splited.strip())
                else:
                    cvs.append(cv)
            for cv in cvs:
                if cv  == value.upper():
                    found = True
                    break
            matric_no = record.matric_no
            name = " ".join(cvs)
            if not found:
                logger.info('%(matric_no)s did not find %(value)s in %(name)s' % vars())
                err = 'No name does match.'
            else:
                logger.info('%(matric_no)s found %(value)s in %(name)s' % vars())
        if err:
            datastructure.setError(widget_id, err)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = value
        return not err

InitializeClass(SecretWidget)

widgetRegistry.register(SecretWidget)
###)

class WAeUPSexWidget(CPSBooleanWidget): ###(
    """WAeUP sex widget."""
    meta_type = 'WAeUP Sex Widget'

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        value = datastructure[self.getWidgetId()]

        if self.render_format not in self.render_formats:
            self.render_format = 'select'

        female = value in ('F','f','Female','female',"True",True)
        male = value in ('M','m','Male','male','False',False)
        if not female and not male:
            datastructure.setError(self.getWidgetId(),
                                   "invalid sex %s" % value)
            return 0
        elif female:
            v = True
        else:
            v = False
        datamodel = datastructure.getDataModel()
        datamodel[self.fields[0]] = v
        return 1

InitializeClass(WAeUPSexWidget)

widgetRegistry.register(WAeUPSexWidget)

###)

class MatricNoWidget(CPSStringWidget): ###(
    """ MatricNo Widget"""
    meta_type = "MatricNo Widget"

    _properties = CPSStringWidget._properties + (
        {'id': 'matric_no_catalog', 'type': 'string', 'mode': 'w',
         'label': 'Catalog to search for MatricNo'},
        { 'id': 'results_catalog', 'type': 'string', 'mode': 'w',
         'label': 'Results Catalog'},
         )
    matric_no_catalog = "" #the catalog to search for matric_no
    results_catalog = "results_import" #results catalog

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        #import pdb;pdb.set_trace()
        valid = CPSStringWidget.validate(self, datastructure, **kw)
        logger = logging.getLogger('Widgets.MatricNoWidget.validate')
        returning = getattr(self,self.matric_no_catalog)
        results = getattr(self,self.results_catalog,None)
        err = 0
        widget_id = self.getWidgetId()
        value = datastructure[widget_id]
        if not valid or not value:
            err = 'Invalid string'
            logger.info('Invalid matric_no string %s' % value)
        else:
            value = value.upper()
            datastructure['student'] = None
            while not err:
                res = returning(matric_no = value)
                if len(res) < 1:
                    logger.info('matric_no %s not found' % value)
                    err = 'No student with this matriculation number.'
                    break
                datastructure['student'] = res[0]
                if results is not None:
                    res = results(matric_no = value)
                    if len(res) < 1:
                        err = 'No results for this matriculation number'
                        continue
                    datastructure['results'] = res
                break
        if err:
            datastructure.setError(widget_id, err)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = value
        return not err

InitializeClass(MatricNoWidget)

widgetRegistry.register(MatricNoWidget)
###)

class StudentIdWidget(CPSStringWidget): ###(
    """ StudentId Widget"""
    meta_type = "StudentId Widget"
    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        valid = CPSStringWidget.validate(self, datastructure, **kw)
        logger = logging.getLogger('Widgets.StudentIdWidget.validate')
        #import pdb;pdb.set_trace()
        s_cat = self.students_catalog
        err = 0
        widget_id = self.getWidgetId()
        value = datastructure[widget_id]
        if not valid or not value:
            err = 'Invalid Id string'
            logger.info('Invalid id string %s' % value)
            datastructure['student'] = None
        else:
            value = value.upper()
            res = s_cat(id = value)
            if not res:
                logger.info('Student id %s not found' % value)
                err = 'No student with this Id'
                datastructure['student'] = None
            else:
                datastructure['student'] = res[0]
        if err:
            datastructure.setError(widget_id, err)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = value
        return not err

InitializeClass(StudentIdWidget)

widgetRegistry.register(StudentIdWidget)
###)

class WAeUPMultilineResultsWidget(CPSStringWidget): ###(
    """ WAeUPMultilineResults Widget"""
    meta_type = "WAeUp Multiline Results Widget"
    _properties = CPSWidget._properties + (
        {'id': 'nr_of_lines', 'type': 'int', 'mode': 'w',
         'label': 'Nr of Lines'},
         )
    nr_of_lines = 5
    def prepare(self, datastructure, **kw): ###(
        """Prepare datastructure from datamodel."""
        datamodel = datastructure.getDataModel()
        #import pdb;pdb.set_trace()
        widget_id = self.getWidgetId()
        v = datamodel[self.fields[0]]
        if type(v) is ListType and v:
            nr_results = len(v)
        else:
            v = []
            nr_results = 0
        count = 1
        for s,g in v:
            wid = "%s%02d"% (widget_id,count)
            datastructure[wid+'_s'] = s
            datastructure[wid+'_g'] = g
            count += 1
        if nr_results < self.nr_of_lines:
            for line in range(nr_results,self.nr_of_lines):
                v.append(('',''))
                wid = "%s%02d"% (widget_id,line)
                datastructure[wid+'_s'] = ''
                datastructure[wid+'_g'] = ''
        datastructure[widget_id] = v
        datastructure[widget_id+'_s'] = ''
        datastructure[widget_id+'_g'] = ''
    ###)

    def validate(self, datastructure, **kw): ###(
        """Validate datastructure and update datamodel."""
        #import pdb;pdb.set_trace()
        widget_id = self.getWidgetId()
        err = 0
        lines = []
        for line in range(1,30):
            wid = "%s%02d"% (widget_id,line)
            if not datastructure.has_key(wid+'_s'):
                break
            lines.append((datastructure[wid+'_s'].strip(),
                         datastructure[wid+'_g'].strip()))

        s = datastructure[widget_id+'_s'].strip()
        g = datastructure[widget_id+'_g'].strip()
        if s and g:
            lines.append((s,g))
        active = []
        for s,g in lines:
            if g != "":
                active.append((s,g))
        if err:
            datastructure.setError(widget_id, err)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = active
        return not err
    ###)

    def render(self, mode, datastructure, **kw): ###(
        """Render in mode from datastructure."""
        render_method = 'widget_waeup_multiline_result_render'
        meth = getattr(self, render_method, None)
        if meth is None:
            raise RuntimeError("Unknown Render Method %s for widget type %s"
                               % (render_method, self.getId()))
        #import pdb;pdb.set_trace()
        datamodel = datastructure.getDataModel()
        widget_id = self.getWidgetId()
        lines = datamodel[self.fields[0]]
        if len(lines) < self.nr_of_lines:
            for line in range(len(lines),self.nr_of_lines + 1):
                lines.append(('',''))
        datastructure[widget_id] = lines
        datastructure[widget_id+'_s'] = ''
        datastructure[widget_id+'_g'] = ''
##        count = 1
##        for s,g in v:
##            wid = "%s%02d"% (widget_id,count)
##            count += 1
        return meth(mode=mode,
                    datastructure=datastructure,
                    )
    ###)


InitializeClass(WAeUPMultilineResultsWidget)
widgetRegistry.register(WAeUPMultilineResultsWidget)
###)

class WAeUPResultsWidget(CPSStringWidget): ###(
    """ WAeUPResults Widget"""
    meta_type = "WAeUp Results Widget"

    def prepare(self, datastructure, **kw): ###(
        """Prepare datastructure from datamodel."""
        datamodel = datastructure.getDataModel()
        v = datamodel[self.fields[0]]
        #import pdb;pdb.set_trace()
        widget_id = self.getWidgetId()
        datastructure[widget_id] = v
        datastructure[widget_id+'_s'] = ''
        datastructure[widget_id+'_g'] = ''
    ###)

    def validate(self, datastructure, **kw): ###(
        """Validate datastructure and update datamodel."""
        #import pdb;pdb.set_trace()
        widget_id = self.getWidgetId()
        v = datastructure[widget_id]
        err = 0
        s = datastructure[widget_id+'_s'].strip()
        g = datastructure[widget_id+'_g'].strip()
        while 1:
            if not s and g:
                err = "No subject grade for subject"
                break
            i = 0
            done = False
            for sv,gv in v:
                if sv == s:
                    done = True
                    if not g:
                        v.pop(i)
                        break
                    v[i] = (s,g)
                    break
                i += 1
            if done:
                break
            if s and g:
                v.append((s,g))
            break
        if err:
            datastructure.setError(widget_id, err)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = v
            datastructure[widget_id+'_s'] = s
            datastructure[widget_id+'_g'] = g
        return not err
    ###)

    def render(self, mode, datastructure, **kw): ###(
        """Render in mode from datastructure."""
        render_method = 'widget_waeup_result_render'
        meth = getattr(self, render_method, None)
        if meth is None:
            raise RuntimeError("Unknown Render Method %s for widget type %s"
                               % (render_method, self.getId()))
        #import pdb;pdb.set_trace()
        datamodel = datastructure.getDataModel()
        widget_id = self.getWidgetId()
        datastructure[widget_id+'_s'] = ''
        datastructure[widget_id+'_g'] = ''
        return meth(mode=mode,
                    datastructure=datastructure,
                    )
    ###)


InitializeClass(WAeUPResultsWidget)
widgetRegistry.register(WAeUPResultsWidget)
###)

class ScratchCardPin: ###(
    """the ScratchCardPin"""
    def __init__(self,prefix,batch_no,number):
        if not batch_no and not number:
            s = prefix
            if len(s) > 3:
                prefix,batch_no,number = s[:3],s[3:-10],s[-10:]
            else:
                prefix,batch_no,number = s,'',''
        self.p = prefix
        self.b = batch_no
        self.n = number

    def __str__(self):
        return "%s-%s-%s" % (self.p,self.b,self.n)

    def __repr__(self):
        return "%s%s%s" % (self.p,self.b,self.n)
###)

class ScratchcardPinWidget(CPSStringWidget): ###(
    """ ScratchcardPin Widget"""
    meta_type = "Scratchcard Pin Widget"
    _properties = CPSWidget._properties + (
        {'id': 'prefix', 'type': 'string', 'mode': 'w',
         'label': 'Prefix'},
         {'id': 'reference', 'type': 'string', 'mode': 'w',
         'label': 'Reference Field'},
        )
    prefix = ''
    reference = ''
    def prepare(self, datastructure, **kw): ###(
        """Prepare datastructure from datamodel."""
        datamodel = datastructure.getDataModel()
        v = datamodel[self.fields[0]]
        widget_id = self.getWidgetId()
        if v and type(v) is StringType:
            try:
                p,b,n = v.split('-')
                v = ScratchCardPin(p,b,n)
            except ValueError:
                v = ScratchCardPin(v,'','')
        if v:
            p = '%s' % v.p
            b = '%s' % v.b
            n = '%s' % v.n
        else:
            p = self.prefix
            if p.startswith('@'):
                p = getattr(self,self.prefix[1:])()
            b = n = ''
            v = ScratchCardPin(p,b,n)
        datastructure[widget_id] = v
        datastructure[widget_id+'_p'] = p
        datastructure[widget_id+'_b'] = b
        datastructure[widget_id+'_n'] = n
    ###)

    def validate(self, datastructure, **kw): ###(
        """Validate datastructure and update datamodel."""
        s_logger = logging.getLogger('Widgets.ScratchcardPinWidget.validate')
        widget_id = self.getWidgetId()
        v = datastructure[widget_id]
        #import pdb;pdb.set_trace()
        err = 0
        mapping = {}
        prefix= self.prefix
        if prefix.startswith('@'):
            prefix= getattr(self,self.prefix[1:])()
        b = datastructure[widget_id+'_b'].strip()
        n = datastructure[widget_id+'_n'].strip()
        pins = self.portal_pins
        pin = "%(prefix)s%(b)s%(n)s" % vars()
        pin_str = "%(prefix)s-%(b)s-%(n)s" % vars()
        do = 1
        s_id = str(self.portal_membership.getAuthenticatedMember())
        if self.isStaff():
            do = 0
            err ='You are not a Student. PIN neither checked nor used.'
            s_logger.info('%s tried to use scratch card %s' % (s_id,pin_str))
        elif len(b) > 1 and b.find('-') > -1:
            do = 0
            err = 'PIN must not contain "-"'
            s_logger.info('%s entered invalid PIN  containing "-"' % (s_id))
        elif n.find('-') > -1:
            do = 0
            err = 'PIN must not contain "-"'
            s_logger.info('%s entered invalid PIN  containing "-"' % (s_id))
        elif len(n) != 10:
            do = 0
            err = 'Invalid PIN length'
            s_logger.info('%s entered invalid PIN with length %d' % (s_id,len(n)))
        elif self.reference == "":
            ref = s_id
        else:
            ref = datastructure[self.reference]
            if datastructure.errors:
                do = 0
                datastructure.setError(widget_id, 'PIN neither checked nor used.')
                s_logger.info('%s/%s entered wrong data together with PIN %s' % (s_id,ref,pin_str))
        while do:
            ok = pins.searchAndSetRecord(pin,ref,prefix)
            if ok < -2 or ok > 2:
                err = 'Unknown error, please report!'
                s_logger.info('%s/%s caused unknown error with PIN %s' % (s_id,ref,pin_str))
                break
            elif ok == -2:
                err = 'Service already is activated but with a different PIN.'
                s_logger.info('%s/%s repeatedly activated service but with different PIN %s' % (s_id,ref,pin_str))
                break
            elif ok == -1:
                err = 'Invalid PIN'
                s_logger.info('%s/%s entered invalid PIN %s' % (s_id,ref,pin_str))
                break
            if ok == 0:
                err = 'PIN already used'
                s_logger.info('%s/%s entered used PIN %s' % (s_id,ref,pin_str))
                break
            if ok >= 1:
                #import pdb;pdb.set_trace()
                if self.isStudent():
                    if self.reference == "jamb_reg_no":
                        err = "You are already logged in."
                        s_logger.info('%s/%s checked admission with PIN %s though logged in' % (s_id,ref,pin_str))
                        break
                    if ok == 1:
                        s_logger.info('%s/%s successfully used PIN %s' % (s_id,ref,pin_str))
                    else:
                        s_logger.info('%s/%s repeatedly used PIN %s' % (s_id,ref,pin_str))
                    break
                else:
                    student = getStudentByRegNo(self,ref)
                    s_logger.info('%s/%s successfully used PIN %s' % (s_id,ref,pin_str))
                if student is None:
                    err = "Student not found"
                    s_logger.info('%s not found in admission list' % (ref))
                    break
                s_id = student.getId()
                if ok == 2:
                    if self.reference == "jamb_reg_no":
                        if hasattr(self.portal_directories.students,s_id):
                            err = "Please login with your Student Id ${id} and 10-digit PIN."
                            mapping = {'id': s_id}
                            s_logger.info('%s/%s repeatedly checked admission with PIN %s' % (s_id,ref,pin_str))
                            break
                        else:
                            s_logger.info('%s/%s (non-member) repeatedly checked admission with PIN %s' % (s_id,ref,pin_str))
                    else:
                        err = "Unknown error"
                        s_logger.info('%s/%s repeatedly activated service with PIN %s' % (s_id,ref,pin_str))
                        break
                try:
                    student.getContent().makeStudentMember(s_id,password=pin[4:])
                    s_logger.info('%s/%s has been created using PIN %s' % (s_id,ref,pin_str))
                except:
                    err = "Please login with your Student Id ${id} and 10-digit PIN."
                    mapping = {'id': s_id}
                    s_logger.info('%s/%s could not be made a member with PIN %s' % (s_id,ref,pin_str))
                    break
            break
        if err:
            datastructure.setError(widget_id, err,mapping)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = ScratchCardPin(prefix,b,n)
            datastructure[widget_id] = ScratchCardPin(prefix,b,n)
            datastructure[widget_id+'_p'] = prefix
            datastructure[widget_id+'_b'] = b
            datastructure[widget_id+'_n'] = n
            datastructure['s_id'] = s_id
        return not err

###)

    def render(self, mode, datastructure, **kw): ###(
        """Render in mode from datastructure."""
        render_method = 'widget_scratch_card_pin_render'
        meth = getattr(self, render_method, None)
        if meth is None:
            raise RuntimeError("Unknown Render Method %s for widget type %s"
                               % (render_method, self.getId()))

        # XXX AT: datastructure has to be set again here, in case we're in edit
        # or create mode, because a default value has to be provided.
        #import pdb;pdb.set_trace()
        datamodel = datastructure.getDataModel()
        v = datamodel[self.fields[0]]
        if v and type(v) is StringType:
            try:
                p,b,n = v.split('-')
                v = ScratchCardPin(p,b,n)
            except ValueError:
                v = ScratchCardPin(self.prefix,'XXX',v)
                pass
        if v:
            prefix= '%s' % v.p
            b = '%s' % v.b
            n = '%s' % v.n
        else:
            prefix= self.prefix
            if prefix.startswith('@'):
                prefix= getattr(self,self.prefix[1:])()
            b = n = ''
            v = ScratchCardPin(prefix,b,n)
        widget_id = self.getWidgetId()
        datastructure[widget_id] = v
        datastructure[widget_id+'_p'] = prefix
        datastructure[widget_id+'_b'] = b
        datastructure[widget_id+'_n'] = n
        return meth(mode=mode,
                    datastructure=datastructure,
                    )
    ###)

InitializeClass(ScratchcardPinWidget)
widgetRegistry.register(ScratchcardPinWidget)
###)

class PumePinWidget(ScratchcardPinWidget): ###(
    """ Pume Pin Widget"""
    meta_type = "Pume Pin Widget"
    catalog = "applicants_catalog"

    def validate(self, datastructure, **kw): ###(
        """Validate datastructure and update datamodel."""
        s_logger = logging.getLogger('Widgets.ScratchcardPinWidget.validate')
        widget_id = self.getWidgetId()
        v = datastructure[widget_id]
        err = 0
        mapping = {}

        prefix= self.prefix
        if prefix.startswith('@'):
            prefix= getattr(self,self.prefix[1:])()
        b = datastructure[widget_id+'_b'].strip()
        n = datastructure[widget_id+'_n'].strip()
        pins = self.portal_pins
        pin = "%(prefix)s%(b)s%(n)s" % vars()
        pin_str = "%(prefix)s-%(b)s-%(n)s" % vars()
        do = 1
        s_id = str(self.portal_membership.getAuthenticatedMember())
        if self.isStaff():
            do = 0
            err ='You are not a Student. PIN neither checked nor used.'
            s_logger.info('%s tried to use scratch card %s' % (s_id,pin_str))
        elif len(b) > 1 and b.find('-') > -1:
            do = 0
            err = 'PIN must not contain "-"'
            s_logger.info('%s entered invalid PIN  containing "-"' % (s_id))
        elif n.find('-') > -1:
            do = 0
            err = 'PIN must not contain "-"'
            s_logger.info('%s entered invalid PIN  containing "-"' % (s_id))
        elif len(n) != 10:
            do = 0
            err = 'Invalid PIN length'
            s_logger.info('%s entered invalid PIN with length %d' % (s_id,len(n)))
        elif self.reference == "":
            ref = s_id
        else:
            ref = datastructure[self.reference]
            if datastructure.errors:
                do = 0
                datastructure.setError(widget_id, 'PIN neither checked nor used.')
                s_logger.info('%s/%s entered wrong data together with PIN %s' % (s_id,ref,pin_str))
        while do:
            ok = pins.searchAndSetRecord(pin,ref,prefix)
            if ok < -2 or ok > 2:
                err = 'Unknown error, please report!'
                s_logger.info('%s/%s caused unknown error with PIN %s' % (s_id,ref,pin_str))
                break
            elif ok == -2:
                err = 'Service already is activated but with a different PIN.'
                s_logger.info('%s/%s repeatedly activated service but with different PIN %s' % (s_id,ref,pin_str))
                break
            elif ok == -1:
                err = 'Invalid PIN'
                s_logger.info('%s/%s entered invalid PIN %s' % (s_id,ref,pin_str))
                break
            if ok == 0:
                err = 'PIN already used'
                s_logger.info('%s/%s entered used PIN %s' % (s_id,ref,pin_str))
                break
            if ok >= 1:
                if self.isStudent():
                    err = "This is only for Pume application."
                    s_logger.info('%s/%s applied for screening test with PIN %s' % (s_id,ref,pin_str))
                    break
                else:
                    applicant = datastructure['record']
                    if not applicant.pin:
                        s_logger.info('%s successfully used PIN %s' % (ref,pin_str))
                        d = {}
                        d['reg_no'] = applicant.reg_no
                        d['pin'] = pin_str
                        d['status'] = 'entered'
                        getattr(self,self.catalog).modifyRecord(**d)
                    elif applicant.pin != pin_str:
                        s_logger.info('%s/%s tried to enter application record with different PIN %s' % (s_id,ref,pin_str))
                    elif applicant.pin == pin_str:
                        s_logger.info('%s/%s repeatedly entered application record with PIN %s' % (s_id,ref,pin_str))
            break
        if err:
            datastructure.setError(widget_id, err,mapping)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = ScratchCardPin(prefix,b,n)
            datastructure[widget_id] = ScratchCardPin(prefix,b,n)
            datastructure[widget_id+'_p'] = prefix
            datastructure[widget_id+'_b'] = b
            datastructure[widget_id+'_n'] = n
            datastructure['s_id'] = s_id
        return not err
    ###)

    def render(self, mode, datastructure, **kw): ###(
        """Render in mode from datastructure."""
        render_method = 'widget_scratch_card_pin_render'
        meth = getattr(self, render_method, None)
        if meth is None:
            raise RuntimeError("Unknown Render Method %s for widget type %s"
                               % (render_method, self.getId()))

        # XXX AT: datastructure has to be set again here, in case we're in edit
        # or create mode, because a default value has to be provided.
        #import pdb;pdb.set_trace()
        datamodel = datastructure.getDataModel()
        v = datamodel[self.fields[0]]
        #import pdb;pdb.set_trace()
        if v and type(v) is StringType:
            try:
                p,b,n = v.split('-')
                v = ScratchCardPin(p,b,n)
            except ValueError:
                v = ScratchCardPin(self.prefix,'XXX',v)
                pass
        if v:
            prefix= '%s' % v.p
            b = '%s' % v.b
            n = '%s' % v.n
        else:
            prefix= self.prefix
            if prefix.startswith('@'):
                prefix= getattr(self,self.prefix[1:])()
            b = n = ''
            v = ScratchCardPin(prefix,b,n)
        widget_id = self.getWidgetId()
        datastructure[widget_id] = v
        datastructure[widget_id+'_p'] = prefix
        datastructure[widget_id+'_b'] = b
        datastructure[widget_id+'_n'] = n
        return meth(mode=mode,
                    datastructure=datastructure,
                    )
    ###)

InitializeClass(PumePinWidget)
widgetRegistry.register(PumePinWidget)
###)

class WAeUPImageWidget(CPSImageWidget): ###(
    """Photo widget."""
    meta_type = 'WAeUP Image Widget'

    def render(self, mode, datastructure, **kw):
        render_method = 'widget_waeup_image_render'
        meth = getattr(self, render_method, None)
        if meth is None:
            raise RuntimeError("Unknown Render Method %s for widget type %s"
                               % (render_method, self.getId()))
        img_info = self.getImageInfo(datastructure)
        return meth(mode=mode, datastructure=datastructure, **img_info)

InitializeClass(WAeUPImageWidget)

widgetRegistry.register(WAeUPImageWidget)
###)

class NoZodbImageWidget(CPSImageWidget): ###(
    """Image widget with filesystem storage."""
    meta_type = 'No Zodb Image Widget'
    _properties = CPSImageWidget._properties +\
    (
     {'id': 'path', 'type': 'string', 'mode': 'w',
      'label': 'Relative Path'},
     {'id': 'id_field', 'type': 'string', 'mode': 'w',
      'label': 'Field to build the id'},
    )
    path = "images"
    storage_path = "%s/import/%s" % (i_home,path)
    id_field = "reg_no"

    def getImageInfo(self, datastructure): ###(
        """Get the file info from the datastructure."""
        #import pdb; pdb.set_trace()
        widget_id = self.getWidgetId()
        if  datastructure.has_key(widget_id):
            fileupload = datastructure[widget_id]
            dm = datastructure.getDataModel()
            field_id = self.fields[0]
            content_url = "/uniben/viewimage?path=%s/%s_%s.jpg" %\
                                    (self.path,
                                    datastructure[self.id_field],
                                    self.getWidgetId(),
                                    )
            current_filename = "%s_%s.jpg" % (datastructure[self.id_field],
                                            field_id,)
            file_path = "/%s/%s" % (self.storage_path,
                                        current_filename)
        else:
            file_path = "XXX"
        # read the file from the filesystem
        if not os.path.exists(file_path):
            height = -1
            width = -1
            empty_file = True
            session_file = False
            current_filename = ''
            content_url = ''
            size = 0
            mimetype = ''
            last_modified = ''
            height = ''
            width = ''

        else:
            image = open(file_path)
            from OFS.Image import getImageInfo as getImageInfoOFS
            image.seek(0)
            data = image.read(2000)
            size = len(data)
            empty_file = size == 0
            session_file = False
            last_modified = ''
            image.close()
            mimetype, width, height = getImageInfoOFS(data)

            if width < 0:
                width = None
            if height < 0:
                height = None

            if (self.allow_resize
                and height is not None
                and width  is not None):
                z_w = z_h = 1
                h = int(self.display_height)
                w = int(self.display_width)
                if w and h:
                    if w < width:
                        z_w = w / float(width)
                    if h < height:
                        z_h = h / float(height)
                    zoom = min(z_w, z_h)
                    width = int(zoom * width)
                    height = int(zoom * height)
                #import pdb;pdb.set_trace()
        image_info = {
            'empty_file': empty_file,
            'session_file': session_file,
            'current_filename': current_filename,
            'size': size,
            'last_modified': last_modified,
            'content_url': content_url,
            'mimetype': mimetype,
            }
        title = image_info['current_filename']
        alt = title or ''
        #height = int(self.display_height)
        #width = int(self.display_width)
        if height is None or width is None:
            tag = renderHtmlTag('img', src=image_info['content_url'],
                                alt=alt, title=title)
        else:
            tag = renderHtmlTag('img', src=image_info['content_url'],
                                width=str(width), height=str(height),
                                alt=alt, title=title)

        image_info['height'] = height
        image_info['width'] = width
        image_info['image_tag'] = tag
        return image_info
    ###)


    def checkFileName(self, filename, mimetype):
        return '', {}
        if mimetype and mimetype.startswith('image'):
            return '', {}
        return 'cpsschemas_err_image', {}

    def prepare(self, datastructure, **kw): ###(
        """Prepare datastructure from datamodel."""
        datamodel = datastructure.getDataModel()
        widget_id = self.getWidgetId()
        file_name = datamodel[self.fields[0]]
        #import pdb; pdb.set_trace()
        if self.allow_resize:
            datastructure[self.getWidgetId() + '_resize'] = ''
        datastructure[widget_id] = file_name
        datastructure[widget_id + '_choice'] = 'change'
        title = 'Passport Foto'
        datastructure[widget_id + '_filename'] = title
    ###)

    def validate(self, datastructure, **kw): ###(
        """Update datamodel from user data in datastructure.
        """
        logger = logging.getLogger('Widgets.NoZodbImageWidget.validate')
        datamodel = datastructure.getDataModel()
        field_id = self.fields[0]
        widget_id = self.getWidgetId()
        store = False
        fileupload = None
        mimetype = None
        old_file = datamodel[field_id]
        # if old_file is not None:
        #     old_filename = old_file.title
        # else:
        #     old_filename = ''
        choice = datastructure[widget_id+'_choice']
        fileupload = datastructure[widget_id]
        is_upload = isinstance(fileupload, FileUpload)
        #import pdb; pdb.set_trace()
        if not is_upload and not datamodel[field_id]:
            if self.is_required:
                return self.validateError('Picture upload required', {},
                                          datastructure)
        if choice == 'delete':
            if self.is_required:
                return self.validateError('cpsschemas_err_required', {},
                                          datastructure)
            datamodel[field_id] = None
        elif choice == 'keep':
            fileupload = datastructure[widget_id]
            if isinstance(fileupload, PersistableFileUpload):
                # Keeping something from the session means we
                # actually want to store it.
                store = True
            # else:
            #     # Nothing to change, don't pollute datastructure
            #     # with something costly already stored, which therefore
            #     # doesn't need to be kept in the session.
            #     self.unprepare(datastructure)
        elif choice == 'change' and is_upload:
            if not fileupload:
                return self.validateError('cpsschemas_err_file_empty', {},
                                          datastructure)
            if not isinstance(fileupload, FileUpload):
                return self.validateError('cpsschemas_err_file', {},
                                          datastructure)
            fileupload.seek(0, 2) # end of file
            size = fileupload.tell()
            if not size:
                return self.validateError('cpsschemas_err_file_empty', {},
                                          datastructure)
            if self.size_max and size > self.size_max:
                max_size_str = self.getHumanReadableSize(self.size_max)
                err = 'This file is too big, the allowed max size is ${max_size}'
                logger.info('%s tried to upload picture with size %dk' %(datastructure['reg_no'],int(size)/1000) )
                err_mapping = {'max_size': max_size_str}
                return self.validateError(err, err_mapping, datastructure)
            store = True


        # Find filename
        if is_upload and store:
            ext ='jpg'
            filename = "%s_%s.%s" % (datastructure[self.id_field],
                                 self.getWidgetId(),
                                 ext)
            datamodel[field_id] = filename
            registry = getToolByName(self, 'mimetypes_registry')
            mimetype = registry.lookupExtension(filename.lower())
            if mimetype is not None:
                mimetype = str(mimetype) # normalize
            # Set/update data
            # file_path = "%s_%s.jpg" % (datamodel[self.id_field],
            #                            field_id,)
            full_path = "%s/%s" % (self.storage_path, filename)
            #import pdb; pdb.set_trace()
            file = self.makeFile(filename, fileupload, datastructure)
            # Fixup mimetype
            if mimetype and file.content_type != mimetype:
                file.content_type = mimetype
            # Store the file in the filesystem
            if not os.path.exists(self.storage_path):
                os.mkdir(self.storage_path)
            #import pdb;pdb.set_trace()
            pict = open(full_path,"w")
            fileupload.seek(0)
            pict.write(fileupload.read())
            pict.close()


        return True

###)

    def render(self, mode, datastructure, **kw): ###(
        render_method = 'widget_passport_render'
        meth = getattr(self, render_method, None)
        if meth is None:
            raise RuntimeError("Unknown Render Method %s for widget type %s"
                               % (render_method, self.getId()))
        img_info = self.getImageInfo(datastructure)
        return meth(mode=mode, datastructure=datastructure, **img_info)
    ###)

InitializeClass(NoZodbImageWidget)

widgetRegistry.register(NoZodbImageWidget)
###)


###########

