#-*- 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 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 = [(int(r.split('/')[0]),int(r.split('/')[1])) for r in re.split(',|\.| ',value)
                                     if r]
            except ValueError,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
            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)
##
#####)

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 Student with JAMB-Reg-No %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()
        #import pdb;pdb.set_trace()
        if v and type(v) is StringType:
            p,b,n = v.split('-')
            v = ScratchCardPin(v,b,n)
        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."""
        #import pdb;pdb.set_trace()
        widget_id = self.getWidgetId()
        v = datastructure[widget_id]
        err = 0
        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()
        if self.reference == "":
            ref = str(self.portal_membership.getAuthenticatedMember())
        else:
            ref = datastructure[self.reference]
        ok = pins.searchAndSetRecord(pin,ref,prefix)
        while 1:
            if ok == -2:
                err = 'You have already applied with a different Pin, please login.'
                break
            elif ok == -1:
                err = 'invalid Pin'
                break
            if ok == 0:
                err = 'Pin already used'
                break
            if ok >= 1:
                #import pdb;pdb.set_trace()
                if self.isStudent():
                    student = self.getStudentInfo()['student']
                    s_id = student.getId()
                    break
                else:
                    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(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:
            prefix,b,n = v.split('-')
            v = ScratchCardPin(prefix,b,n)
        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)


###########

