"""WAeUP portal certificates
"""
import grok
from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
try:
    from zope.catalog.interfaces import ICatalog
except ImportError:
    # BBB
    from zope.app.catalog.interfaces import ICatalog
from zope.component import getUtility
from zope.component.interfaces import IFactory, ComponentLookupError
from zope.interface import implementedBy
from waeup.sirp.university.interfaces import (
    ICertificate, ICertificateAdd, ICertificateCourse, ICourse)
from waeup.sirp.university.vocabularies import course_levels    

class Certificate(grok.Container):
    """A certificate.
    """
    grok.implements(ICertificate, ICertificateAdd)

    def __init__(self, code=u'NA', title=u'Unnamed Certificate',
                 study_mode=None, start_level=None,
                 end_level=None, application_category=None):
        super(Certificate, self).__init__()
        self.code = code
        self.title = title
        self.study_mode = study_mode
        self.start_level = start_level
        self.end_level = end_level
        self.application_category = application_category
        # Initialize workflow state...
        # self.setReviewState('unchecked')

    #def check(self):
    #    """Set Review State to ``checked``.
    #    """
    #    self.setReviewState(state='checked')

    #def getReviewState(self):
    #    return IWorkflowState(self).getState()

    #def setReviewState(self, state=None):
    #    """Try to set new state.

    #    Instead of simply setting a value, we fire a transition of a
    #    workflow. This might fail if, for instance, the required state
    #    is not part of the workflow or unreachable from current state.
    #    """
    #    if state == self.getReviewState():
    #        # Accept staying in the same state, even if workflow does
    #        # not allow this.
    #        return
    #    info = IWorkflowInfo(self)
    #    info.fireTransitionToward(state)
    #    return

    #review_state = property(getReviewState, setReviewState)
    
    def longtitle(self):
        return "%s (%s)" % (self.title,self.code)  
    
    def addCourseRef(self, course, level=100, core_or_elective=True):
        """Add a course referrer.
        """
        code = "%s_%s" % (course.code, level)
        self[code] = CertificateCourse(course, level, core_or_elective)
        self[code].__parent__ = self
        self[code].__name__ = code
        self._p_changed = True

    def delCourseRef(self, code, level=None):
        """Delete a course referrer denoted by its code.
        """
        for key in self.keys():
            if self[key].getCourseCode() != code:
                continue
            if level is not None and str(self[key].level) != str(level):
                # found a course with correct key but wrong level...
                continue
            del self[key]
            self._p_changed = True
        return

class CertificateFactory(grok.GlobalUtility):
    """A factory for certificates.
    """
    grok.implements(IFactory)
    grok.name(u'waeup.Certificate')
    title = u"Create a new certificate.",
    description = u"This factory instantiates new certificate instances."

    def __call__(self, *args, **kw):
        return Certificate(*args, **kw)

    def getInterfaces(self):
        return implementedBy(Certificate)

class CertificateCourse(grok.Model):
    grok.implements(ICertificateCourse)

    def __init__(self, course=None, level=100, core_or_elective=True):
        self.course = course
        self.level = level
        self.core_or_elective = core_or_elective

    def getCourseCode(self):
        """Get code of a course.
        """
        return self.course.code
        
    def longtitle(self):
        return "%s in level %s" % (self.course.code,
                   course_levels.getTerm(self.level).title)    
    
class CertificateCourseFactory(grok.GlobalUtility):
    """A factory for certificate courses.
    """
    grok.implements(IFactory)
    grok.name(u'waeup.CertificateCourse')
    title = u"Create a new certificate course.",
    description = u"This factory instantiates new certificate courses."

    def __call__(self, *args, **kw):
        return CertificateCourse(*args, **kw)

    def getInterfaces(self):
        return implementedBy(CertificateCourse)

@grok.subscribe(ICourse, grok.IObjectRemovedEvent)
def removedCourseHandler(course, event):
    """If a course is deleted, we make sure that also referrers in a
       certificatecontainer are removed.
    """
    code = course.code

    # Find all certificatecourses that refer to given course...
    try:
        cat = getUtility(ICatalog, name='certcourses_catalog')
    except ComponentLookupError:
        # catalog not available. This might happen during tests.
        return
        
    results = cat.searchResults(course_code=(code, code))
    for certcourse in results:
        # Remove that referrer...
        cert = certcourse.__parent__
        cert.delCourseRef(code)
        cert._p_changed = True
    return
