#
# 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 zope.container.contained import NameChooser
from zope.container.interfaces import INameChooser
from zope.component import queryUtility, getMultiAdapter
from zope.component import adapter, adapts
from zope.interface import implementer, implements
from zope.lifecycleevent.interfaces import IObjectRemovedEvent
from zope.security.proxy import removeSecurityProxy
from zope.traversing.api import getParent

from schooltool.app.app import InitBase, StartUpBase
from schooltool.app.interfaces import ISchoolToolApplication
from schooltool.person.interfaces import IPerson
from schooltool.schoolyear.interfaces import ISchoolYear, ISchoolYearContainer
from schooltool.schoolyear.subscriber import ObjectEventAdapterSubscriber
from schooltool.term.interfaces import IDateManager

import interfaces, intervention


def setUpInterventions(app):
    app[u'schooltool.interventions'] = intervention.InterventionRoot()


class InterventionStartup(StartUpBase):
    def __call__(self):
        if u'schooltool.interventions' not in self.app:
            setUpInterventions(self.app)


class InterventionInit(InitBase):
    """Create the InterventionRoot object."""

    def __call__(self):
        setUpInterventions(self.app)


@adapter(ISchoolToolApplication)
@implementer(interfaces.IInterventionRoot)
def getInterventionRoot(app):
    return app[u'schooltool.interventions']


@adapter(ISchoolYear)
@implementer(interfaces.IInterventionSchoolYear)
def getSchoolYearInterventionSchoolYear(schoolyear):
    app = ISchoolToolApplication(None)
    interventionRoot = interfaces.IInterventionRoot(app)
    try:
        interventionSchoolYear = interventionRoot[schoolyear.__name__]
    except KeyError:
        interventionSchoolYear = intervention.InterventionSchoolYear()
        interventionRoot[schoolyear.__name__] = interventionSchoolYear
    return interventionSchoolYear


@adapter(ISchoolToolApplication)
@implementer(interfaces.IInterventionSchoolYear)
def getSchoolToolApplicationInterventionSchoolYear(app):
    term = queryUtility(IDateManager).current_term
    schoolyear = ISchoolYear(term)
    return interfaces.IInterventionSchoolYear(schoolyear)


@adapter(interfaces.IInterventionSchoolYear)
@implementer(ISchoolYear)
def getInterventionSchoolYearSchoolYear(schoolyear):
    app = ISchoolToolApplication(None)
    return ISchoolYearContainer(app)[schoolyear.__name__]


@adapter(interfaces.IInterventionMarker)
@implementer(interfaces.IInterventionStudent)
def getMarkerInterventionStudent(marker):
    return interfaces.IInterventionStudent(marker.__parent__.__parent__)


@adapter(IPerson, ISchoolYear)
@implementer(interfaces.IInterventionStudent)
def getStudentYearInterventionStudent(student, schoolyear):
    interventionSchoolYear = interfaces.IInterventionSchoolYear(schoolyear)
    try:
        interventionStudent = interventionSchoolYear[student.__name__]
    except KeyError:
        interventionStudent = intervention.InterventionStudent()
        interventionSchoolYear[student.__name__] = interventionStudent
        interventionStudent[u'messages'] = intervention.InterventionMessages()
        interventionStudent[u'goals'] = intervention.InterventionGoals()
    return interventionStudent


@adapter(IPerson)
@implementer(interfaces.IInterventionStudent)
def getStudentInterventionStudent(student):
    app = ISchoolToolApplication(None)
    interventionSchoolYear = interfaces.IInterventionSchoolYear(app)
    schoolyear = ISchoolYear(interventionSchoolYear)
    interventionStudent = getMultiAdapter((student, schoolyear), 
        interfaces.IInterventionStudent)
    return interventionStudent


@adapter(interfaces.IStudentSchoolYearProxy)
@implementer(interfaces.IInterventionStudent)
def getSchoolYearProxyInterventionStudent(proxy):
    student = proxy.__parent__.__parent__
    app = ISchoolToolApplication(None)
    schoolyear = ISchoolYearContainer(app)[proxy.__name__]
    interventionStudent = getMultiAdapter((student, schoolyear), 
        interfaces.IInterventionStudent)
    return interventionStudent


@adapter(interfaces.IInterventionStudent)
@implementer(IPerson)
def getInterventionStudentStudent(interventionStudent):
    persons = ISchoolToolApplication(None)['persons']
    return persons[interventionStudent.__name__]


@adapter(interfaces.IInterventionMessages)
@implementer(IPerson)
def getInterventionMessagesStudent(interventionMessages):
    return IPerson(interventionMessages.__parent__)


@adapter(interfaces.IInterventionMessage)
@implementer(IPerson)
def getInterventionMessageStudent(interventionMessage):
    return IPerson(interventionMessage.__parent__)


@adapter(interfaces.IInterventionGoals)
@implementer(IPerson)
def getInterventionGoalsStudent(interventionGoals):
    return IPerson(interventionGoals.__parent__)


@adapter(interfaces.IInterventionGoal)
@implementer(IPerson)
def getInterventionGoalStudent(interventionGoal):
    return IPerson(interventionGoal.__parent__)


@adapter(interfaces.ISectionMessagesProxy)
@implementer(IPerson)
def getSectionMessagesProxyStudent(proxy):
    return removeSecurityProxy(proxy).student


@adapter(interfaces.IStudentMessagesGoalsProxy)
@implementer(IPerson)
def getSectionMessagesGoalsProxyStudent(proxy):
    return removeSecurityProxy(proxy.__parent__.__parent__).student


def getInterventionSchoolYearFromObj(obj):
    while not interfaces.IInterventionSchoolYear.providedBy(obj):
        if interfaces.IStudentSchoolYearProxy.providedBy(obj):
            return obj.year
        obj = getParent(obj)
    return obj


class SequenceNumberNameChooser(NameChooser):
    """A name chooser that returns a sequence number."""

    implements(INameChooser)

    def chooseName(self, name, obj):
        """See INameChooser."""
        numbers = [int(v.__name__) for v in self.context.values()
                   if v.__name__.isdigit()]
        if numbers:
            n = str(max(numbers) + 1)
        else:
            n = '1'
        self.checkName(n, obj)
        return n


class PersonRemovedSubsciber(ObjectEventAdapterSubscriber):
    adapts(IObjectRemovedEvent, IPerson)

    def __call__(self):
        app = ISchoolToolApplication(None)
        interventionRoot = app[u'schooltool.interventions']
        for schoolYear in interventionRoot.values():
            if self.object.username in schoolYear:
                del schoolYear[self.object.username]


class SchoolYearRemovedSubsciber(ObjectEventAdapterSubscriber):
    adapts(IObjectRemovedEvent, ISchoolYear)

    def __call__(self):
        app = ISchoolToolApplication(None)
        interventionRoot = app[u'schooltool.interventions']
        if self.object.__name__ in interventionRoot:
            del interventionRoot[self.object.__name__]

