## $Id: browser.py 10382 2013-06-25 12:46:38Z 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
##
"""UI components for basic applicants and related components.
"""
import grok
import os
from zope.component import getUtility
from waeup.kofa.interfaces import (
    IExtFileStore, IFileStoreNameChooser)
from zope.formlib.textwidgets import BytesDisplayWidget
from hurry.workflow.interfaces import IWorkflowState
from waeup.kofa.utils.helpers import string_from_bytes, file_size
from waeup.imostate.applicants.interfaces import (
    ICustomApplicant,
    ICustomUGApplicant,
    ICustomUGApplicantEdit,
    )
from waeup.imostate.interfaces import MessageFactory as _
from kofacustom.nigeria.applicants.browser import (
    NigeriaApplicantDisplayFormPage,
    NigeriaApplicantManageFormPage,
    NigeriaApplicantEditFormPage,
    NigeriaPDFApplicationSlip,
    UG_OMIT_DISPLAY_FIELDS,
    UG_OMIT_PDF_FIELDS,
    UG_OMIT_MANAGE_FIELDS,
    UG_OMIT_EDIT_FIELDS,
    )

UG_OMIT_DISPLAY_FIELDS += ('course2',)
UG_OMIT_PDF_FIELDS += ('course2',)
UG_OMIT_MANAGE_FIELDS += ('course2',)
UG_OMIT_EDIT_FIELDS += ('course2',)

from waeup.imostate.applicants.workflow import STARTED

MAX_FILE_UPLOAD_SIZE = 1024 * 500

def handle_file_upload(upload, context, view, attr=None):
    """Handle upload of applicant files.

    Returns `True` in case of success or `False`.

    Please note that file pointer passed in (`upload`) most probably
    points to end of file when leaving this function.
    """
    size = file_size(upload)
    if size > MAX_FILE_UPLOAD_SIZE:
        view.flash(_('Uploaded file is too big!'))
        return False
    dummy, ext = os.path.splitext(upload.filename)
    ext.lower()
    if ext != '.pdf':
        view.flash(_('pdf file extension expected.'))
        return False
    upload.seek(0) # file pointer moved when determining size
    store = getUtility(IExtFileStore)
    file_id = IFileStoreNameChooser(context).chooseName(attr=attr)
    store.createFile(file_id, upload)
    return True

class CustomApplicantDisplayFormPage(NigeriaApplicantDisplayFormPage):
    """A display view for applicant data.
    """

    grok.template('applicantdisplaypage')

    @property
    def file_links(self):
        html = ''
        pdf = getUtility(IExtFileStore).getFileByContext(
            self.context, attr='extraform.pdf')
        if pdf:
            html += '<a href="extraform.pdf">Extra Applicant Information Form</a>, '
        pdf = getUtility(IExtFileStore).getFileByContext(
            self.context, attr='refereeform.pdf')
        if pdf:
            html += '<a href="refereeform.pdf">Referee\'s Form</a>, '
        pdf = getUtility(IExtFileStore).getFileByContext(
            self.context, attr='credentials.pdf')
        if pdf:
            html += '<a href="credentials.pdf">Credentials</a>'
        return html

    @property
    def form_fields(self):
        form_fields = grok.AutoFields(ICustomUGApplicant)
        for field in UG_OMIT_DISPLAY_FIELDS:
            form_fields = form_fields.omit(field)
        if form_fields.get('perm_address', None):
            form_fields['perm_address'].custom_widget = BytesDisplayWidget
        form_fields['notice'].custom_widget = BytesDisplayWidget
        if not getattr(self.context, 'student_id'):
            form_fields = form_fields.omit('student_id')
        if not getattr(self.context, 'screening_score'):
            form_fields = form_fields.omit('screening_score')
        if not getattr(self.context, 'screening_venue'):
            form_fields = form_fields.omit('screening_venue')
        if not getattr(self.context, 'screening_date'):
            form_fields = form_fields.omit('screening_date')
        return form_fields

    def update(self):
        super(CustomApplicantDisplayFormPage, self).update()
        self.extraform_url = self.url(self.context, 'extraform.pdf')
        self.referreeform_url = self.url(self.context, 'refereeform.pdf')
        self.credentials_url = self.url(self.context, 'credentials.pdf')
        return

class CustomPDFApplicationSlip(NigeriaPDFApplicationSlip):

    @property
    def form_fields(self):
        form_fields = grok.AutoFields(ICustomUGApplicant)
        for field in UG_OMIT_PDF_FIELDS:
            form_fields = form_fields.omit(field)
        if not getattr(self.context, 'student_id'):
            form_fields = form_fields.omit('student_id')
        if not getattr(self.context, 'screening_score'):
            form_fields = form_fields.omit('screening_score')
        if not getattr(self.context, 'screening_venue'):
            form_fields = form_fields.omit('screening_venue')
        if not getattr(self.context, 'screening_date'):
            form_fields = form_fields.omit('screening_date')
        return form_fields

