## $Id: pdf.py 8059 2012-04-07 08:15:16Z 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
##
"""
Generate PDF docs for applicants.
"""
import grok
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import cm
from reportlab.platypus import Paragraph, Image, Table, Spacer
from zope.component import getUtility
from zope.formlib.form import setUpEditWidgets
from zope.i18n import translate
from zope.publisher.browser import TestRequest
from waeup.kofa.applicants.interfaces import IApplicant, IApplicantsUtils
from waeup.kofa.browser import DEFAULT_PASSPORT_IMAGE_PATH
from waeup.kofa.browser.interfaces import IPDFCreator
from waeup.kofa.interfaces import IExtFileStore, IPDF, IKofaUtils
from waeup.kofa.interfaces import MessageFactory as _
from waeup.kofa.widgets.datewidget import FriendlyDateDisplayWidget

class PDFApplicationSlip(grok.Adapter):
    """Create a PDF application slip for applicants.
    """
    # XXX: Many things in here are reusable. We might want to split
    # things. Possibly move parts to IPDFCreator?
    grok.context(IApplicant)
    grok.implements(IPDF)
    grok.name('application_slip')

    form_fields =  grok.AutoFields(IApplicant).omit(
        'locked', 'course_admitted')
    form_fields['date_of_birth'].custom_widget = FriendlyDateDisplayWidget('le')

    @property
    def title(self):
        container_title = self.context.__parent__.title
        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
        ar_translation = translate(_('Application Record'),
            'waeup.kofa', target_language=portal_language)
        return '%s - %s %s' % (container_title,
            ar_translation, self.context.application_number)

    def _setUpWidgets(self):
        """Setup simple display widgets.

        Returns the list of widgets.
        """
        request = TestRequest()
        return setUpEditWidgets(
            self.form_fields, 'form', self.context, request, {},
            for_display=True, ignore_request=True
            )

    def _getCourseAdmittedLink(self, view):
        """Return link, title and code in html format to the certificate
           admitted.
        """
        course_admitted = self.context.course_admitted
        if view is not None and getattr(course_admitted, '__parent__',None):
            url = view.url(course_admitted)
            title = course_admitted.title
            code = course_admitted.code
            return '<a href="%s">%s - %s</a>' %(url,code,title)
        return ''

    def _addPassportImage(self, data):
        """Add passport image to data stream.

        If no image exists yet the default image is added.
        """
        img = getUtility(IExtFileStore).getFileByContext(self.context)
        if img is None:
            img = open(DEFAULT_PASSPORT_IMAGE_PATH, 'rb')
        doc_img = Image(img.name, width=4*cm, height=3*cm, kind='bound')
        data.append([doc_img])
        data.append([Spacer(1, 18)])
        return data

    def _addDeptAndFaculty(self, data):
        """If we have a valid course admitted, add dept. and faculty to data
           stream.
        """
        style = getSampleStyleSheet()
        course_admitted = self.context.course_admitted
        dept = getattr(
                getattr(course_admitted, '__parent__', None),
                '__parent__', None)
        if dept is None:
            return data
        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
        dp_translation = translate(_('Department:'),
            'waeup.kofa', target_language=portal_language)
        f_label = '<font size=12>%s</font>' % dp_translation
        f_text = '<font size=12>%s</font>' % dept.longtitle()
        f_label = Paragraph(f_label, style["Normal"])
        f_text = Paragraph(f_text, style["Normal"])
        data.append([f_label,f_text])

        faculty = getattr(dept, '__parent__', None)
        if faculty is None:
            return data
        fc_translation = translate(_('Faculty:'),
            'waeup.kofa', target_language=portal_language)
        f_label = '<font size=12>%s</font>' % fc_translation
        f_text = '<font size=12>%s</font>' % faculty.longtitle()
        f_label = Paragraph(f_label, style["Normal"])
        f_text = Paragraph(f_text, style["Normal"])
        data.append([f_label,f_text])
        return data

    def _getWidgetsTable(self, view):
        """Return a reportlab table buildt of widgets.
        """
        style = getSampleStyleSheet()
        table_data = []
        table_style = [('LEFTPADDING', (0,0), (0,-1), 0),
                       ('VALIGN', (0,0), (-1,-1), 'TOP'),
                       ]
        row_num = 0
        widgets = self._setUpWidgets()
        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
        for widget in widgets:
            separators = getUtility(IApplicantsUtils).SEPARATORS_DICT
            if separators and separators.get(widget.name):
                f_headline = ('<font size=12><strong>%s</strong></font>'
                    % translate(separators[widget.name], 'waeup.kofa',
                    target_language=portal_language))
                f_headline = Paragraph(f_headline, style["Normal"])
                table_data.append([f_headline ])
                table_style.append(('SPAN', (0,row_num), (-1,row_num)),)
                table_style.append(
                    ('TOPPADDING', (0,row_num), (-1,row_num), 12),)
                row_num += 1
            f_label = '<font size=12>%s</font>:' % translate(
                widget.label.strip(), 'waeup.kofa',
                target_language=portal_language)
            f_label = Paragraph(f_label, style["Normal"])
            f_text = '<font size=12>%s</font>' % widget()
            # Add br tag if widgets contain div tags
            # which are not supported by reportlab
            f_text = f_text.replace('</div>', '</div><br />')
            f_text = f_text.replace('\n', '')
            f_text = Paragraph(f_text, style["Normal"])
            table_data.append([f_label,f_text])
            row_num += 1
        adm_translation = translate(_('Admitted Course of Study:'),
                'waeup.kofa', target_language=portal_language)
        f_label = '<font size=12>%s</font>' % adm_translation
        f_text = '<font size=12>%s</font>' % (
            self._getCourseAdmittedLink(view),)
        f_label = Paragraph(f_label, style["Normal"])
        f_text = Paragraph(f_text, style["Normal"])
        table_data.append([f_label,f_text])
        row_num += 1

        # Add dept. and faculty if applicable
        table_data = self._addDeptAndFaculty(table_data)

        # Create table
        table = Table(table_data,style=table_style)
        table.hAlign = 'LEFT'
        return table

    def _addComments(self, data):
        style = getSampleStyleSheet()
        if self.context.state == 'created':
            comment1 = _(
                '<font size=10>Proceed to the login page of the portal' +
                ' and enter your new credentials:' +
                ' user name= ${a}, password = ${b}.</font>', mapping = {
                    'a':self.context.student_id,
                    'b':self.context.application_number}
                )
            comment2 = _(
                '<font size=10>Change your password when you have ' +
                ' logged in.</font>'
                )
            comment1 = Paragraph(comment1, style["Normal"])
            comment2 = Paragraph(comment2, style["Normal"])
            data.extend([Spacer(1, 18), comment1, comment2])
        return data

    def __call__(self, view=None):
        """Return a PDF representation of the context applicant.

        If no `view` is given, the course admitted field will be an
        empty string and author will be set as ``'unknown'``.

        If a `view` is given, author will be set as the calling
        principal.
        """
        doc_title = self.title.replace('-', '\n')
        style = getSampleStyleSheet()
        data = []

        # append history
        for msg in self.context.history.messages:
            f_msg = '<font face="Courier" size=10>%s</font>' % msg
            data.append(Paragraph(f_msg, style["Normal"]))
        data.append(Spacer(1, 20))

        # append photograph
        img_path = getattr(
            getUtility(IExtFileStore).getFileByContext(self.context),
            'name', DEFAULT_PASSPORT_IMAGE_PATH)
        doc_img = Image(img_path, width=4*cm, height=3*cm, kind='bound')
        doc_img.hAlign='LEFT'
        data.append(doc_img)

        # append widgets
        data.append(self._getWidgetsTable(view))

        # append comments
        data = self._addComments(data)

        creator = getUtility(IPDFCreator)
        return creator.create_pdf(data, None, doc_title)
