##
## browser.py
## Login : <uli@pu.smp.net>
## Started on  Sun Jun 27 11:03:10 2010 Uli Fouquet
## $Id$
## 
## Copyright (C) 2010 Uli Fouquet
## 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

from datetime import datetime
from hurry.jquery import jquery
from hurry.jqueryui import jqueryui
from zope.component import getUtility, getAllUtilitiesRegisteredFor
from zope.formlib.widgets import FileWidget, DateWidget
from waeup.sirp.browser import (
    WAeUPPage, WAeUPEditFormPage, WAeUPAddFormPage,
    WAeUPDisplayFormPage, NullValidator)
from waeup.sirp.browser.pages import LoginPage
from waeup.sirp.interfaces import IWAeUPObject
from waeup.sirp.browser.resources import datepicker
from waeup.sirp.browser.viewlets import (
    AddActionButton, ManageActionButton, PrimaryNavTab,
    )
from waeup.sirp.browser.breadcrumbs import Breadcrumb
from waeup.sirp.applicants import get_applicant_data, ResultEntry
from waeup.sirp.applicants.interfaces import (
    IApplicant, IApplicantPrincipal, IApplicantPDEEditData,
    IApplicantsRoot, IApplicantsContainer, IApplicantsContainerProvider,
    )
from waeup.sirp.widgets.passportwidget import (
    PassportWidget, PassportDisplayWidget
    )
#from zope.formlib.objectwidget import ObjectWidget
from zope.formlib.sequencewidget import ListSequenceWidget, SequenceDisplayWidget
from zope.formlib.widget import CustomWidgetFactory
from waeup.sirp.utils.helpers import ReST2HTML
from waeup.sirp.widgets.objectwidget import (
    WAeUPObjectWidget, WAeUPObjectDisplayWidget)
from waeup.sirp.widgets.multilistwidget import (
    MultiListWidget, MultiListDisplayWidget)
from waeup.sirp.image.browser.widget import (
    ThumbnailWidget, EncodingImageFileWidget,
    )

results_widget = CustomWidgetFactory(
    WAeUPObjectWidget, ResultEntry)

results_display_widget = CustomWidgetFactory(
    WAeUPObjectDisplayWidget, ResultEntry)

#list_results_widget = CustomWidgetFactory(
#    ListSequenceWidget, subwidget=results_widget)

list_results_widget = CustomWidgetFactory(
    MultiListWidget, subwidget=results_widget)

list_results_display_widget = CustomWidgetFactory(
    MultiListDisplayWidget, subwidget=results_display_widget)

#: A date widget that renders with CSS class `datepicker` thus
#  enabling : the jQuery datepicker for this field if the form loaded
#  the jQuery code.
FriendlyDateWidget = CustomWidgetFactory(
    DateWidget, cssClass='datepicker')

class ApplicationsPage(WAeUPPage):
    grok.context(IApplicantsRoot)
    grok.name('index')
    title = 'Applicants'
    pnav = 3
    
    def getApplications(self):
        """Get a list of all stored applicant containers.
        """
        for key, val in self.context.items():
            url = self.url(val)
            yield(dict(url=url, name=key, container=val))

class ManageApplicantsRootActionButton(ManageActionButton):
    grok.context(IApplicantsRoot)
    grok.view(ApplicationsPage)
    text = 'Manage applicant containers'

class ApplicantsRootEditPage(WAeUPPage):
    grok.context(IApplicantsRoot)
    grok.name('manage')
    grok.template('applicantsrooteditpage')
    title = 'Edit applicants containers'
    pnav = 3

    def update(self, entries=None, DELETE=None, CANCEL=None):
        if CANCEL is not None:
            self.redirect(self.url(self.context))
            return
        if DELETE is None:
            return
        if entries is None:
            return
        if not isinstance(entries, list):
            entries = [entries]
        for name in entries:
            del self.context[name]
            self.flash('Deleted "%s"' % name)
        return

    def getApplications(self):
        """Get a list of all stored applicant containers.
        """
        for key, val in self.context.items():
            url = self.url(val)
            yield(dict(url=url, name=key))

class AddApplicantsContainerActionButton(AddActionButton):
    grok.context(IApplicantsRoot)
    grok.view(ApplicantsRootEditPage)
    text = 'Add applicants container'

class AddApplicantsContainer(WAeUPPage):
    grok.context(IApplicantsRoot)
    grok.name('add')
    grok.template('addcontainer')
    title = 'Add applicants container'
    pnav = 3

    def update(self, providername=None, name=None, title=None,
               description=None, ADD=None, CANCEL=None):
        if CANCEL is not None:
            self.redirect(self.url(self.context))
            return
        if ADD is None:
            return
        if not name:
            self.flash('Error: you must give a name')
            return
        if name in self.context.keys():
            self.flash('A container of the given name already exists')
            return
        # Add new applicants container...
        provider = getUtility(IApplicantsContainerProvider,
                              name=providername)
        container = provider.factory()
        container.name = name
        if title:
            container.title = title
        if description:
            container.description = description
        self.context[name] = container
        self.flash('Added "%s".' % name)
        self.redirect(self.url(self.context))
        return
        
    def getContainerProviders(self):
        """Get a list of applicants container providers.

        Applicants container providers are named utilities that help
        to create applicants containers of different types
        (JAMB-based, non-JAMB-based, etc.).

        The list returned contains dicts::

          {'name': <utility_name>,
           'provider': <provider instance>}

        where `utility_name` is the name under which the respective
        provider utility is registered and `provider` is the real
        provider instance.

        The `utility_name` can be used to lookup the utility anew (for
        instance after submitting a form) and the `provider` instance
        can be used to create new instances of the respective
        applicants container type.
        """
        providers = getAllUtilitiesRegisteredFor(IApplicantsContainerProvider)
        result = [
            {'name': getattr(x, 'grokcore.component.directive.name'),
             'provider': x}
             for x in providers
            ]
        return result

