## $Id: export.py 8393 2012-05-09 11:31:01Z uli $
##
## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## 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
##
"""Exporters for student related stuff.
"""
import grok
from zope.catalog.interfaces import ICatalog
from zope.component import queryUtility
from waeup.kofa.interfaces import ICSVExporter
from waeup.kofa.interfaces import MessageFactory as _
from waeup.kofa.students.interfaces import (
    IStudent, IStudentStudyCourse, IStudentStudyLevel, ICourseTicket,
    IStudentOnlinePayment)
from waeup.kofa.utils.batching import ExporterBase
from waeup.kofa.utils.helpers import iface_names

class StudentsExporter(grok.GlobalUtility, ExporterBase):
    """Exporter for Students.
    """
    grok.implements(ICSVExporter)
    grok.name('students')

    #: Fieldnames considered by this exporter
    fields = tuple(sorted(iface_names(IStudent, omit=['loggerInfo'])))

    #: The title under which this exporter will be displayed
    title = _(u'Students')

    def export(self, students, filepath=None):
        """Export `students`, an iterable, as CSV file.

        If `filepath` is ``None``, a raw string with CSV data is returned.
        """
        writer, outfile = self.get_csv_writer(filepath)
        for student in students:
            self.write_item(student, writer)
        return self.close_outfile(filepath, outfile)

    def export_all(self, site, filepath=None):
        """Export students into filepath as CSV data.

        If `filepath` is ``None``, a raw string with CSV data is returned.
        """
        catalog = queryUtility(
            ICatalog, context=site, name='students_catalog', default=None)
        if catalog is None:
            return self.export([], filepath)
        students = catalog.searchResults(
            student_id=(None, None))
        return self.export(students, filepath)

class StudentStudyCourseExporter(grok.GlobalUtility, ExporterBase):
    """Exporter for StudentStudyCourses.
    """
    grok.implements(ICSVExporter)
    grok.name('studentstudycourses')

    #: Fieldnames considered by this exporter
    fields = tuple(sorted(iface_names(IStudentStudyCourse)))

    #: The title under which this exporter will be displayed
    title = _(u'Student Study Courses')

    def mangle_value(self, value, name, context=None):
        """Add the hash symbol at the end of date_of_birth.

        This is to avoid annoying automatic date transformation
        by Excel or Calc.
        """
        if name == 'certificate' and value is not None:
            # XXX: hopefully cert codes are unique site-wide
            value = value.code
        return super(
            StudentStudyCourseExporter, self).mangle_value(
            value, name, context=context)


    def export(self, study_courses, filepath=None):
        """Export `study_courses`, an iterable, as CSV file.

        If `filepath` is ``None``, a raw string with CSV data is returned.
        """
        writer, outfile = self.get_csv_writer(filepath)
        for study_course in study_courses:
            self.write_item(study_course, writer)
        return self.close_outfile(filepath, outfile)

    def export_all(self, site, filepath=None):
        """Export study courses into filepath as CSV data.

        If `filepath` is ``None``, a raw string with CSV data is returned.
        """
        catalog = queryUtility(
            ICatalog, context=site, name='students_catalog', default=None)
        if catalog is None:
            return self.export([], filepath)
        students = catalog.searchResults(
            student_id=(None, None))
        study_courses = [x.get('studycourse', None) for x in students
                         if x is not None]
        return self.export(study_courses, filepath)

class StudentStudyLevelExporter(grok.GlobalUtility, ExporterBase):
    """Exporter for StudentStudyLevels.
    """
    grok.implements(ICSVExporter)
    grok.name('studentstudylevels')

    #: Fieldnames considered by this exporter
    fields = tuple(sorted(iface_names(IStudentStudyLevel) + [
        'reg_number', 'matric_number', 'level']))

    #: The title under which this exporter will be displayed
    title = _(u'Student Study Levels')

    def mangle_value(self, value, name, context=None):
        """Add the hash symbol at the end of date_of_birth.

        This is to avoid annoying automatic date transformation
        by Excel or Calc.
        """

        if name == 'reg_number' and context is not None:
            value = getattr(
                getattr(getattr(context, '__parent__', None),
                        '__parent__', None), 'reg_number', None)
        if name == 'matric_number' and context is not None:
            value = getattr(
                getattr(getattr(context, '__parent__', None),
                        '__parent__', None), 'matric_number', None)
        return super(
            StudentStudyLevelExporter, self).mangle_value(
            value, name, context=context)

    def export(self, study_levels, filepath=None):
        """Export `study_levels`, an iterable, as CSV file.

        If `filepath` is ``None``, a raw string with CSV data is returned.
        """
        writer, outfile = self.get_csv_writer(filepath)
        for study_level in study_levels:
            self.write_item(study_level, writer)
        return self.close_outfile(filepath, outfile)

    def export_all(self, site, filepath=None):
        """Export study levels into filepath as CSV data.

        If `filepath` is ``None``, a raw string with CSV data is returned.
        """
        catalog = queryUtility(
            ICatalog, context=site, name='students_catalog', default=None)
        if catalog is None:
            return self.export([], filepath)
        students = catalog.searchResults(
            student_id=(None, None))
        levels = []
        study_courses = [x.get('studycourse', None) for x in students
                         if x is not None]
        for course in study_courses:
            for level in course.values():
                levels.append(level)
        return self.export(levels, filepath)

