## $Id: pdf.py 7438 2011-12-22 18:24:35Z henrik $
##
## 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 datetime import datetime
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import Frame, Paragraph, Image, Table, Spacer
from reportlab.platypus.tables import TableStyle
from zope.component import getUtility
from zope.formlib.form import setUpEditWidgets
from zope.publisher.browser import TestRequest
from waeup.sirp.applicants.interfaces import IApplicant
from waeup.sirp.browser import DEFAULT_PASSPORT_IMAGE_PATH
from waeup.sirp.interfaces import IExtFileStore, IPDF

SLIP_STYLE = TableStyle(
    [('VALIGN',(0,0),(-1,-1),'TOP')]
    )


class PDFApplicationSlip(grok.Adapter):

    grok.context(IApplicant)
    grok.implements(IPDF)
    grok.name('application_slip')

    form_fields =  grok.AutoFields(IApplicant).omit(
        'locked', 'course_admitted')

    @property
    def title(self):
        container_title = self.context.__parent__.title
        return '%s Application Record %s' % (
            container_title, 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
        f_label = '<font size=12>Department:</font>'
        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
        f_label = '<font size=12>Faculty:</font>'
        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 __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.
        """
        pdf = canvas.Canvas('application_slip.pdf',pagesize=A4)
        pdf.setTitle(self.title)
        pdf.setSubject('Application')
        if view is None:
            pdf.setAuthor('unknown')
        if view is not None:
            pdf.setAuthor('%s (%s)' % (view.request.principal.title,
                                      view.request.principal.id))
        pdf.setCreator('SIRP')
        width, height = A4
        style = getSampleStyleSheet()
        pdf.line(1*cm,height-(1.8*cm),width-(1*cm),height-(1.8*cm))

        story = []
        frame_header = Frame(1*cm,1*cm,width-(1.7*cm),height-(1.7*cm))
        header_title = getattr(grok.getSite(), 'name', u'Sample University')
        story.append(Paragraph(header_title, style["Heading1"]))
        frame_header.addFromList(story,pdf)

        story = []
        frame_body = Frame(1*cm,1*cm,width-(2*cm),height-(3.5*cm))
        story.append(Paragraph(self.title, style["Heading2"]))
        story.append(Spacer(1, 18))
        for msg in self.context.history.messages:
            f_msg = '<font face="Courier" size=10>%s</font>' % msg
            story.append(Paragraph(f_msg, style["Normal"]))
        story.append(Spacer(1, 24))

        # Setup table data
        data = []
        # Insert passport photograph
        data = self._addPassportImage(data)
        # Render widget fields
        widgets = self._setUpWidgets()
        for widget in widgets: # self.widgets:
            f_label = '<font size=12>%s</font>:' % widget.label.strip()
            f_label = Paragraph(f_label, style["Normal"])
            f_text = '<font size=12>%s</font>' % widget()
            f_text = Paragraph(f_text, style["Normal"])
            data.append([f_label,f_text])
        f_label = '<font size=12>Admitted Course of Study:</font>'
        f_text = '<font size=12>%s</font>' % (
            self._getCourseAdmittedLink(view),)
        f_label = Paragraph(f_label, style["Normal"])
        f_text = Paragraph(f_text, style["Normal"])
        data.append([f_label,f_text])

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

        # Create table
        table = Table(data,style=SLIP_STYLE)
        story.append(table)

        # Add some comments
        if self.context.state == 'created':
            comment1 = (
                '<font size=10>Proceed to the login page of the portal' +
                ' and enter your new credentials:' +
                ' user name= %s, password = %s.</font>' %
                (self.context.student_id, 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"])
            story.append(Spacer(1, 18))
            story.append(comment1)
            story.append(comment2)

        frame_body.addFromList(story,pdf)

        story = []
        frame_footer = Frame(1*cm,0,width-(2*cm),1*cm)
        timestamp = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
        f_text = '<font size=10>%s</font>' % timestamp
        story.append(Paragraph(f_text, style["Normal"]))
        frame_footer.addFromList(story,pdf)
        return pdf.getpdfdata()