class ApplicantsRootBreadcrumb(Breadcrumb):
    """A breadcrumb for applicantsroot.
    """
    grok.context(IApplicantsRoot)
    title = u'Applicants'
    
class ApplicantsContainerBreadcrumb(Breadcrumb):
    """A breadcrumb for applicantscontainers.
    """
    grok.context(IApplicantsContainer)

class ApplicantsTab(PrimaryNavTab):
    """Faculties-tab in primary navigation.
    """
    grok.context(IWAeUPObject)
    grok.order(3)
    grok.require('waeup.View')
    grok.template('primarynavtab')

    pnav = 3
    tab_title = u'Applicants'

    @property
    def link_target(self):
        return self.view.application_url('applicants')

class ApplicantsContainerPage(WAeUPPage):
    """The standard view for regular applicant containers.
    """
    grok.context(IApplicantsContainer)
    grok.name('index')
    pnav = 3
    
    @property
    def title(self):
        return "Applicants Container: %s" % getattr(
            self.context, '__name__', 'unnamed')

    @property
    def label(self):
        return self.title

    def descriptionToHTML(self):
        return ReST2HTML(self.context.description)

class ManageApplicantsContainerActionButton(ManageActionButton):
    grok.context(IApplicantsContainer)
    grok.view(ApplicantsContainerPage)
    text = 'Manage'


class ManageApplicantsContainer(WAeUPEditFormPage):
    grok.context(IApplicantsContainer)
    grok.name('manage')
    form_fields = grok.AutoFields(IApplicantsContainer)
    # Use friendlier date widget...
    form_fields['startdate'].custom_widget = FriendlyDateWidget
    form_fields['enddate'].custom_widget = FriendlyDateWidget

    @property
    def title(self):
        return "Manage applicants container: %s" % getattr(
            self.context, '__name__', 'unnamed')
    
    @property
    def label(self):
        return self.title

    pnav = 3

    def update(self):
        datepicker.need() # Enable jQuery datepicker in date fields.
        return super(ManageApplicantsContainer, self).update()

    @grok.action('Save')
    def apply(self, **data):
        self.applyData(self.context, **data)
        self.flash('Data saved.')
        return
        
    @grok.action('Back')
    def cancel(self, **data):
        self.redirect(self.url(self.context))
        return
    
#class AddApplicant(WAeUPAddFormPage):
#    grok.context(IApplicantsContainer)
#    grok.name('add')
#    form_fields = grok.AutoFields(IApplicant)
#    form_fields['fst_sit_results'].custom_widget = list_results_widget
#    form_fields['passport'].custom_widget = EncodingImageFileWidget
#    label = 'Add Applicant'
#    title = 'Add Applicant'
#    pnav = 1
#
#    @grok.action('Add applicant')
#    def addApplicant(self, **data):
#        from waeup.sirp.jambtables.applicants import Applicant
#        applicant = Applicant()
#        self.applyData(applicant, **data)
#        # XXX: temporarily disabled.
#        #self.context[applicant.reg_no] = applicant
#        try:
#            self.context[applicant.access_code] = applicant
#        except KeyError:
#            self.flash('The given access code is already in use!')
#            return
#        self.redirect(self.url(self.context))

class DisplayApplicant(WAeUPDisplayFormPage):
    grok.context(IApplicant)
    grok.name('index')
    form_fields = grok.AutoFields(IApplicant)
    form_fields['fst_sit_results'].custom_widget = list_results_display_widget
    #form_fields['passport'].custom_widget = PassportDisplayWidget
    form_fields['passport'].custom_widget = ThumbnailWidget
    label = 'Applicant'
    title = 'Applicant'
    pnav = 3

class EditApplicant(WAeUPEditFormPage):
    grok.context(IApplicant)
    grok.name('edit')
    form_fields = grok.AutoFields(IApplicantPDEEditData)
    #form_fields['passport'].custom_widget = FileWidget
    #form_fields['passport'].custom_widget = PassportWidget
    form_fields['passport'].custom_widget = EncodingImageFileWidget
    grok.template('form_edit_pde')

    def update(self):
        super(EditApplicant, self).update()
        print self.request.form
        return
    
    @property
    def label(self):
        # XXX: Use current/upcoming session
        return 'Apply for Post UDE Screening Test (2009/2010)'
    title = 'Edit Application'
    pnav = 3

    @grok.action('Save')
    def save(self, **data):
        self.applyData(self.context, **data)
        self.context._p_changed = True
        return

    @grok.action('Final Submit')
    def finalsubmit(self, **data):
        self.applyData(self.context, **data)
        self.context._p_changed = True
        # XXX: Lock the form for editing...
        return
