#-*- mode: python; mode: fold -*-
# (C) Copyright 2005 AixtraWare <http://aixtraware.de>
# Author: Joachim Schmitz <js@aixtraware.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#
# $Id: WAeUPTables.py 1673 2007-04-09 16:01:51Z joachim $

from zope.interface import implements
from Globals import InitializeClass
from Products.ZCatalog.ZCatalog import ZCatalog
from AccessControl import ClassSecurityInfo
from Products.CMFCore.permissions import ModifyPortalContent

import DateTime
import csv,re
import logging
import Globals
p_home = Globals.package_home(globals())
i_home = Globals.INSTANCE_HOME

from interfaces import IWAeUPTable

class AttributeHolder(object):
    pass

def dict2ob(dict):
    ob = AttributeHolder()
    for key, value in dict.items():
        setattr(ob, key, value)
    return ob


class WAeUPTable(ZCatalog): ###(

    implements(IWAeUPTable)
    security = ClassSecurityInfo()

    def addRecord(self, **data):
        # The uid is the same as "bed".
        uid = data[self.key]
        res = self.searchResults({"%s" % self.key : uid})
        if len(res) > 0:
            raise ValueError("More than one record with uid %s" % uid)
        self.catalog_object(dict2ob(data), uid=uid)
        return uid

    def deleteRecord(self, uid):
        #import pdb;pdb.set_trace()
        self.uncatalog_object(uid)

    def searchAndSetRecord(self, **data):
        raise NotImplemented

    def modifyRecord(self, **data):
        #records = self.searchResults(uid=uid)
        uid = data[self.key]
        records = self.searchResults({"%s" % self.key : uid})
        if len(records) > 1:
            # Can not happen, but anyway...
            raise ValueError("More than one record with uid %s" % uid)
        if len(records) == 0:
            raise KeyError("No record for uid %s" % uid)
        record = records[0]
        record_data = {}
        for field in self.schema() + self.indexes():
            record_data[field] = getattr(record, field)
        record_data = {}
        for field in self.schema() + self.indexes():
            record_data[field] = getattr(record, field)
        # Add the updated data:
        record_data.update(data)
        self.catalog_object(dict2ob(record_data), uid)

    def reindexIndex(self, name, REQUEST,pghandler=None):
        if isinstance(name, str):
            name = (name,)
        paths = self._catalog.uids.items()
        i = 0
        #import pdb;pdb.set_trace()
        for p,rid in paths:
            i += 1
            metadata = self.getMetadataForRID(rid)
            record_data = {}
            for field in name:
                record_data[field] = metadata.get(field)
            uid = metadata.get(self.key)
            self.catalog_object(dict2ob(record_data), uid, idxs=name,
                                update_metadata=0)

    security.declareProtected(ModifyPortalContent,"exportAllRecords")
    def exportAllRecords(self):
        "export a WAeUPTable"
        #import pdb;pdb.set_trace()
        fields = [field for field in self.schema()]
        format = ','.join(['"%%(%s)s"' % fn for fn in fields])
        csv = []
        csv.append(','.join(['"%s"' % fn for fn in fields]))
        for uid in self._catalog.uids:
            records = self.searchResults({"%s" % self.key : uid})
            if len(records) > 1:
                # Can not happen, but anyway...
                raise ValueError("More than one record with uid %s" % uid)
            if len(records) == 0:
                raise KeyError("No record for uid %s" % uid)
            rec = records[0]
            csv.append(format % rec)
        current = DateTime.DateTime().strftime("%d-%m-%y_%H_%M_%S")
        open("%s/import/%s-%s.csv" % (i_home,self.getId(),current),"w+").write('\n'.join(csv))

###)

class AccommodationTable(WAeUPTable): ###(

    meta_type = 'WAeUP Accommodation Tool'
    name = "accommodation"
    key = "bed"
    def __init__(self):
        WAeUPTable.__init__(self, 'portal_accommodation')

    def searchAndReserveBed(self, student_id,bed_type):
        records = self.searchResults({'student' : student_id})
        if len(records) > 0:
            return -1,"Student with Id %s already booked bed %s." % (student_id,records[0].bed)

        records = [r for r in self.searchResults({'bed_type' : bed_type}) if not r.student]
        #import pdb;pdb.set_trace()
        if len(records) == 0:
            return -2,"No bed available"
        rec = records[0]
        self.modifyRecord(bed=rec.bed,student=student_id)
        s_logger = logging.getLogger('WAeUPTables.AccommodationTable.searchAndReserveBed')
        s_logger.info('%s reserved bed %s' % (student_id,rec.bed))
        return 1,rec.bed


InitializeClass(AccommodationTable)

###)

