## $Id: webservices.py 10044 2013-03-22 12:59:13Z henrik $
##
## Copyright (C) 2012 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
##

import grok
import xmlrpclib
from zope.component import getUtility, queryUtility
from zope.catalog.interfaces import ICatalog
from waeup.kofa.interfaces import IUniversity, IExtFileStore
    

def get_student(students, identifier):
    if identifier is None:
        return None
    student = students.get(identifier, None)
    if student is None:
        cat = queryUtility(ICatalog, name='students_catalog')
        results = list(
            cat.searchResults(matric_number=(identifier, identifier)))
        if len(results) == 1:
            student = results[0]
        else:
            results = list(
                cat.searchResults(reg_number=(identifier, identifier)))
            if len(results) == 1:
                student = results[0]
    return student

#class XMLRPCPermission(grok.Permission):
#    """Permission for using XMLRPC functions.
#    """
#    grok.name('waeup.xmlrpc')

#class XMLRPCUsers2(grok.Role):
#    """Usergroup 2
#    """
#    grok.name('waeup.xmlrpcusers2')
#    grok.title('XMLRPC Users Group 2')
#    grok.permissions('waeup.xmlrpc',)

class StudentsXMLRPC(grok.XMLRPC):
    """Student related XMLRPC webservices.

    Please note, that XMLRPC does not support real keyword arguments
    but positional arguments only.
    """

    grok.context(IUniversity)

    @grok.require('waeup.xmlrpc')
    def get_student_id(self, reg_number=None):
        """Get the id of a student with registration number `reg_number`.

        Returns the student id as string if successful, ``None`` else.
        """
        if reg_number is not None:
            cat = getUtility(ICatalog, name='students_catalog')
            result = list(
                cat.searchResults(reg_number=(reg_number, reg_number),
                                  _limit=1))
            if not len(result):
                return None
            return result[0].student_id
        return None

    @grok.require('waeup.xmlrpc')
    def get_courses_by_session(self, identifier=None, session=None):
        """1. What COURSES are registered by student X in session Y?

        """
        students = self.context['students']
        student = get_student(students, identifier)
        if student is None:
            return None
        try:
            session = int(session)
        except (TypeError, ValueError):
            pass
        sessionsearch = True
        if session in (None, ''):
            sessionsearch = False
        studycourse = student['studycourse']
        coursetickets = {}
        for level in studycourse.values():
            if sessionsearch and level.level_session != session:
                continue
            for ct in level.values():
                coursetickets.update(
                    {"%s|%s" % (level.level, ct.code): ct.title})
        if not coursetickets:
            return None
        return coursetickets

    @grok.require('waeup.xmlrpc')
    def get_students_by_course(self, course=None, session=None):
        """2. What STUDENTS registered (student id / matric no)
        for course Z in session Y and did they pay school fee?

        """
        try:
            session = int(session)
        except (TypeError, ValueError):
            pass
        sessionsearch = True
        if session in (None, ''):
            sessionsearch = False
        cat = queryUtility(ICatalog, name='coursetickets_catalog')
        if sessionsearch:
            coursetickets = cat.searchResults(
                session=(session, session),
                code=(course, course))
        else:
            coursetickets = cat.searchResults(
                code=(course, course))
        if not coursetickets:
            return None
        hitlist = []
        for c_ticket in coursetickets:
            amount = 0
            for p_ticket in c_ticket.student['payments'].values():
                if p_ticket.p_state == 'paid' and \
                    p_ticket.p_category == 'schoolfee' and \
                    p_ticket.p_session == c_ticket.__parent__.level_session:
                    amount = p_ticket.amount_auth
            hitlist.append((
                c_ticket.student.student_id,
                c_ticket.student.matric_number,
                c_ticket.__parent__.validated_by,
                amount
                ))
        return list(set(hitlist))

    @grok.require('waeup.xmlrpc')
    def get_student_info(self, identifier=None):
        """3a. Who is the student with matriculation number / student id

        """
        students = self.context['students']
        student = get_student(students, identifier)
        if student is None:
            return None
        return [student.display_fullname, student.certcode,
            student.phone, student.email]

    @grok.require('waeup.xmlrpc')
    def get_student_passport(self, identifier=None):
        """3b. Get passport picture of student with
        matriculation number / student id.

        """
        students = self.context['students']
        student = get_student(students, identifier)
        if student is None:
            return None
        img = getUtility(IExtFileStore).getFileByContext(
            student, attr='passport.jpg')
        return xmlrpclib.Binary(img.read())

    @grok.require('waeup.xmlrpc')
    def get_paid_sessions(self, identifier=None):
        """6. Get list of SESSIONS school fees paid by student X.

        """
        students = self.context['students']
        student = get_student(students, identifier)
        if student is None:
            return None
        payments_dict = {}
        for ticket in student['payments'].values():
            if ticket.p_state == 'paid' and \
                ticket.p_category == 'schoolfee':
                payments_dict[str(ticket.p_session)] = ticket.amount_auth
        if not payments_dict:
            return None
        return payments_dict
