#-*- mode: python; mode: fold -*-
# $Id: Widgets.py 1988 2007-07-05 11:14:12Z joachim $
from cgi import escape
from types import *
from Globals import InitializeClass
##from Products.CPSSchemas.Widget import CPSWidgetType
from Products.CMFCore.utils import getToolByName
from Products.CPSSchemas.BasicWidgets import CPSBooleanWidget, CPSWidget, CPSStringWidget, CPSEmailWidget,CPSImageWidget
from Products.CPSSchemas.BasicWidgets import renderHtmlTag,CPSSelectWidget, CPSStringWidget
from Products.CPSSchemas.ExtendedWidgets import CPSDateTimeWidget
from Products.CPSSchemas.Widget import widgetRegistry
##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 re import compile
import logging
import operator

#from zLOG import LOG, DEBUG

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

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

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

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

InitializeClass(CPSSelectWidgetForRecord)

widgetRegistry.register(CPSSelectWidgetForRecord)

###)

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

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

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

InitializeClass(CPSStringWidgetForRecord)

widgetRegistry.register(CPSStringWidgetForRecord)

###)

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

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

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

            return not err

InitializeClass(CertificateCourseIdWidget)

widgetRegistry.register(CertificateCourseIdWidget)
###)

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

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

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

            return not err

InitializeClass(CourseIdWidget)

widgetRegistry.register(CourseIdWidget)


###)

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

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

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

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

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

InitializeClass(WAeUPStudyModeWidget)

widgetRegistry.register(WAeUPStudyModeWidget)

###)

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

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

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

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

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

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

InitializeClass(WAeUPSessionWidget)

widgetRegistry.register(WAeUPSessionWidget)

###)

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

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

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

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

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

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

InitializeClass(WAeUPLevelWidget)

widgetRegistry.register(WAeUPLevelWidget)

###)

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

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

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

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

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

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

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

InitializeClass(WAeUPVerdictWidget)

widgetRegistry.register(WAeUPVerdictWidget)

###)

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

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

InitializeClass(WAeUPReservedRoomsWidget)

widgetRegistry.register(WAeUPReservedRoomsWidget)
###)

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

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

        valid = CPSStringWidget.validate(self, datastructure, **kw)
        id_pat_str = r"\S"
        inv_id_pat = 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()
            err = 0
            mapping = {}
            if len(value.split()) > 1:
                err = 'Invalid Id, Id contains space(s).'
            elif self.portal_catalog(portal_type=portal_type_query,id=value):
                brain = self.portal_catalog(portal_type=portal_type_query,id=value)[0]
                err = 'An ${portal_type} object with the Id ${id} already exists at ${path}.'
                mapping = {'portal_type': brain.portal_type,
                           'id': value,
                           'path': brain.getPath(),
                           }
            if err:
                datastructure.setError(widget_id, err, mapping)
            else:
                datamodel = datastructure.getDataModel()
                datamodel[self.fields[0]] = value

            return not err

InitializeClass(WAeUPIdWidget)

widgetRegistry.register(WAeUPIdWidget)


###)

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

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

InitializeClass(StudyCourseWidget)

widgetRegistry.register(StudyCourseWidget)
###)

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

InitializeClass(JambRegNoWidget)

widgetRegistry.register(JambRegNoWidget)
###)

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

InitializeClass(SecretWidget)

widgetRegistry.register(SecretWidget)
###)

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

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

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

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

InitializeClass(WAeUPSexWidget)

widgetRegistry.register(WAeUPSexWidget)

###)

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

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

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

InitializeClass(MatricNoWidget)

widgetRegistry.register(MatricNoWidget)
###)

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

InitializeClass(StudentIdWidget)

widgetRegistry.register(StudentIdWidget)
###)

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

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

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

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


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

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

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

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

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


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

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

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

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