class PinTable(WAeUPTable): ###(
    from ZODB.POSException import ConflictError
    meta_type = 'WAeUP Pin Tool'
    name = "pins"
    key = 'pin'
    def __init__(self):
        WAeUPTable.__init__(self, 'portal_pins')


    def searchAndSetRecord(self, uid, student_id,prefix):
        #records = self.searchResults(uid=uid)
        records = self.searchResults(student = student_id)
        #import pdb;pdb.set_trace()
        if len(records) > 0:
            for r in records:
                if r.pin != uid and r.prefix_batch.startswith(prefix):
                    return -2
        records = self.searchResults({"%s" % self.key : uid})
        if len(records) > 1:
            # Can not happen, but anyway...
            raise ValueError("More than one record with uid %s" % uid)
        if len(records) == 0:
            return -1
        record = records[0]
        if record.student == "":
            record_data = {}
            for field in self.schema() + self.indexes():
                record_data[field] = getattr(record, field)
            # Add the updated data:
            record_data['student'] = student_id
            try:
                self.catalog_object(dict2ob(record_data), uid)
                return 1
            except ConflictError:
                return 2
        if record.student.upper() != student_id.upper():
            return 0
        if record.student.upper() == student_id.upper():
            return 2
        return -3

InitializeClass(PinTable)

###)

class PumeResultsTable(WAeUPTable): ###(

    meta_type = 'WAeUP PumeResults Tool'
    name = "pumeresults"
    key = "jamb_reg_no"
    def __init__(self):
        WAeUPTable.__init__(self, 'portal_pumeresults')


InitializeClass(PumeResultsTable)

###)

class StudentsCatalog(WAeUPTable): ###(
    security = ClassSecurityInfo()

    meta_type = 'WAeUP Students Catalog'
    name = "students_catalog"
    key = "id"
    interesting_types = ('Student',
                         'StudentApplication',
                         'StudentCLearance',
                         'StudentPersonal',
                         'StudentStudyCourse',
                         )
    def __init__(self):
        WAeUPTable.__init__(self, 'students_catalog')

        
        
    security.declarePrivate('notify_event_listener')
    def notify_event_listener(self,event_type,object,infos):
        "listen for events"
        pt = object.portal_type
        mt = object.meta_type
        students_catalog = self.students_catalog
        #if pt not in self.interesting_types:
        #    return
        #print "%(pt)s\n %(event_type)s \n %(infos)s\n" % vars()
        if not infos.has_key('rpath'):
            return
        if pt == 'Student' and event_type == "workflow":
            pass
        elif mt == 'StudentApplication':
            if event_type not in ('sys_modify_object'):
                return
            print "%(pt)s\n %(event_type)s \n %(infos)s\n" % vars()
            from pdb import set_trace;set_trace()
            jamb_reg_no = getattr(object,'jamb_reg_no',None)
            if jamb_reg_no is None:
                return
            student_id = infos['rpath'].split('/')[2]
            self.fixName(student_id)
            student_entry = students_catalog(id = student_id)[0]
            if student_entry.jamb_reg_no == jamb_reg_no:
                return
            students_catalog.modifyRecord(id = student_id,
                                          jamb_reg_no = jamb_reg_no)
        elif mt == 'StudentPersonal':
            if event_type not in ('sys_modify_object'):
                return
            print "%(pt)s\n %(event_type)s \n %(infos)s\n" % vars()
            student_id = infos['rpath'].split('/')[2]
            self.fixName(student_id)
            

InitializeClass(StudentsCatalog)

###)

class CoursesCatalog(WAeUPTable): ###(

    meta_type = 'WAeUP Courses Catalog'
    name = "students_catalog"
    key = "code"
    def __init__(self):
        WAeUPTable.__init__(self, 'courses_catalog')


InitializeClass(CoursesCatalog)
###)

class OnlinePaymentsImport(WAeUPTable): ###(

    meta_type = 'WAeUP Online Payment Transactions'
    name = "online_payments_import"
    key = "order_id"
    def __init__(self):
        WAeUPTable.__init__(self, self.name)


InitializeClass(CoursesCatalog)
###)

class ReturningImport(WAeUPTable): ###(

    meta_type = 'Returning Import Table'
    name = "returning_import"
    key = "matric_no"
    def __init__(self):
        WAeUPTable.__init__(self, 'returning_import')


InitializeClass(ReturningImport)
###)

class ResultsImport(WAeUPTable): ###(

    meta_type = 'Results Import Table'
    name = "results_import"
    key = "key"
    def __init__(self):
        WAeUPTable.__init__(self, 'results_import')


InitializeClass(ResultsImport)

###)

class PaymentsCatalog(WAeUPTable): ###(

    meta_type = 'WAeUP Payments Catalog'
    name = "students_catalog"
    key = "id"
    def __init__(self):
        WAeUPTable.__init__(self, 'payments_catalog')


InitializeClass(PaymentsCatalog)

###)

# BBB:
AccomodationTable = AccommodationTable
