#-*- mode: python; mode: fold -*-
# $Id: Widgets.py 5577 2010-10-27 08:49:46Z henrik $
from cgi import escape
from types import *
import Globals
from Globals import InitializeClass
from ZPublisher.HTTPRequest import FileUpload
from OFS.Image import cookId, File, Image
##from Products.CPSSchemas.Widget import CPSWidgetType
from Products.CMFCore.utils import getToolByName
from Products.CPSSchemas.BasicWidgets import CPSBooleanWidget, CPSWidget, CPSStringWidget, CPSEmailWidget,CPSImageWidget,CPSIntWidget
from Products.CPSSchemas.BasicWidgets import CPSFileWidget, CPSPasswordWidget
from Products.CPSSchemas.BasicWidgets import renderHtmlTag,CPSSelectWidget, CPSStringWidget
from Products.CPSSchemas.ExtendedWidgets import CPSDateTimeWidget
from Products.CPSSchemas.Vocabulary import Vocabulary
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.WAeUP_SRP.WAeUPTool import getImagesDir
#from Products.ExtFile.ExtFile import ExtFile
import logging,os,re
import random
import operator
p_home = Globals.package_home(globals())
i_home = Globals.INSTANCE_HOME

#from zLOG import LOG, DEBUG


class WAeUPPasswordWidget(CPSPasswordWidget): ###(
    """WAeUP Password Widget"""
    meta_type = 'WAeUP Password Widget'

    _properties = CPSStringWidget._properties + (
        {'id': 'password_widget', 'type': 'string', 'mode': 'w',
         'label': 'Password widget to compare with'},
        {'id': 'check_lower', 'type': 'boolean', 'mode': 'w',
         'label': 'Checking at least one lower case [a-z]'},
        {'id': 'check_upper', 'type': 'boolean', 'mode': 'w',
         'label': 'Checking at least one upper case [A-Z]'},
        {'id': 'check_digit', 'type': 'boolean', 'mode': 'w',
         'label': 'Checking at least one digit [0-9]'},
        {'id': 'check_extra', 'type': 'boolean', 'mode': 'w',
         'label': 'Checking at least one extra char other than [a-zA-Z0-9]'},
        {'id': 'check_words', 'type': 'string', 'mode': 'w',
         'label': 'Checking for words'},
        )

    field_types = ('CPS Password Field',)
    password_widget = ''
    check_lower = 0
    check_upper = 0
    check_digit = 0
    check_extra = 0
    check_words = ''
    display_width = 8
    size_min = 5
    size_max = 8

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        widget_id = self.getWidgetId()
        value = datastructure[widget_id]
        err = 0
        try:
            v = str(value).strip()
        except ValueError:
            err = 'cpsschemas_err_string'
        else:
            if self.password_widget:
                # here we only check that that our confirm match the pwd
                pwidget_id = self.password_widget
                pvalue = datastructure[pwidget_id]
                datastructure[widget_id] = ''
                datastructure[pwidget_id] = ''
                pv = str(pvalue).strip()
                if pv and v != pv:
                    err = 'cpsschemas_err_password_mismatch'
            else:
                if not v:
                    if self.is_required:
                        datamodel = datastructure.getDataModel()
                        if not datamodel[self.fields[0]]:
                            err = 'cpsschemas_err_required'
                else:
                    # checking pw consistancy
                    len_v = len(v)
                    if not err and self.size_max and len_v > self.size_max:
                        err = 'cpsschemas_err_string_too_long'
                    if not err and self.size_min and len_v < self.size_min:
                        err = 'cpsschemas_err_password_size_min'
                    if not err and self.check_lower and not search(r'[a-z]', v):
                        err = 'cpsschemas_err_password_lower'
                    if not err and self.check_upper and not search(r'[A-Z]', v):
                        err = 'cpsschemas_err_password_upper'
                    if not err and self.check_digit and not search(r'[0-9]', v):
                        err = 'cpsschemas_err_password_digit'
                    if not err and self.check_extra and not search(r'[^a-zA-Z0-9]',
                                                                   v):
                        err = 'cpsschemas_err_password_extra'
                    if not err and v in self.check_words:
                        err = 'Your password is unsecure, please choose another password!'

        if err:
            datastructure[widget_id] = ''
            datastructure.setError(widget_id, err)
        elif v:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = v

        return not err

