"""Batch processing components for academics objects.

Batch processors eat CSV files to add, update or remove large numbers
of certain kinds of objects at once.

Here we define the processors for academics specific objects like
faculties, departments and the like.
"""
import grok
from zope.interface import Interface
from waeup.sirp.interfaces import IBatchProcessor
from waeup.sirp.university.interfaces import (
    IFacultyContainer, IFaculty, ICourse, IDepartment, ICertificate,
    ICertificateCourse)
from waeup.sirp.utils.batching import BatchProcessor

class FacultyProcessor(BatchProcessor):
    """A batch processor for IFaculty objects.
    """
    grok.provides(IBatchProcessor)
    grok.context(Interface)
    util_name = 'facultyimporter'
    grok.name(util_name)

    name = u'Faculty importer'
    iface = IFaculty

    location_fields = ['code',]
    factory_name = 'waeup.Faculty'

    def parentsExist(self, row, site):
        return 'faculties' in site.keys()

    def entryExists(self, row, site):
        return row['code'] in site['faculties'].keys()

    def getParent(self, row, site):
        return site['faculties']

    def getEntry(self, row, site):
        if not self.entryExists(row, site):
            return None
        parent = self.getParent(row, site)
        return parent.get(row['code'])
    
    def addEntry(self, obj, row, site):
        parent = self.getParent(row, site)
        parent.addFaculty(obj)
        return

    def delEntry(self, row, site):
        parent = self.getParent(row, site)
        del parent[row['code']]
        pass

class DepartmentProcessor(BatchProcessor):
    """A batch processor for IDepartment objects.
    """
    grok.provides(IBatchProcessor)
    grok.context(Interface)
    util_name = 'departmentimporter'
    grok.name(util_name)

    name = u'Department importer'
    iface = IDepartment

    location_fields = ['code', 'faculty_code']
    factory_name = 'waeup.Department'

    def parentsExist(self, row, site):
        if not 'faculties' in site.keys():
            return False
        return row['faculty_code'] in site['faculties']

    def entryExists(self, row, site):
        if not self.parentsExist(row, site):
            return False
        parent = self.getParent(row, site)
        return row['code'] in parent.keys()

    def getParent(self, row, site):
        return site['faculties'][row['faculty_code']]

    def getEntry(self, row, site):
        if not self.entryExists(row, site):
            return None
        parent = self.getParent(row, site)
        return parent.get(row['code'])
    
    def addEntry(self, obj, row, site):
        parent = self.getParent(row, site)
        parent.addDepartment(obj)
        return

    def delEntry(self, row, site):
        parent = self.getParent(row, site)
        del parent[row['code']]
        return

class CourseProcessor(BatchProcessor):
    """A batch processor for ICourse objects.
    """
    grok.provides(IBatchProcessor)
    grok.context(Interface)
    util_name = 'courseimporter'
    grok.name(util_name)

    name = u'Course importer'
    iface = ICourse

    location_fields = ['code', 'faculty_code', 'department_code']
    factory_name = 'waeup.Course'

    def parentsExist(self, row, site):
        if not 'faculties' in site.keys():
            return False
        if not row['faculty_code'] in site['faculties'].keys():
            return False
        faculty = site['faculties'][row['faculty_code']]
        return row['department_code'] in faculty.keys()

    def entryExists(self, row, site):
        if not self.parentsExist(row, site):
            return False
        parent = self.getParent(row, site)
        return row['code'] in parent.keys()

    def getParent(self, row, site):
        dept = site['faculties'][row['faculty_code']][row['department_code']]
        return dept.courses

    def getEntry(self, row, site):
        if not self.entryExists(row, site):
            return None
        parent = self.getParent(row, site)
        return parent.get(row['code'])
    
    def addEntry(self, obj, row, site):
        parent = self.getParent(row, site)
        parent.addCourse(obj)
        return

    def delEntry(self, row, site):
        parent = self.getParent(row, site)
        del parent[row['code']]
        return

class CertificateProcessor(BatchProcessor):
    """A batch processor for ICertificate objects.
    """
    grok.provides(IBatchProcessor)
    grok.context(Interface)
    util_name = 'certificateimporter'
    grok.name(util_name)

    name = u'Certificate importer'
    iface = ICertificate

    location_fields = ['code', 'faculty_code', 'department_code']
    factory_name = 'waeup.Certificate'

    def parentsExist(self, row, site):
        if not 'faculties' in site.keys():
            return False
        if not row['faculty_code'] in site['faculties'].keys():
            return False
        faculty = site['faculties'][row['faculty_code']]
        return row['department_code'] in faculty.keys()

    def entryExists(self, row, site):
        if not self.parentsExist(row, site):
            return False
        parent = self.getParent(row, site)
        return row['code'] in parent.keys()

    def getParent(self, row, site):
        dept = site['faculties'][row['faculty_code']][row['department_code']]
        return dept.certificates

    def getEntry(self, row, site):
        if not self.entryExists(row, site):
            return None
        parent = self.getParent(row, site)
        return parent.get(row['code'])

    def addEntry(self, obj, row, site):
        parent = self.getParent(row, site)
        parent.addCertificate(obj)
        return

    def delEntry(self, row, site):
        parent = self.getParent(row, site)
        del parent[row['code']]
        return

class CertificateCourseProcessor(BatchProcessor):
    """A batch processor for ICertificateCourse objects.
    """
    grok.provides(IBatchProcessor)
    grok.context(Interface)
    util_name = 'certificatecourseimporter'
    grok.name(util_name)

    name = u'CertificateCourse importer'
    iface = ICertificateCourse

    location_fields = ['course', 'level', 'faculty_code', 'department_code',
                       'certificate_code',]
    factory_name = 'waeup.CertificateCourse'

    def parentsExist(self, row, site):
        if not 'faculties' in site.keys():
            return False
        if not row['faculty_code'] in site['faculties'].keys():
            return False
        faculty = site['faculties'][row['faculty_code']]
        if not row['department_code'] in faculty.keys():
            return False
        dept = faculty[row['department_code']]
        return row['certificate_code'] in dept.certificates.keys()

    def entryExists(self, row, site):
        if not self.parentsExist(row, site):
            return False
        parent = self.getParent(row, site)
        code = "%s_%s" % (row['course'].code, row['level'])
        return code in parent.keys()

    def getParent(self, row, site):
        dept = site['faculties'][row['faculty_code']][row['department_code']]
        return dept.certificates[row['certificate_code']]

    def getEntry(self, row, site):
        if not self.entryExists(row, site):
            return None
        parent = self.getParent(row, site)
        return parent.get(row['course'])

    def addEntry(self, obj, row, site):
        parent = self.getParent(row, site)
        parent.addCourseRef(row['course'],
                            row['level'], row['core_or_elective'])
        return

    def delEntry(self, row, site):
        parent = self.getParent(row, site)
        parent.delCourseRef(row['course'].code, row['level'])
        return
