#-*- mode: python; mode: fold -*-

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 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 re import compile

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 %s already exists' % (value)
            elif value not in c_ids:
                err = 'Course %s does not exist' % (value)
            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 %s already exists' % (value)
            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 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
            if len(value.split()) > 1:
                err = 'Invalid Id (Id contains space(s)'
            elif self.portal_catalog(portal_type=portal_type_query,id=value):
                err = 'An object with the Id %s already exists in the Academic section' % (value)
            if err:
                datastructure.setError(widget_id, err)
            else:
                datamodel = datastructure.getDataModel()
                datamodel[self.fields[0]] = value

            return not err

InitializeClass(WAeUPIdWidget)

widgetRegistry.register(WAeUPIdWidget)


###)

class StudentIdWidget(CPSStringWidget): ###(
    """ StudentId Widget"""
    meta_type = "StudentId Widget"
    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)
        if not valid:
            return 0
        else:
            widget_id = self.getWidgetId()
            value = datastructure[widget_id]
            err = 0
            if not (len(value) == self.digits + self.letters and value[:self.digits].isdigit() and value[self.digits:].isalpha()):
                err = 'Invalid Registration Number in the format: %s%s with N = Number, L = Letter' % (self.digits_str,self.letters_str)
            if err:
                datastructure.setError(widget_id, err)
            else:
                datamodel = datastructure.getDataModel()
                datamodel[self.fields[0]] = value

            return not err

InitializeClass(StudentIdWidget)
widgetRegistry.register(StudentIdWidget)

###)

##def getStudentByRegNo(self,reg_no):
##    search = self.portal_catalog({'meta_type': 'StudentApplication',
##                                  'jamb_reg_no': reg_no,
##                                  })
##    if len(search) < 1:
##        return None
##    return search[0].getObject().
                    
class JambRegNoWidget(CPSStringWidget): ###(
    """ JambRegNo Widget"""
    meta_type = "JambRegNo Widget"
    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)
        if not valid:
            return 0
        else:
            widget_id = self.getWidgetId()
            value = datastructure[widget_id]
            err = 0
            if not (len(value) == self.digits + self.letters and value[:self.digits].isdigit() and value[self.digits:].isalpha()):
                err = 'Invalid Registration Number in the format: %s%s with N = Number, L = Letter' % (self.digits_str,self.letters_str)
            else:
                s = getStudentByRegNo(self,value)
                if s is None:
                    err = 'No JAMB data for %s' % (value)
            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 ScratchCardPin: ###(
    """the ScratchCardPin"""
    def __init__(self,prefix,batch_no,number):
        self.p = prefix
        self.b = batch_no
        self.n = number

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

class ScratchcardPinWidget(CPSStringWidget): ###(
    """ ScratchcardPin Widget"""
    meta_type = "Scratchcard Pin Widget"
    _properties = CPSWidget._properties + (
        {'id': 'prefix', 'type': 'string', 'mode': 'w',
         'label': 'Prefix'},
         {'id': 'reference', 'type': 'string', 'mode': 'w',
         'label': 'Reference Field'},

        )
    prefix = ''
    reference = ''
    
    def prepare(self, datastructure, **kw): ###(
        """Prepare datastructure from datamodel."""
        datamodel = datastructure.getDataModel()
        v = datamodel[self.fields[0]]
        widget_id = self.getWidgetId()
        if v and type(v) is StringType:
            p,b,n = v.split('-')
            v = ScratchCardPin(v,b,n)
        if v:
            b = '%s' % v.b
            n = '%s' % v.n
        else:
            b = n = ''
        datastructure[widget_id] = v
        datastructure[widget_id+'_b'] = b
        datastructure[widget_id+'_n'] = n
        
###)

    def validate(self, datastructure, **kw):
        """Validate datastructure and update datamodel."""
        widget_id = self.getWidgetId()
        v = datastructure[widget_id]
        err = 0
        p = self.prefix
        b = datastructure[widget_id+'_b'].strip()
        n = datastructure[widget_id+'_n'].strip()
        pins = self.portal_pins
        pin = "%(p)s%(b)s%(n)s" % vars()
        ref = datastructure[self.reference]
        #import pdb;pdb.set_trace()
        ok = pins.searchAndSetRecord(pin,ref)
        while 1:
            if ok == -1:
                err = 'invalid Pin'
                break
            if ok == 0:
                err = 'Pin already used'
                break
            if ok >= 1:
                student = getStudentByRegNo(self,ref)
                if student is None:
                    err = "Student not Found in validate SC"
                    break
                s_id = student.getId()
                if ok == 2:
                    break
                student.getContent().makeStudentMember(s_id,password=pin[4:])
            break
        if err:
            datastructure.setError(widget_id, err)
        else:
            datamodel = datastructure.getDataModel()
            datamodel[self.fields[0]] = ScratchCardPin(self.prefix,b,n)
            datastructure[widget_id] = ScratchCardPin(self.prefix,b,n)
            datastructure[widget_id+'_b'] = b
            datastructure[widget_id+'_n'] = n
            datastructure['s_id'] = s_id
        #import pdb;pdb.set_trace()
        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:
            p,b,n = v.split('-')
            v = ScratchCardPin(p,b,n)
        if v:
            b = '%s' % v.b
            n = '%s' % v.n
        else:
            b = n = ''
        if mode in ['edit', 'create']:
            widget_id = self.getWidgetId()
            datastructure[widget_id] = v
            datastructure[widget_id+'_b'] = b
            datastructure[widget_id+'_n'] = n
        return meth(mode=mode, 
                    datastructure=datastructure, 
                    prefix=self.prefix,
                    )
    ###)


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)


###########

