--
-- workflow_case__fire_transition_internal/2
--
create or replace function workflow_case__fire_transition_internal(
  integer,
  integer
) returns int4 as $$

declare
  fire_transition_internal__task_id                alias for $1;  
  fire_transition_internal__journal_id             alias for $2;  
  v_case_id                                        integer;        
  v_state                                          varchar;   
  v_transition_key                                 varchar;  
  v_workflow_key                                   varchar;  
  v_place_key                                      varchar;  
  v_direction                                      varchar;    
  v_guard_happy_p                                  boolean;       
  v_fire_callback                                  varchar;  
  v_fire_custom_arg                                text; 
  v_found_happy_guard                              boolean;       
  v_locked_task_id                                 integer;   
  place_rec                                        record;     
begin
        select t.case_id, t.state, t.workflow_key, t.transition_key, ti.fire_callback, ti.fire_custom_arg
        into   v_case_id, v_state, v_workflow_key, v_transition_key, v_fire_callback, v_fire_custom_arg
        from   wf_tasks t, wf_cases c, wf_transition_info ti
        where  t.task_id = fire_transition_internal__task_id
        and    c.case_id = t.case_id
        and    ti.context_key = c.context_key
        and    ti.workflow_key = c.workflow_key
        and    ti.transition_key = t.transition_key;

        /* Check that the state is either started or enabled */

        if v_state = 'enabled' then 
            v_locked_task_id := null;
        else if v_state = 'started' then
            v_locked_task_id := fire_transition_internal__task_id;
        else 
            raise EXCEPTION '-20000: Can''t fire the transition if it''s not in state enabled or started';
        end if; end if;

        /* Mark the task finished */

        update wf_tasks
        set    state = 'finished',
               finished_date = now()
        where  task_id = fire_transition_internal__task_id;


        /* Consume the tokens */

        for place_rec in select *
        from   wf_transition_places tp
        where  tp.workflow_key = v_workflow_key
        and    tp.transition_key = v_transition_key
        LOOP 
            PERFORM workflow_case__consume_token (
                v_case_id,
                place_rec.place_key,
                fire_transition_internal__journal_id,
                v_locked_task_id
             );
        end loop;

    
        /* Spit out new tokens in the output places */

        v_found_happy_guard := 'f';
        for place_rec in 
        select *
        from   wf_transition_places tp
        where  tp.workflow_key = v_workflow_key
        and    tp.transition_key = v_transition_key
        and    direction = 'out'
        LOOP
            v_place_key := place_rec.place_key;
            v_direction := place_rec.direction;

            v_guard_happy_p := workflow_case__evaluate_guard(
                place_rec.guard_callback, 
                place_rec.guard_custom_arg,
                v_case_id, 
                v_workflow_key, 
                v_transition_key, 
                v_place_key, 
                v_direction
            );
    
            if v_guard_happy_p = 't' then
                v_found_happy_guard := 't';
                PERFORM workflow_case__add_token (
                    v_case_id, 
                    place_rec.place_key,
                    fire_transition_internal__journal_id
                );
            end if;
        end loop;


        /* If we did not find any happy guards, look for arcs with the special hash (#) guard */

        if v_found_happy_guard = 'f' then
            for place_rec in 
                select place_key
                from   wf_transition_places tp
                where  tp.workflow_key = v_workflow_key
                and    tp.transition_key = v_transition_key
                and    tp.direction = 'out'
                and    tp.guard_callback = '#'
            loop

                PERFORM workflow_case__add_token (
                    v_case_id, 
                    place_rec.place_key,
                    fire_transition_internal__journal_id
                );
            end loop;
        end if;


        /* Execute the transition fire callback */

        PERFORM workflow_case__execute_transition_callback (
            v_fire_callback, 
            v_fire_custom_arg, 
            v_case_id, 
            v_transition_key
        );

        return 0; 
end;$$ language plpgsql;