class ScratchcardPinWidget(CPSStringWidget): ###(
    """ ScratchcardPin Widget"""
    meta_type = "Scratchcard Pin Widget"
    _properties = CPSWidget._properties + (
        {'id': 'prefix', 'type': 'string', 'mode': 'w',
         'label': 'Prefix'},
         {'id': 'reference', 'type': 'string', 'mode': 'w',
         'label': 'Reference Field'},
        )
    prefix = ''
    reference = ''
    def prepare(self, datastructure, **kw): ###(
        """Prepare datastructure from datamodel."""
        datamodel = datastructure.getDataModel()
        v = datamodel[self.fields[0]]
        widget_id = self.getWidgetId()
        #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(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())
        #import pdb;pdb.set_trace()
        if self.isStaff():
            do = 0
            err ='You are not a Student. PIN neither checked nor used.'
            s_logger.info('%s tried to use scratch card %s' % (s_id,pin_str))
        elif len(b) > 1 and b.find('-') > -1:
            do = 0
            err = 'PIN must not contain "-"'
            s_logger.info('%s entered invalid PIN  containing "-"' % (s_id))
        elif n.find('-') > -1:
            do = 0
            err = 'PIN must not contain "-"'
            s_logger.info('%s entered invalid PIN  containing "-"' % (s_id))
        elif len(n) != 10:
            do = 0
            err = 'Invalid PIN length'
            s_logger.info('%s entered invalid PIN with length %d' % (s_id,len(n)))
        elif self.reference == "":
            ref = s_id
        else:
            ref = datastructure[self.reference]
            if datastructure.errors:
                do = 0
                datastructure.setError(widget_id, 'PIN neither checked nor used.')
                s_logger.info('%s/%s entered wrong data together with PIN %s' % (s_id,ref,pin_str))
        while do:
            ok = pins.searchAndSetRecord(pin,ref,prefix)
            if ok < -2 or ok > 2:
                err = 'Unknown error, please report!'
                s_logger.info('%s/%s caused unknown error with PIN %s' % (s_id,ref,pin_str))
                break
            elif ok == -2:
                err = 'Service already is activated but with a different PIN.'
                s_logger.info('%s/%s repeatedly activated service but with different PIN %s' % (s_id,ref,pin_str))
                break
            elif ok == -1:
                err = 'Invalid PIN'
                s_logger.info('%s/%s entered invalid PIN %s' % (s_id,ref,pin_str))
                break
            if ok == 0:
                err = 'PIN already used'
                s_logger.info('%s/%s entered used PIN %s' % (s_id,ref,pin_str))
                break
            if ok >= 1:
                #import pdb;pdb.set_trace()
                if self.isStudent():
                    if self.reference == "jamb_reg_no":
                        err = "You are already logged in."
                        s_logger.info('%s/%s checked admission with PIN %s though logged in' % (s_id,ref,pin_str))
                        break
                    if ok == 1:
                        s_logger.info('%s/%s successfully used PIN %s' % (s_id,ref,pin_str))
                    else:
                        s_logger.info('%s/%s repeatedly used PIN %s' % (s_id,ref,pin_str))
                    break
                else:
                    student = getStudentByRegNo(self,ref)
                    s_logger.info('%s/%s successfully used PIN %s' % (s_id,ref,pin_str))
                if student is None:
                    err = "Student not found"
                    s_logger.info('%s not found in admission list' % (ref))
                    break
                s_id = student.getId()
                if ok == 2:
                    if self.reference == "jamb_reg_no":
                        if hasattr(self.portal_directories.students,s_id):
                            err = "Please login with your Student Id ${id} and 10-digit PIN."
                            mapping = {'id': s_id}
                            s_logger.info('%s/%s repeatedly checked admission with PIN %s' % (s_id,ref,pin_str))
                            break
                        else:
                            s_logger.info('%s/%s (non-member) repeatedly checked admission with PIN %s' % (s_id,ref,pin_str))
                    else:
                        err = "Unknown error"
                        s_logger.info('%s/%s repeatedly activated service with PIN %s' % (s_id,ref,pin_str))
                        break
                try:
                    student.getContent().makeStudentMember(s_id,password=pin[4:])
                    s_logger.info('%s/%s has been created using PIN %s' % (s_id,ref,pin_str))
                except:
                    err = "Please login with your Student Id ${id} and 10-digit PIN."
                    mapping = {'id': s_id}
                    s_logger.info('%s/%s could not be made a member with PIN %s' % (s_id,ref,pin_str))
                    break
            break
        if err:
            datastructure.setError(widget_id, err,mapping)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = ScratchCardPin(prefix,b,n)
            datastructure[widget_id] = ScratchCardPin(prefix,b,n)
            datastructure[widget_id+'_p'] = prefix
            datastructure[widget_id+'_b'] = b
            datastructure[widget_id+'_n'] = n
            datastructure['s_id'] = s_id
        return not err

###)

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

        # XXX AT: datastructure has to be set again here, in case we're in edit
        # or create mode, because a default value has to be provided.
        #import pdb;pdb.set_trace()
        datamodel = datastructure.getDataModel()
        v = datamodel[self.fields[0]]
        if v and type(v) is StringType:
            try:
                p,b,n = v.split('-')
                v = ScratchCardPin(p,b,n)
            except ValueError:
                v = ScratchCardPin(self.prefix,'1',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 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)
###)


###########

