"""Workflow for students.
"""
import grok
from zope.component import getUtility
from hurry.workflow.workflow import Transition, WorkflowState, NullCondition
from hurry.workflow.interfaces import IWorkflowState, IWorkflowTransitionEvent
from waeup.sirp.interfaces import (
    IObjectHistory, ISIRPWorkflowInfo, ISIRPUtils,
    CREATED, ADMITTED, CLEARANCE, REQUESTED, CLEARED, PAID, RETURNING,
    REGISTERED, VALIDATED)
from waeup.sirp.interfaces import MessageFactory as _
from waeup.sirp.workflow import SIRPWorkflow, SIRPWorkflowInfo
from waeup.sirp.students.interfaces import IStudent, IStudentsUtils


IMPORTABLE_STATES = (ADMITTED, CLEARANCE, REQUESTED, CLEARED, PAID, RETURNING,
    REGISTERED, VALIDATED)

REGISTRATION_TRANSITIONS = (
    Transition(
        transition_id = 'create',
        title = _('Create student'),
        source = None,
        condition = NullCondition,
        msg = _('Student record created'),
        destination = CREATED),

    Transition(
        transition_id = 'admit',
        title = _('Admit student'),
        msg = _('Student admitted'),
        source = CREATED,
        destination = ADMITTED),

    Transition(
        transition_id = 'reset1',
        title = _('Reset student'),
        msg = _('Student record reset'),
        source = ADMITTED,
        destination = CREATED),

    Transition(
        transition_id = 'start_clearance',
        title = _('Start clearance'),
        msg = _('Clearance started'),
        source = ADMITTED,
        destination = CLEARANCE),

    Transition(
        transition_id = 'reset2',
        title = _('Reset to admitted'),
        msg = _("Student record reset to 'admitted'"),
        source = CLEARANCE,
        destination = ADMITTED),

    Transition(
        transition_id = 'request_clearance',
        title = _('Request clearance'),
        msg = _('Clearance requested'),
        source = CLEARANCE,
        destination = REQUESTED),

    Transition(
        transition_id = 'reset3',
        title = _('Reset to clearance'),
        msg = _("Student record reset to 'clearance'"),
        source = REQUESTED,
        destination = CLEARANCE),

    Transition(
        transition_id = 'clear',
        title = _('Clear student'),
        msg = _('Cleared'),
        source = REQUESTED,
        destination = CLEARED),

    Transition(
        transition_id = 'reset4',
        title = _('Reset to clearance'),
        msg = _("Student record reset to 'clearance'"),
        source = CLEARED,
        destination = CLEARANCE),

    Transition(
        transition_id = 'pay_first_school_fee',
        title = _('Pay school fee'),
        msg = _('School fee paid'),
        source = CLEARED,
        destination = PAID),

    Transition(
        transition_id = 'reset5',
        title = _('Reset to cleared'),
        msg = _("Student record reset to 'cleared'"),
        source = PAID,
        destination = CLEARED),

    Transition(
        transition_id = 'pay_school_fee',
        title = _('Pay school fee'),
        msg = _('School fee paid'),
        source = RETURNING,
        destination = PAID),

    Transition(
        transition_id = 'reset6',
        title = _('Reset to returning'),
        msg = _("Student record reset to 'returning'"),
        source = PAID,
        destination = RETURNING),

    Transition(
        transition_id = 'register_courses',
        title = _('Register courses'),
        msg = _('Courses registered'),
        source = PAID,
        destination = REGISTERED),

    Transition(
        transition_id = 'reset7',
        title = _('Reset to paid'),
        msg = _("Student record reset to 'paid'"),
        source = REGISTERED,
        destination = PAID),

    Transition(
        transition_id = 'validate_courses',
        title = _('Validate courses'),
        msg = _('Courses validated'),
        source = REGISTERED,
        destination = VALIDATED),

    Transition(
        transition_id = 'reset8',
        title = _('Reset to paid'),
        msg = _("Student record reset to 'paid'"),
        source = VALIDATED,
        destination = PAID),

    Transition(
        transition_id = 'return',
        title = _('Return'),
        msg = _('Returned'),
        source = VALIDATED,
        destination = RETURNING),

    Transition(
        transition_id = 'reset9',
        title = _('Reset to validated'),
        msg = _("Student record reset to 'validated'"),
        source = RETURNING,
        destination = VALIDATED),
    )

LOCK_CLEARANCE_TRANS = ('reset2', 'request_clearance')
UNLOCK_CLEARANCE_TRANS = ('reset3', 'reset4', 'start_clearance')

registration_workflow = SIRPWorkflow(REGISTRATION_TRANSITIONS)

class RegistrationWorkflowState(WorkflowState, grok.Adapter):
    """An adapter to adapt Student objects to workflow states.
    """
    grok.context(IStudent)
    grok.provides(IWorkflowState)

    state_key = 'wf.registration.state'
    state_id = 'wf.registration.id'

class RegistrationWorkflowInfo(SIRPWorkflowInfo, grok.Adapter):
    """Adapter to adapt Student objects to workflow info objects.
    """
    grok.context(IStudent)
    grok.provides(ISIRPWorkflowInfo)

    def __init__(self, context):
        self.context = context
        self.wf = registration_workflow

@grok.subscribe(IStudent, IWorkflowTransitionEvent)
def handle_student_transition_event(obj, event):
    """Append message to student history and log file when transition happened.

    Lock and unlock clearance form.
    """

    msg = event.transition.user_data['msg']
    history = IObjectHistory(obj)
    history.addMessage(msg)
    if event.transition.transition_id in LOCK_CLEARANCE_TRANS:
        obj.clearance_locked = True
    if event.transition.transition_id in UNLOCK_CLEARANCE_TRANS:
        obj.clearance_locked = False
    # Student data don't change after first-time payment
    if event.transition.transition_id == 'pay_first_school_fee':
        pass
    # School fee payment of returning students triggers the change of
    # current session, current level, and current verdict
    if event.transition.transition_id == 'pay_school_fee':
        getUtility(IStudentsUtils).setReturningData(obj)
    # In some tests we don't have a students container
    try:
        students_container = grok.getSite()['students']
        students_container.logger.info('%s - %s' % (obj.student_id,msg))
    except (TypeError, AttributeError):
        pass
    return
