from roundup.date import Interval

def deprevive_reactor(db, cl, issue_id, oldvals):
    '''Revives depending issue if an issue is marked as done
    '''

    waiting_id = db.status.lookup('waiting')
    done_id = db.status.lookup('done')
    att_id = db.status.lookup('needs attention')
    if oldvals.has_key("status") and cl.get(issue_id, "status") == done_id:
        for id in cl.find(superseder=issue_id):
            deps = cl.get(id, "superseder")
            if cl.get(id,"status") == waiting_id and len(deps) == \
                    len([x for x in deps if cl.get(x, "status") == done_id ]):
                cl.set(id, status=att_id)
                cl.set(id, revives=None)



def deprevive_auditor(db, cl, issue_id, newdata):
    ''' Checks that:
         - The revive date is before the due date
         - If there is no revive date, the due date is later
           than those of all dependencies
         - The priority is lower or equal to that of the dependencies
    '''

    # New priority
    if newdata.has_key("priority"):
        priority = newdata["priority"]
    elif issue_id:
        priority = cl.get(issue_id, "priority")
    else:
        priority = None

    # New superseder
    if newdata.has_key("superseder"):
        superseder = newdata["superseder"]
    elif issue_id:
        superseder = cl.get(issue_id, "superseder")
    else:
        superseder = []

    # New due date
    if newdata.has_key("due_date"):
        due_date = newdata["due_date"]
    elif issue_id:
        due_date = cl.get(issue_id, "due_date")
    else:
        due_date = None

    # New Revives
    if newdata.has_key("revives"):
        revives = newdata["revives"]
    elif issue_id:
        revives = cl.get(issue_id, "revives")
    else:
        revives = None


    # Check that the revive date is at least 1 day
    # before the due date
    if due_date and revives and due_date - revives < Interval("1d"):
        raise ValueError, "Revive date must be at least 1 day before due date."


    # Check that dependencies have higher or equal priority
    if newdata.has_key("superseder") or \
            newdata.has_key("priority"):
        for id in superseder:
            if db.issue.get(id, "priority") > priority:
                raise ValueError, "Depends on issue " + id + " which has lower priority."

        if issue_id:
            for id in cl.find(superseder=issue_id):
                if db.issue.get(id, "priority") < priority:
                    raise ValueError, "Depending issue " + id + " has higher priority."

    # Check that dependencies have later due date or or revive date
    if newdata.has_key("superseder") or \
            newdata.has_key("due_date") or \
            newdata.has_key("revives"):

        for id in superseder:
            if due_date and not revives and (not db.issue.get(id, "due_date") or \
               due_date - db.issue.get(id, "due_date") < Interval("1d")):
                raise ValueError, "Depends on issue " + id + " which has later (or no) due_date."

        if issue_id:
            for id in cl.find(superseder=issue_id):
                if db.issue.get(id, "due_date") and \
                        not db.issue.get(id, "revives") and \
                        ( not due_date or
                          db.issue.get(id, "due_date") - due_date < Interval("1d") ):
                    raise ValueError, "Issue " + id + " with earlier due date depends on this issue."

def init(db):
    db.issue.react('set', deprevive_reactor)
    db.issue.audit('set', deprevive_auditor)
    db.issue.audit('create', deprevive_auditor)

# vim: set filetype=python ts=4 sw=4 et si
