#
# SchoolTool - common information systems platform for school administration
# Copyright (c) 2005 Shuttleworth Foundation
#
# 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
#
"""
Student Intervention widgets.
"""
from zope.browser.interfaces import IAdding 
from zope.app.form.interfaces import MissingInputError
from zope.app.form.browser.interfaces import IBrowserWidget, IInputWidget
from zope.app.form.browser.submit import Update
from zope.app.pagetemplate import ViewPageTemplateFile
from zope.component import getUtility
from zope.interface import implements
from zope.security.proxy import removeSecurityProxy

from schooltool.contact.interfaces import IContactable, IContact
from schooltool.contact.browser.relationship import get_relationship_title
from schooltool.email.interfaces import IEmailUtility
from schooltool.intervention import InterventionGettext as _
from schooltool.intervention import intervention


class WidgetBase(object):
    """Base Class for all Widget Classes"""

    implements(IBrowserWidget, IInputWidget)

    template = None
    _prefix = 'field.'
    _error = ''

    # See zope.app.form.interfaces.IWidget
    name = None
    label = property(lambda self: self.context.title)
    hint = property(lambda self: self.context.description)
    visible = True

    # See zope.app.form.interfaces.IInputWidget
    required = property(lambda self: self.context.required)

    def __init__(self, field, request):
        self.context = field
        self.request = request

    def isAddView(self):
        return IAdding.providedBy(self.context.context)

    def setRenderedValue(self, value):
        """See zope.app.form.interfaces.IWidget"""
        pass

    def setPrefix(self, prefix):
        """See zope.app.form.interfaces.IWidget"""
        self._prefix = prefix

    def applyChanges(self, content):
        """See zope.app.form.interfaces.IInputWidget"""
        field = self.context
        new_value = self.getInputValue()
        old_value = field.query(content, self)
        if new_value == old_value:
            return False
        field.set(content, new_value)
        return True

    def hasInput(self):
        """See zope.app.form.interfaces.IInputWidget"""
        return True

    def hasValidInput(self):
        """See zope.app.form.interfaces.IInputWidget"""
        return True

    def getInputValue(self):
        """See zope.app.form.interfaces.IInputWidget"""
        return None

    def error(self):
        """See zope.app.form.browser.interfaces.IBrowserWidget"""
        return self._error

    def __call__(self):
        """See zope.app.form.browser.interfaces.IBrowserWidget"""
        return self.template()


class PersonListWidget(WidgetBase):
    """Person List Widget"""

    template = ViewPageTemplateFile('person_list.pt')

    def __init__(self, field, request):
        super(PersonListWidget, self).__init__(field, request)

        utility = getUtility(IEmailUtility)
        self.enabled = utility.enabled()
        self.message = ""
        if not self.enabled:
            self.message = _('Email server is not enabled')
        else:
            sender = self.request.principal._person.username
            if not intervention.convertIdToEmail(sender).strip():
                self.message = _('User has no email address')
                self.enabled = False

        valueList = self.getRequestValue()
        if self.isAddView():
            student = field.context.context.student
        else:
            student = field.context.student
            if not Update in self.request:
                valueList = getattr(field.context, field.getName())
        student = removeSecurityProxy(student)

        person_choices = intervention.getPersonsResponsible(student)
        advisors = [removeSecurityProxy(advisor).username
                    for advisor in student.advisors]

        if self.isAddView():
            changed = []
        else:
            changed = [person
                       for person in field.context.at_one_time_responsible
                       if person not in person_choices]

        self.responsible = []
        self.notified = []
        self.changed = []
        for choice in person_choices + changed:
            checked = ''
            if choice in valueList:
                checked = 'checked'

            value = intervention.convertIdToName(choice)
            if choice in advisors:
                value = '%s (%s)' % (value, _('advisor'))
                if self.isAddView() and not Update in self.request:
                    checked = 'checked'

            if choice[-2] == ':':
                personObj = intervention.convertIdToPerson(choice[:-2])
                index = int(choice[-1]) - 1
                parent = list(IContactable(student).contacts)[index]
                parent = removeSecurityProxy(parent)
                email = parent.email
                title = get_relationship_title(student, parent)
                if title is not None and len(title.strip()):
                    value = '%s (%s)' % (value, title.lower())
            else:
                personObj = intervention.convertIdToPerson(choice)
                email = IContact(personObj).email

            person = {
                'name': 'person.' + choice,
                'checked': checked,
                'value': value,
                'hasEmail': email is not None and len(email),
                }

            if choice == student.username or choice[-2] == ':':
                self.notified.append(person)
            elif choice in changed:
                self.changed.append(person)
            else:
                self.responsible.append(person)

    def canEmail(self, person):
        return self.enabled and person['hasEmail']

    def getRequestValue(self):
        persons = []
        for field in self.request:
            if field.startswith('person.'):
                person = field[7:]
                persons.append(person)
        return persons

    def setPrefix(self, prefix):
        """See zope.app.form.interfaces.IWidget"""
        self._prefix = prefix
        self.name = prefix + self.context.username

    def getInputValue(self):
        """See zope.app.form.interfaces.IInputWidget"""
        persons = self.getRequestValue()
        if not persons and self.enabled:
            self._error = MissingInputError.__doc__
            raise MissingInputError('', '')
        return persons

    def hasValidInput(self):
        """See zope.app.form.interfaces.IInputWidget"""
        return bool(self.getInputValue())


class GoalMetWidget(WidgetBase):
    """Goal Met Widget"""

    template = ViewPageTemplateFile('goal_met.pt')
    label = property(lambda self: '')

    def __init__(self, field, request):
        super(GoalMetWidget, self).__init__(field, request)
        
        if self.isAddView():
            value = False
        else:
            value = getattr(field.context, field.getName())

        if Update in self.request:
            value = self.getInputValue()

        self.goal_not_met = not value and 'checked' or None
        self.goal_met = value and 'checked' or None

    def getInputValue(self):
        """See zope.app.form.interfaces.IInputWidget"""
        return self.request['goal_met'] == 'Yes'
