#
# 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, see <http://www.gnu.org/licenses/>.
#

from datetime import date

import z3c.form.field
from zope.component import getUtility
from zope.traversing.browser.absoluteurl import absoluteURL
from zope.i18n import translate

from schooltool.app.interfaces import ISchoolToolApplication
from schooltool.contact.interfaces import IContactable, IContact
from schooltool.email.interfaces import IEmailUtility
from schooltool.email.mail import Email
from schooltool.person.interfaces import IPerson

from schooltool.intervention import InterventionGettext as _
from interfaces import IInterventionGoal, IInterventionSchoolYear
import intervention


def sendInterventionMessageEmail(obj):
    """Send email corresponding to the intervention message just added."""

    # there can be only one sender - none may or may not be accepted by utility
    for contact in obj.sender:
        sender = contact.email
        sender_name = intervention.contactName(contact)
        break
    else:
        sender = ''
        sender_name = ''
    recipients = intervention.contactsEmail(obj.recipients)
    name = intervention.contactName(IContact(IPerson(obj)))
    mapping = {'student': name}
    if obj.subject:
        subject = obj.subject
    elif obj.status_change:
        subject = translate(_('INTERVENTION STATUS CHANGE: ${student}',
                              mapping=mapping),
                            context=intervention.getRequest())
    else:
        subject = translate(_('INTERVENTION MESSAGE: ${student}',
                              mapping=mapping),
                            context=intervention.getRequest())
    body = translate(_('${sender} writes:', mapping={'sender': sender_name}),
                     context=intervention.getRequest())
    body += '\n\n%s' % obj.body
    return sendEmail(sender, recipients, subject, body)


def sendInterventionGoalAddEmail(obj):
    """Send email corresponding to the intervention goal just added."""

    # there can be only one sender - none may or may not be accepted by utility
    for contact in obj.creator:
        sender = contact.email
        break
    else:
        sender = ''

    student = IPerson(obj)
    student_contacts = IContactable(student).contacts
    name = intervention.contactName(IContact(student))
    subject = translate(_('INTERVENTION GOAL ADDED: ${student}',
                          mapping={'student': name}),
                        context=intervention.getRequest())

    responsible, notified = [], []
    for contact in obj.persons_responsible:
        if IPerson(contact, None) is student or contact in student_contacts:
            notified.append(contact)
        else:
            responsible.append(contact)

    emails = []
    if responsible:
        recipients = intervention.contactsEmail(responsible)
        body = buildInterventionGoalAddBody(obj)
        emails.append(sendEmail(sender, recipients, subject, body))

    if notified:
        recipients = intervention.contactsEmail(notified)
        body = buildInterventionGoalAddBody(obj, False)
        emails.append(sendEmail(sender, recipients, subject, body))
    return emails


def buildInterventionGoalAddBody(obj, staff=True):
    name = intervention.contactName(IContact(IPerson(obj)))
    body = translate(_('The following goal was added for ${student}:',
                       mapping={'student': name}),
                     context=intervention.getRequest())
    body += '\n'
    fields = z3c.form.field.Fields(IInterventionGoal)
    fields = fields.omit('__name__', '__parent__', 'goal_met',
                         'follow_up_notes', 'notified', 'creator', 'created',
                         'at_one_time_responsible')
    for k, v in fields.items():
        text = obj.__getattribute__(k)
        if not text:
            continue
        body += '\n%s\n%s\n\n' % (v.field.title, '-' * len(v.field.title))
        if k == 'persons_responsible':
            names = [intervention.contactName(contact)
                     for contact in obj.persons_responsible]
            text = '\n'.join(sorted(names))
        elif k == 'timeline':
            text = obj.timeline.strftime('%x')
        body += '%s\n' % text
    if staff:
        url = absoluteURL(obj.__parent__.__parent__, intervention.getRequest())
        intervention_center = translate(_('Intervention Center'),
                                        context=intervention.getRequest())
        body += '\n%s\n%s\n' % (intervention_center, '-' * len(intervention_center))
        body += '\n%s\n' % url
    return body


def sendInterventionGoalNotifyEmails():
    """Loop through all goals for the current school year and send
       email to the persons responsible for the goal if:

       1) the goal's timeline is on or before today.
       2) an email for the goal has never been sent.
    """

    request = intervention.getRequest()
    now = date.today()
    goalsNotified = []
    app = ISchoolToolApplication(None)
    interventionSchoolYear = IInterventionSchoolYear(app)
    for interventionStudent in interventionSchoolYear.values():
        for interventionGoal in interventionStudent['goals'].values():
            if interventionGoal.timeline <= now and not interventionGoal.notified:
                notifyInterventionGoal(interventionGoal, request)
                goalsNotified.append(interventionGoal)
    return goalsNotified


def notifyInterventionGoal(interventionGoal, request):
    """Send email to the persons responsible for the given goal."""

    # there can be only one sender - none may or may not be accepted by utility
    for contact in interventionGoal.creator:
        sender = contact.email
        break
    else:
        sender = ''
 
    student = IPerson(interventionGoal)
    student_contacts = IContactable(student).contacts
    responsible = []
    for contact in interventionGoal.persons_responsible:
        if IPerson(contact, None) is student or contact in student_contacts:
            continue
        responsible.append(contact)
    recipients = intervention.contactsEmail(responsible)
 
    name = intervention.contactName(IContact(student))
    subject = translate(_('INTERVENTION GOAL DUE: ${student}',
                          mapping={'student': name}),
                        context=request)
    url = absoluteURL(interventionGoal, request) + '/@@editGoal.html'
    body = translate(_("Please follow the link below to update the follow "
                       "up notes and, if appropriate, the goal met status "
                       "of the intervention goal for ${student}.",
                       mapping={'student': name}),
                     context=request)
    body += '\n\n%s\n' % url

    sendEmail(sender, recipients, subject, body)
    interventionGoal.notified = True


def sendEmail(sender, recipients, subject, body):
    """send email through the schooltool email utility."""

    email = Email(sender, recipients, body, subject)
    utility = getUtility(IEmailUtility)
    utility.send(email)
    return email


class TestMailDelivery(object):
    """Email delivery utility used for testing"""

    def enabled(self):
        return True

    def send(self, email):
        print 'From:', email.from_address
        print 'To:', ', '.join(email.to_addresses)
        print 'Subject:', email.subject
        print email.body

