"""Own caller hang-up policy model, not complete SIP transaction machinery."""
import json
def simulate(events):
    provisional=False;final=None;hangup=False;actions=[];trace=[];bye_sent=False
    for e in events:
        emitted=[]
        if e=='hangup':
            hangup=True
            if final=='accepted' and not bye_sent:emitted=['BYE'];bye_sent=True
            elif final is None and provisional:emitted=['CANCEL']
        elif e=='180_INVITE':
            provisional=True
            if hangup and final is None:emitted=['CANCEL']
        elif e=='200_INVITE':
            final='accepted';emitted=['ACK']
            if hangup and not bye_sent:emitted.append('BYE');bye_sent=True
        elif e=='487_INVITE':final='rejected';emitted=['ACK_non2xx']
        elif e not in ('200_CANCEL','200_BYE','200_OPTIONS'):raise ValueError('event outside fixture subset')
        actions.extend(emitted);trace.append({'event':e,'emitted':emitted,'INVITE_final_state':final,'hangup_requested':hangup})
    return {'trace':trace,'actions':actions,'INVITE_final_state':final,'BYE_sent_in_model':bye_sent}
def demo():
    cases={
      'before_provisional_then_rejection':['hangup','180_INVITE','200_CANCEL','487_INVITE'],
      'CANCEL_crosses_acceptance':['180_INVITE','hangup','200_CANCEL','200_INVITE','200_BYE'],
      'confirmed_then_hangup':['180_INVITE','200_INVITE','hangup','200_BYE'],
      'unrelated_OK_without_provisional':['hangup','200_OPTIONS']}
    rows=[{'case':name,'result':simulate(events)} for name,events in cases.items()]
    assert [r['result']['actions'] for r in rows]==[['CANCEL','ACK_non2xx'],['CANCEL','ACK','BYE'],['ACK','BYE'],[]]
    assert rows[1]['result']['trace'][2]['INVITE_final_state'] is None
    return {'authored_cases':rows,'caller_policy_abandon_attempt_and_accepted_dialog':True,'BYE_in_early_dialog_globally_forbidden_claimed':False,'SIP_headers_retransmission_forking_or_real_calls_implemented':False,'billing_or_human_answer_inferred':False}
if __name__=='__main__':print(json.dumps(demo(),ensure_ascii=False,indent=2))