class CourseTicketExporter(grok.GlobalUtility, ExporterBase):
    """Exporter for CourseTickets.
    """
    grok.implements(ICSVExporter)
    grok.name('coursetickets')

    #: Fieldnames considered by this exporter
    fields = tuple(sorted(iface_names(ICourseTicket) + [
        'reg_number', 'matric_number', 'level', 'code', 'title', 'credits',
        'passmark', 'semester', 'fcode', 'dcode']))

    #: The title under which this exporter will be displayed
    title = _(u'Course Tickets')

    def mangle_value(self, value, name, context=None):
        """Treat location values special.
        """
        if context is not None:
            student = context.getStudent()
            if name in ['reg_number', 'matric_number'] and student is not None:
                value = getattr(student, name, None)
            if name == 'level':
                value = getattr(context, 'getLevel', lambda: None)()
        return super(
            CourseTicketExporter, self).mangle_value(
            value, name, context=context)

    def export(self, course_tickets, filepath=None):
        """Export `course_tickets`, an iterable, as CSV file.

        If `filepath` is ``None``, a raw string with CSV data is returned.
        """
        writer, outfile = self.get_csv_writer(filepath)
        for ticket in course_tickets:
            self.write_item(ticket, writer)
        return self.close_outfile(filepath, outfile)

    def export_all(self, site, filepath=None):
        """Export course tickets into filepath as CSV data.

        If `filepath` is ``None``, a raw string with CSV data is returned.
        """
        catalog = queryUtility(
            ICatalog, context=site, name='students_catalog', default=None)
        if catalog is None:
            return self.export([], filepath)
        students = catalog.searchResults(
            student_id=(None, None))
        levels = []
        study_courses = [x.get('studycourse', None) for x in students
                         if x is not None]
        for course in study_courses:
            for level in course.values():
                levels.append(level)

        tickets = []
        for level in levels:
            for ticket in level.values():
                tickets.append(ticket)
        return self.export(tickets, filepath)

class PaymentsExporter(grok.GlobalUtility, ExporterBase):
    """Exporter for OnlinePayment instances.
    """
    grok.implements(ICSVExporter)
    grok.name('studentpayments')

    #: Fieldnames considered by this exporter
    fields = tuple(
        sorted(['reg_number', 'matric_number'] +
               iface_names(IStudentOnlinePayment, exclude_attribs=False)))

    #: The title under which this exporter will be displayed
    title = _(u'Course Tickets')

    def mangle_value(self, value, name, context=None):
        """Treat location values special.
        """
        if context is not None:
            student = context.getStudent()
            if name in ['reg_number', 'matric_number'] and student is not None:
                value = getattr(student, name, None)
        return super(
            PaymentsExporter, self).mangle_value(
            value, name, context=context)

    def export(self, payments, filepath=None):
        """Export `payments`, an iterable, as CSV file.

        If `filepath` is ``None``, a raw string with CSV data is returned.
        """
        writer, outfile = self.get_csv_writer(filepath)
        for payment in payments:
            self.write_item(payment, writer)
        return self.close_outfile(filepath, outfile)

    def export_all(self, site, filepath=None):
        """Export payments into filepath as CSV data.

        If `filepath` is ``None``, a raw string with CSV data is returned.
        """
        catalog = queryUtility(
            ICatalog, context=site, name='students_catalog', default=None)
        if catalog is None:
            return self.export([], filepath)
        students = catalog.searchResults(
            student_id=(None, None))
        payments = []
        for student in students:
            if not 'payments' in student.keys():
                continue
            for payment in student['payments'].values():
                payments.append(payment)
        return self.export(payments, filepath)
