'Update the presence log of a person entity
- mandatory to be called as onaccept routine at any modification
of pr_presence records'

@staticmethod
def presence_onaccept(form):

    db = current.db
    table = db.pr_presence
    popts = current.s3db.pr_presence_opts
    if isinstance(form, (int, long, str)):
        id = form
    elif hasattr(form, 'vars'):
        id = form.vars.id
    else:
        id = form.id
    presence = db((table.id == id)).select(table.ALL, limitby=(0, 1)).first()
    if (not presence):
        return
    else:
        condition = presence.presence_condition
    pe_id = presence.pe_id
    datetime = presence.datetime
    if ((not datetime) or (not pe_id)):
        return
    this_entity = ((table.pe_id == pe_id) & (table.deleted == False))
    earlier = (table.datetime < datetime)
    later = (table.datetime > datetime)
    same_place = ((table.location_id == presence.location_id) | (table.shelter_id == presence.shelter_id))
    is_present = table.presence_condition.belongs(popts.PERSISTANT_PRESENCE)
    is_absent = table.presence_condition.belongs(popts.ABSENCE)
    is_missing = (table.presence_condition == popts.MISSING)
    if (not presence.deleted):
        if (condition in popts.TRANSITIONAL_PRESENCE):
            if presence.closed:
                db((table.id == id)).update(closed=False)
        elif (condition in popts.PERSISTANT_PRESENCE):
            if (not presence.closed):
                query = (((this_entity & earlier) & (is_present | is_missing)) & (table.closed == False))
                db(query).update(closed=True)
                query = ((this_entity & later) & (is_present | (is_absent & same_place)))
                if db(query).count():
                    db((table.id == id)).update(closed=True)
        elif (condition in popts.ABSENCE):
            query = (((this_entity & earlier) & is_present) & same_place)
            db(query).update(closed=True)
            if (not presence.closed):
                db((table.id == id)).update(closed=True)
    if (not presence.closed):
        query = (this_entity & is_present)
        presence = db(query).select(table.ALL, orderby=(~ table.datetime), limitby=(0, 1)).first()
        if (presence and presence.closed):
            later = (table.datetime > presence.datetime)
            query = (((this_entity & later) & is_absent) & same_place)
            if (not db(query).count()):
                db((table.id == presence.id)).update(closed=False)
        query = (this_entity & is_missing)
        presence = db(query).select(table.ALL, orderby=(~ table.datetime), limitby=(0, 1)).first()
        if (presence and presence.closed):
            later = (table.datetime > presence.datetime)
            query = ((this_entity & later) & is_present)
            if (not db(query).count()):
                db((table.id == presence.id)).update(closed=False)
    pentity = db((db.pr_pentity.pe_id == pe_id)).select(db.pr_pentity.instance_type, limitby=(0, 1)).first()
    if (pentity and (pentity.instance_type == 'pr_person')):
        query = ((this_entity & is_missing) & (table.closed == False))
        if db(query).count():
            db((db.pr_person.pe_id == pe_id)).update(missing=True)
        else:
            db((db.pr_person.pe_id == pe_id)).update(missing=False)
    return