class CustomApplicantManageFormPage(NigeriaApplicantManageFormPage):
    """A full edit view for applicant data.
    """
    grok.template('applicanteditpage')

    @property
    def form_fields(self):
        form_fields = grok.AutoFields(ICustomUGApplicant)
        for field in UG_OMIT_MANAGE_FIELDS:
            form_fields = form_fields.omit(field)
        form_fields['student_id'].for_display = True
        form_fields['applicant_id'].for_display = True
        return form_fields

    def update(self):
        super(CustomApplicantManageFormPage, self).update()
        upload_extraform = self.request.form.get('form.extraform', None)
        if upload_extraform:
            # We got a fresh extraform upload
            success = handle_file_upload(
                upload_extraform, self.context, self, attr='extraform.pdf')
            if success:
                self.context.writeLogMessage(self, 'saved: extraform')
            else:
                self.upload_success = False
        upload_refereeform = self.request.form.get('form.refereeform', None)
        if upload_refereeform:
            # We got a fresh refereeform upload
            success = handle_file_upload(
                upload_refereeform, self.context, self, attr='refereeform.pdf')
            if success:
                self.context.writeLogMessage(self, 'saved: refereeform')
            else:
                self.upload_success = False
        upload_credentials = self.request.form.get('form.credentials', None)
        if upload_credentials:
            # We got a fresh credentials upload
            success = handle_file_upload(
                upload_credentials, self.context, self, attr='credentials.pdf')
            if success:
                self.context.writeLogMessage(self, 'saved: credentials')
            else:
                self.upload_success = False
        self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE)
        return

class CustomApplicantEditFormPage(NigeriaApplicantEditFormPage):
    """An applicant-centered edit view for applicant data.
    """
    grok.template('applicanteditpage')
    submit_state = STARTED

    @property
    def form_fields(self):
        form_fields = grok.AutoFields(ICustomUGApplicantEdit)
        for field in UG_OMIT_EDIT_FIELDS:
            form_fields = form_fields.omit(field)
        form_fields['applicant_id'].for_display = True
        form_fields['reg_number'].for_display = True
        return form_fields

    @property
    def display_actions(self):
        state = IWorkflowState(self.context).getState()
        actions = [[],[]]
        if state == STARTED:
            actions = [[_('Save'), _('Final Submit')], []]
        return actions

    def dataNotComplete(self):
        store = getUtility(IExtFileStore)
        if not store.getFileByContext(self.context, attr=u'passport.jpg'):
            return _('No passport picture uploaded.')
        if not store.getFileByContext(self.context, attr=u'extraform.pdf'):
            return _('No extra information form pdf file uploaded.')
        #if not store.getFileByContext(self.context, attr=u'refereeform.pdf'):
        #    return _('No referee form pdf file uploaded.')
        #if self.target is not None and self.target.startswith('pg') \
        #    and not store.getFileByContext(self.context, attr=u'credentials.pdf'):
        #    return _('No credentials pdf file uploaded.')
        if not self.request.form.get('confirm_passport', False):
            return _('Passport picture confirmation box not ticked.')
        return False

    def update(self):
        if self.context.locked or (
            self.context.__parent__.expired and
            self.context.__parent__.strict_deadline):
            self.emit_lock_message()
            return
        super(CustomApplicantEditFormPage, self).update()
        upload_extraform = self.request.form.get('form.extraform', None)
        if upload_extraform:
            # We got a fresh extraform upload
            success = handle_file_upload(
                upload_extraform, self.context, self, attr='extraform.pdf')
            if not success:
                self.upload_success = False
        upload_refereeform = self.request.form.get('form.refereeform', None)
        if upload_refereeform:
            # We got a fresh refereeform upload
            success = handle_file_upload(
                upload_refereeform, self.context, self, attr='refereeform.pdf')
            if not success:
                self.upload_success = False
        upload_credentials = self.request.form.get('form.credentials', None)
        if upload_credentials:
            # We got a fresh credentials upload
            success = handle_file_upload(
                upload_credentials, self.context, self, attr='credentials.pdf')
            if not success:
                self.upload_success = False
        self.max_file_upload_size = string_from_bytes(MAX_FILE_UPLOAD_SIZE)
        return

class ExtraForm(grok.View):
    """Renders the pdf form extension for applicants.
    """
    grok.name('extraform.pdf')
    grok.context(ICustomApplicant)
    grok.require('waeup.viewApplication')

    def render(self):
        pdf = getUtility(IExtFileStore).getFileByContext(
            self.context, attr='extraform.pdf')
        self.response.setHeader('Content-Type', 'application/pdf')
        return pdf

class RefereeForm(grok.View):
    """Renders the pdf referee's form for applicants.
    """
    grok.name('refereeform.pdf')
    grok.context(ICustomApplicant)
    grok.require('waeup.viewApplication')

    def render(self):
        pdf = getUtility(IExtFileStore).getFileByContext(
            self.context, attr='refereeform.pdf')
        self.response.setHeader('Content-Type', 'application/pdf')
        return pdf

class Credentials(grok.View):
    """Renders the pdf credential's form for applicants.
    """
    grok.name('credentials.pdf')
    grok.context(ICustomApplicant)
    grok.require('waeup.viewApplication')

    def render(self):
        pdf = getUtility(IExtFileStore).getFileByContext(
            self.context, attr='credentials.pdf')
        self.response.setHeader('Content-Type', 'application/pdf')
        return pdf