InitializeClass(WAeUPPasswordWidget)

widgetRegistry.register(WAeUPPasswordWidget)
###)

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.courses_catalog(code = 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 mode 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 mode key" % v)
            return 0
        if self.is_required and not len(v):
            datastructure.setError(widget_id, "mode 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 for import only"""
    meta_type = 'WAeUP Session Widget'

    def _getSessions(self):
        current_year = DateTime().year()
        #d = {'': ''}
        d = {}
        for y in range(current_year - 25,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]
        #import pdb;pdb.set_trace()        
        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 len(v) == 9:
            v = value[2:4]
        elif not value:
            v = ''
        sessions = self._getSessions()

        if not sessions.has_key(v):
            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

    # rendering is not used, instead we use a select widget with dynamic vocabulary
    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':'Pre-Studies'}
        d = {'000':'Pre-Studies'}
        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 v == '0':
            v = '000'
        if not levels.has_key(v):
            datastructure.setError(widget_id, "'%s' not a valid level" % v)
            return 0
        # if self.is_required and len(v) == 0:
        #     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['']
        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):
        if getattr(self,'_v_states',None) is not None and\
           getattr(self,'_v_lgas',None) is not None and\
           getattr(self,'_v_d',None) is not None and\
           getattr(self,'_v_word_dict',None) is not None:
            return (self._v_d,self._v_states,self._v_lgas,self._v_word_dict)
        mapping = self.waeup_tool.getStatesLgas()
        self._v_d = mapping['lga_dict']
        self._v_states = mapping['states']
        self._v_lgas = mapping['lgas']
        self._v_word_dict = mapping['word_dict']
        return (self._v_d,self._v_states,self._v_lgas,self._v_word_dict)


    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,word_dict = self._getLGAs()
        datamodel = datastructure.getDataModel()
        if self.state_field and self.lga_field:
            v = ' '.join((datastructure.get(self.state_field,""),
                              datastructure.get(self.lga_field,"")))
        state_lga = self.waeup_tool.findLga(v,word_dict)
        if not state_lga:
            if self.is_required:
                datastructure.setError(widget_id, "'%s' not a valid lga key" % v)
                #datastructure.setError(widget_id, "%s required" % widget_id)
                return 0
            else:
                state_lga = v
        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."""
        mode = kw.get('mode','create')
        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 and mode != 'remove':
                err = 'Invalid Id, Id contains space(s).'
            elif mode == "create" and\
                          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()
        value = 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 VocabularyOnTheFly: ###(
    def __init__(self, tuples):
        """a nonpersistent vocabulary (copy from CPSSchemas.Vocabulary.Vocabulary).
        Allowed parameter syntaxes is:
          - Vocabulary((('foo', "Foo", 'label_foo'), ('bar', "Bar", 'label_bar')))
            Same as first with message ids (msgids) that can be used for i18n
        """
        l = []
        d = {}
        m = {}
        # We suppose that initial vocabulary is sorted
        # Vocabulary((('foo', "Foo", 'label_foo'), ('bar', "Bar", 'label_bar')))
        for k, v, msgid in tuples:
            l.append(k)
            d[k] = v
            m[k] = msgid
        self._list = l
        self._dict = d
        self._msgids = m

    def __getitem__(self, key):
        """Get a label for a key."""
        return self._dict[key]

    def get(self, key, default=None):
        """Get a label for a key, default to None."""
        try:
            v = self._dict.get(key, default)
        except TypeError:
            # XXX temporary fix, don't know why sometime rendering try to do
            # get([]) that returning a typeError
            return ''
        return v

    def getMsgid(self, key, default=None):
        """Get a msgid for a key, default to None."""
        return self._msgids.get(key, default)

    def has_key(self, key):
        """Test if a key is present."""
        return self._dict.has_key(key)

    def keys(self):
        """Get the ordered list of keys."""
        return self._list[:]

    def items(self):
        """Get the ordered list of (key, value)."""
        return [(key, self._dict.get(key)) for key in self._list]

    def values(self):
        """Get the ordered list of values."""
        return [self._dict.get(key) for key in self._list]

    def keysSortedBy(self, crit='id'):
        """Return a keys list sorted on a criterium

        Crit is one of 'id', 'label' or 'i18n'.
        """

        if crit == 'label':
            l = [(x[1], x[0]) for x in self.items()]
            l.sort()
            return [x[1] for x in l]
        elif crit == 'i18n':
            portal = getToolByName(self, 'portal_url').getPortalObject()
            cpsmcat = portal.translation_service
            l = [(cpsmcat(self.getMsgid(key)).encode('ISO-8859-15', 'ignore'),
                  key) for key in self.keys()]
            l.sort()
            return [x[1] for x in l]
        else:
            return self.keys()
###)

class ApplicationCourseWidget(CPSSelectWidget): ###(
    """ ApplicationCourse Widget"""
    meta_type = "Application Course Widget"

    def _getVocabulary(self,datastructure=None):
        if self.REQUEST.traverse_subpath:
            screening_type = self.REQUEST.traverse_subpath[0].lower()
        else:
            screening_type = 'all'
        if screening_type in ("all","sandwich","sandwich2008","pg"):
            application_category = screening_type
        elif screening_type in ("cest","dp","ct","pt"):
            application_category = "cest"
        else:
            application_category = "basic"
        if not hasattr(self,'_v_certificates_docs'):
            # res = self.portal_catalog_real.search({'meta_type': "Certificate"})
            # d = {}
            # for cert in res:
            #     c = cert.getObject().getContent()
            #     if getattr(c,'application_category',''):
            #         d[cert.getId] = c
            res = self.certificates_catalog()
            d = {}
            for cert in res:
                if getattr(cert,'application_category',''):
                    d[cert.code] = cert
            self._v_certificates_docs = d
        l  = [('','','')]
        #l = []
        for k,d in self._v_certificates_docs.items():
            if application_category == "all":
                l  += (k,self._v_certificates_docs[k].title,k),
            else:
                if getattr(d,'application_category','') == application_category:
                    l  += (k,self._v_certificates_docs[k].title,k),
        #import ipdb;ipdb.set_trace()
        return VocabularyOnTheFly(l)

InitializeClass(ApplicationCourseWidget)

widgetRegistry.register(ApplicationCourseWidget)
###)

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)
            student_record = reg_no_catalog(jamb_reg_no = value)
            if len(student_record) < 1:
                err = 'No student record with this registration number'
            #elif self.catalog == "students_catalog" and student_record[0].review_state not in ('student_created','admitted'):
            #    err = 'Admission checking not allowed (wrong registration state)'
            else:
                datastructure['pume'] = student_record[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.strip(),)
            for cv in cvs:
                if cv  == value.strip().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','TRUE',True)
        male = value in ('M','m','Male','male','False','false','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 WAeUPBooleanWidget(CPSBooleanWidget): ###(
    """WAeUP boolean widget."""
    meta_type = 'WAeUP Boolean 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'
        true = value.upper() in ('T','1','TRUE','True','true','WAHR',True)
        false = value.upper() in ('F','0','FALSE','False','false','FALSCH',False)
        if not true and not false:
            datastructure.setError(self.getWidgetId(),
                                   "invalid boolean %s" % value)
            return 0
        elif true:
            v = True
        else:
            v = False
        datamodel = datastructure.getDataModel()
        datamodel[self.fields[0]] = v
        return 1

InitializeClass(WAeUPBooleanWidget)

widgetRegistry.register(WAeUPBooleanWidget)

###)

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]
        if not v:
            v = []
        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
            #import pdb;pdb.set_trace()
            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:
                if v:
                    v += (s,g),
                else:
                    v = [(s,g),]
            break
        if err:
            datastructure.setError(widget_id, err)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = v
            datastructure[widget_id] = 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()))
        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'},
         {'id': 'reuse_pin', 'type': 'boolean', 'mode': 'w',
         'label': 'Reuse Application Pin'},
        )
    prefix = ''
    reference = ''
    reuse_pin = False

    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))
            elif prefix == 'APP' and not self.reuse_pin:
                res =  self.applicants_catalog(reg_no = ref)
                if not res:
                    res =  self.applicants_catalog(reg_no = ref.upper())
                if res and res[0].pin == pin_str:
                    do = 0
                    err = 'Application PINs cannot be reused.'
                    s_logger.info('%s entered same PIN as for screening application %s' % (s_id,pin_str))

        while do:
            ok,record = 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 record 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=n)
                    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"
    reference = ''

    def prepare(self, datastructure, **kw): ###(
        """Prepare datastructure from datamodel."""
        datamodel = datastructure.getDataModel()
        #import pdb;pdb.set_trace()
        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.PumePinWidget.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()
        member_id = str(self.portal_membership.getAuthenticatedMember())
        do = 1
        expiration_date = self.REQUEST.get('expiration_date')
        if self.isStaff():
            do = 0
            err ='You are logged in, please log out. PIN neither checked nor used.'
            s_logger.info('%s tried to use scratch card %s' % (member_id,pin_str))
        elif self.isStudent():
            do = 0
            #ref = datastructure[self.reference]
            err ='You are logged in, please log out. PIN neither checked nor used.'
            s_logger.info('%s applied for screening test while logged in with pin %s' % (member_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 "-"' % (member_id))
        elif n.find('-') > -1:
            do = 0
            err = 'PIN must not contain "-"'
            s_logger.info('%s entered invalid PIN  containing "-"' % (member_id))
        elif len(n) != 10:
            do = 0
            err = 'Invalid PIN length'
            s_logger.info('%s entered invalid PIN with length %d' % (member_id,len(n)))
        elif self.reference == "":
            # see fceokene #147. must be also changed for uniben after clearing the catalog
            #import pdb;pdb.set_trace()
            if 'sandwich2008' in self.REQUEST.get('screening_type'):
                ref = n
            else:
                ref = pin
        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' % (member_id,ref,pin_str))
        while do:
            if self.REQUEST.traverse_subpath:
                screening_type_request = self.REQUEST.traverse_subpath[0]
            else:
                screening_type_request = 'manage'
            if datastructure.has_key('record'):
                applicant = datastructure['record']
                if applicant.screening_type != screening_type_request and screening_type_request != 'manage':
                    err = "You are using the wrong access form!"
                    s_logger.info('%s tried to use %s application form but has applied for %s' % (ref,screening_type_request,applicant.screening_type))
                    break
            elif expiration_date and DateTime(expiration_date).lessThan(DateTime()):
                if not pins(student=ref):
                    if not self.applicants_catalog(reg_no=ref):
                        err = 'no application record found'
                        s_logger.info('%s/%s tried new application though expired with PIN %s' % (member_id,ref,pin_str))
                        break
                    else:
                        s_logger.info('%s/%s entered application record which has been created by import (with PIN %s)' % (member_id,ref,pin_str))
            ok,pin_record = 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' % (member_id,ref,pin_str))
                break
            elif ok == -2:
                err = 'Service is already activated but with a different PIN.'
                s_logger.info('%s/%s repeatedly activated service but with different PIN %s' % (member_id,ref,pin_str))
                break
            elif ok == -1:
                err = 'Invalid PIN'
                s_logger.info('%s/%s entered invalid PIN %s' % (member_id,ref,pin_str))
                break
            if ok == 0:
                err = 'PIN already used'
                s_logger.info('%s/%s entered used PIN %s' % (member_id,ref,pin_str))
                break
            if ok >= 1:
                #screening_type = self.REQUEST.form.get('screening_type','unknown')
                #screening_type = datastructure['screening_type']
                if datastructure.has_key('record'):
                    applicant = datastructure['record']
                    if applicant.screening_type != screening_type_request\
                          and screening_type_request != 'manage':
                        err = "You are using the wrong access form!"
                        s_logger.info('%s tried to use %s application form but has applied for %s' % (ref,screening_type_request,applicant.screening_type))
                        break
                    if not applicant.pin:
                        s_logger.info('%s successfully used PIN %s, imported applicant record modified' % (ref,pin_str))
                        d = {}
                        d['reg_no'] = applicant.reg_no
                        d['pin'] = pin_str
                        #d['screening_type'] = screening_type
                        #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' % (member_id,ref,pin_str))
                    #elif applicant.pin == pin_str:
                        #s_logger.info('%s/%s repeatedly entered application record with PIN %s' % (member_id,ref,pin_str))
                else:
                    datastructure['reg_no'] = ref
                    res = self.applicants_catalog(reg_no = ref)
                    if res:
                        if getattr(res[0],'screening_type',None) != screening_type_request\
                              and screening_type_request != 'manage':
                            err = "You are using the wrong access form!"
                            s_logger.info('%s tried to use %s application form but has applied for %s' % (ref,screening_type_request,getattr(res[0],'screening_type',None)))
                            break
                        #s_logger.info('%s/%s repeatedly entered application record with PIN %s' % (member_id,ref,pin_str))
                    else:
                        s_logger.info('%s successfully used PIN %s, applicant record added' % (ref,pin_str))
                        d = {}
                        d['reg_no'] = ref
                        d['pin'] = pin_str
                        d['status'] = 'entered'
                        d['screening_type'] = screening_type_request
                        d['serial'] = "%c%05d" % (pin_record.prefix_batch[-1],
                                                  pin_record.serial)
                        self.applicants_catalog.addRecord(**d)

            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
        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 ApplicationImageWidget(CPSImageWidget): ###(
    """Image widget with filesystem storage."""
    meta_type = 'Application 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."""
        widget_id = self.getWidgetId()
        if  datastructure.has_key(widget_id):
            fileupload = datastructure[widget_id]
            dm = datastructure.getDataModel()
            field_id = self.fields[0]
            screening_type = datastructure.get('screening_type')
            current_filename = "%s_%s.jpg" % (datastructure[self.id_field],
                                            field_id,)
            base_path = os.path.join(screening_type,current_filename)
            content_url = os.path.join('viewimage_applicant',self.path,base_path)
            file_path = os.path.join(self.storage_path,base_path)
            #import pdb; pdb.set_trace()
        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'] = ''
        screening_type = datamodel.get('screening_type',None)
        if not screening_type:
            screening_type = self.REQUEST.form.get('screening_type','pume')
        datastructure["screening_type"] = screening_type
        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.ApplicationImageWidget.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'
            screening_type = datastructure.get('screening_type')
            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
            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
            #import pdb;pdb.set_trace()
            base_path = os.path.join(self.storage_path, screening_type)
            if not os.path.exists(base_path):
                os.mkdir(base_path)
            full_path = os.path.join(base_path, filename)
            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(ApplicationImageWidget)

widgetRegistry.register(ApplicationImageWidget)
###)

class FileImageWidget(CPSImageWidget): ###(
    """Image widget with filesystem storage."""
    meta_type = 'File 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'},
     {'id': 'show_image', 'type': 'boolean', 'mode': 'w',
      'label': 'Show Image'},
    )
    path = "images"
    #storage_path = "%s/%s" % (i_home,path)
    id_field = ""
    show_image = False

    def getStorageImageInfo(self,field_id):
        info = {}
        if self.id_field == "":
            student_id = self.getStudentId()
        else:
            student_id = datastructure[self.id_field]
        # student_path = os.path.join(self.storage_path,
        #                             student_id)
        student_path = getImagesDir(student_id)
        image_name = ''
        content_url = ''
        current_filename = ''
        if os.path.exists(student_path):
            for name in os.listdir(student_path):
                if name.startswith(field_id):
                    image_name = name
                    break
        if image_name:
            info['image_name'] = image_name
            info['content_url'] = os.path.join(self.portal_url(),
                                               "viewimage",
                                               student_id,
                                               image_name,
                                              )
            info['current_filename'] =  image_name
            info['file_path'] = os.path.join(student_path, image_name)
        return info

    def getImageInfo(self, datastructure): ###(
        """Get the file info from the datastructure."""
        widget_id = self.getWidgetId()
        info = None
        if  datastructure.has_key(widget_id):
            fileupload = datastructure[widget_id]
            dm = datastructure.getDataModel()
            field_id = self.fields[0]
            info = self.getStorageImageInfo(field_id)
        else:
            file_path = "XXX"
            title = ""
        # read the file from the filesystem
        #import pdb; pdb.set_trace()
        #if not os.path.exists(file_path):
        if not info:
            title = ""
            height = -1
            width = -1
            empty_file = True
            session_file = False
            current_filename = ''
            content_url = ''
            size = 0
            mimetype = ''
            last_modified = ''
            height = ''
            width = ''
        else:
            title = info['image_name']
            current_filename = info['current_filename']
            content_url = info['content_url']
            image = open(info['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)
            registry = getToolByName(self, 'mimetypes_registry')
            mimetype = (registry.lookupExtension(current_filename.lower()) or
                        registry.lookupExtension('file.bin'))
            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': title,
            'size': size,
            'last_modified': last_modified,
            'content_url': content_url,
            'mimetype': mimetype,
            }
        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
        image_info['show_image'] = self.show_image
        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]]
        if self.id_field == "":
            student_id = self.getStudentId()
        else:
            student_id = datastructure[self.id_field]
        if student_id is not None:
            # student_path = os.path.join(self.storage_path,
            #                             student_id)
            student_path = getImagesDir(student_id)
            if not os.path.exists(student_path):
                self.waeup_tool.moveImagesToFS(student_id)
        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.FileImageWidget.validate')
        datamodel = datastructure.getDataModel()
        field_id = self.fields[0]
        widget_id = self.getWidgetId()
        store = False
        fileupload = None
        mimetype = None
        old_file = datamodel[field_id]
        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 self.id_field == "":
            student_id = self.getStudentId()
        else:
            student_id = datastructure[self.id_field]
        if choice == 'delete':
            if self.is_required:
                return self.validateError('cpsschemas_err_required', {},
                                          datastructure)
            info= self.getStorageImageInfo(field_id)
            # Remove the file in the filesystem
            if info:
                os.remove(info['file_path'])
            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}'
                member_id = str(self.portal_membership.getAuthenticatedMember())
                logger.info('%s tried to upload picture with size %dk' %(member_id,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:
            filename = cookId('', '', fileupload)[0].strip()
            base,ext = os.path.splitext(filename)
            filename = "%s_%s%s" % (field_id,
                                    student_id,
                                    ext)
            datamodel[field_id] = filename
            registry = getToolByName(self, 'mimetypes_registry')
            mimetype = registry.lookupExtension(filename.lower())
            if mimetype is not None:
                mimetype = str(mimetype) # normalize
            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
            #student_path = os.path.join(self.storage_path,student_id)
            student_path = getImagesDir(student_id)
            if not os.path.exists(student_path):
                os.mkdir(student_path)
            full_path = os.path.join(student_path, filename)
            pict = open(full_path,"w")
            #fileupload.seek(0)
            #import pdb; pdb.set_trace()
            pict.write(str(file.data))
            pict.close()
        return True
    ###)

    def render(self, mode, datastructure, **kw): ###(
        render_method = 'widget_image_render'
        meth = getattr(self, render_method, None)
        #import pdb;pdb.set_trace()
        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(FileImageWidget)

widgetRegistry.register(FileImageWidget)
###)

class DiscFileWidget(CPSFileWidget): ###(
    """File widget with filesystem storage."""
    meta_type = 'Disc File Widget'
    _properties = CPSFileWidget._properties +\
    (
     {'id': 'path', 'type': 'string', 'mode': 'w',
      'label': 'Relative Path'},
    )
    path = "import"
    storage_path = "%s/%s" % (i_home,path)

    def getStoredFileInfo(self,datastructure): ###(
        datamodel = datastructure.getDataModel()
        field_id = self.fields[0]
        widget_id = self.getWidgetId()
        file_name = datamodel[field_id]
        info = {}
        registry = getToolByName(self, 'mimetypes_registry')
        info['mimetype'] = registry.lookupExtension('file.csv')
        info['empty_file'] = True
        info['size'] = 0
        info['last_modified'] = ''
        file_path = os.path.join(self.storage_path, file_name)
        if os.path.exists(file_path):
            info['empty_file'] = False
            info['file_name'] = file_name
            info['content_url'] = os.path.join(self.portal_url(),
                                            "viewfile",
                                            file_name,
                                            )
            info['current_filename'] =  file_name
            # get the mimetype
            mimetype = (registry.lookupExtension(file_name.lower()) or
                        registry.lookupExtension('file.bin'))
            info['mimetype'] = mimetype
            info['file_path'] = file_path
        else:
            info['file_name'] = ''
            info['content_url'] = ''
            info['current_filename'] = ''
            info['file_path'] = ''
        return info
        ###)

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

    def validate(self, datastructure, **kw): ###(
        """Update datamodel from user data in datastructure.
        """
        logger = logging.getLogger('Widgets.DiscFileWidget.validate')
        datamodel = datastructure.getDataModel()
        field_id = self.fields[0]
        widget_id = self.getWidgetId()
        store = False
        fileupload = None
        mimetype = None
        old_file = datamodel[field_id]
        choice = datastructure[widget_id+'_choice']
        fileupload = datastructure[widget_id]
        is_upload = isinstance(fileupload, FileUpload)
        if not is_upload and not datamodel[field_id]:
            if self.is_required:
                return self.validateError('File upload required', {},
                                          datastructure)
        if choice == 'delete':
            if self.is_required:
                return self.validateError('cpsschemas_err_required', {},
                                          datastructure)
            info = self.getStoredFileInfo(datastructure)
            # Remove the file in the filesystem
            if info:
                os.remove(info['file_path'])
            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}'
                member_id = str(self.portal_membership.getAuthenticatedMember())
                logger.info('%s tried to upload picture with size %dk' %(member_id,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:
            filename = cookId('', '', fileupload)[0].strip()
            base,ext = os.path.splitext(filename)
            if ext not in ("csv",".csv"):
                return self.validateError('only csv files allowed', {},
                                          datastructure)
            uploads_folder = self.portal_url.getPortalObject().campus.uploads
            if hasattr(uploads_folder,filename):
                return self.validateError('upload object exists', {},
                                          datastructure)
            datamodel[field_id] = filename
            registry = getToolByName(self, 'mimetypes_registry')
            mimetype = registry.lookupExtension(filename.lower())
            if mimetype is not None:
                mimetype = str(mimetype) # normalize
            file = self.makeFile(filename, fileupload, datastructure)
            # Fixup mimetype
            if mimetype and file.content_type != mimetype:
                file.content_type = mimetype
            file_path = os.path.join(self.storage_path,filename)
            data = open(file_path,"w")
            data.write(str(file.data))
            data.close()
        return True
    ###)

    def render(self, mode, datastructure, **kw): ###(
        render_method = 'widget_uploadfile_render'
        meth = getattr(self, render_method, None)
        #import pdb;pdb.set_trace()
        if meth is None:
            raise RuntimeError("Unknown Render Method %s for widget type %s"
                               % (render_method, self.getId()))
        file_info = self.getStoredFileInfo(datastructure)

        return meth(mode=mode, datastructure=datastructure, **file_info)
    ###)

InitializeClass(DiscFileWidget)

widgetRegistry.register(DiscFileWidget)


class RegMatricNoWidget(CPSStringWidget): ###(
    """ RegMatricNo Widget"""
    meta_type = "RegMatricNo Widget"
    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        valid = CPSStringWidget.validate(self, datastructure, **kw)
        widget_id = self.getWidgetId()
        value = datastructure[widget_id].upper()
        err = 0
        #import pdb;pdb.set_trace()
        if not valid:
            err = 'Invalid number'
        else:
            student_record = self.students_catalog(jamb_reg_no = value)
            if len(student_record) < 1:
                student_record = self.students_catalog(matric_no = value)
                if len(student_record) < 1:
                    err = 'No student record with this registration or matric number'
                else:
                    datastructure['record'] = student_record[0]
                    #import pdb;pdb.set_trace()
            else:
                datastructure['record'] = student_record[0]
                #import pdb;pdb.set_trace()
        if err:
            datastructure.setError(widget_id, err)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = value
        
        return not err

InitializeClass(RegMatricNoWidget)

widgetRegistry.register(RegMatricNoWidget)

class CheckEmailWidget(CPSStringWidget): ###(
    """ CheckEmail Widget"""
    meta_type = "CheckEmail Widget"
    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        if datastructure.errors:
            return
        valid = CPSStringWidget.validate(self, datastructure, **kw)
        widget_id = self.getWidgetId()
        value = datastructure[widget_id].upper()
        err = 0
        #import pdb;pdb.set_trace()
        if not valid:
            err = 'Invalid string'
        else:
            email_cat = datastructure['record'].email.upper()
            if email_cat != value:
                err = 'Email address does not match'
            else:
                pass
        if err:
            datastructure.setError(widget_id, err)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = value            
        
        return not err

InitializeClass(CheckEmailWidget)

widgetRegistry.register(CheckEmailWidget)

###)

class PhoneWidget(CPSIntWidget): ###(
    """ Phone Widget"""
    meta_type = "Phone Widget"
    
    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""

        valid = CPSIntWidget.validate(self, datastructure, **kw)
        if not valid:
            return 0
        else:
            widget_id = self.getWidgetId()
            value = datastructure[widget_id]
            #import pdb;pdb.set_trace()
            if value == '234':
                value = ''
                datamodel = datastructure.getDataModel()
                datamodel[self.fields[0]] = value
            elif value.startswith('2340'):
                err = 'Wrong Nigerian phone format'
                datastructure.setError(widget_id, err)
                return 0
            return 1

    def render(self, mode, datastructure, **kw):
        """Render in mode from datastructure."""
        value = datastructure[self.getWidgetId()]
        #import pdb;pdb.set_trace()
        if mode == 'view':
            if value == '':
                return ''
            else:
                return '+' + escape(value)
        elif mode == 'edit':
            if value == '':
                value = 234
            tag = renderHtmlTag('input',
                                 type='text',
                                 name=self.getHtmlWidgetId(),
                                 value=value)
            return '<strong>+</strong>' + tag
        raise RuntimeError('unknown mode %s' % mode)


InitializeClass(PhoneWidget)

widgetRegistry.register(PhoneWidget)




###########

