% ----------------------------------------------------------------------
% -- ensure that companion files are charged

:- ensure_loaded(pref0203).

% ----------------------------------------------------------------------
% -- the real transformation

transform_clauses( Rules, NewRules ) :-
	homogenize(Rules,Rules0),
        apply_to_conjuncts(Rules0,add_preferences,Rules1),
        ok_rules(Rules0,OKRules),
        pref_rules(PrefRules),
	aux_rules(AuxRules0),

        conjoin(OKRules,AuxRules0,AuxRules1),
        conjoin(PrefRules,AuxRules1,AuxRules2),

        conjoin(Rules1,AuxRules2,NewRules).


add_preferences( (Head :- name(N), Body), Rules ) :-
	!,
	Rule  = (Head  :- Body),
        add_preferences_body(Rule, N, BodyRules),
	prime(Head,Head1),
        Rule0 = (Head1 :- ap(N)),
	add_primed_nots(Body,NewBody1),flatten_conjunction(NewBody1,NewBody), % PATCH!!!
        Rule1 = (ap(N) :- name(N), ok(N), NewBody),
	Rules1 = (Rule,Rule0,Rule1),
        conjoin(Rules1, BodyRules, Rules).
add_preferences( (Head :- name(N)), Rules ) :-
	!,
        add_preferences( (Head :- name(N), true), Rules ).
add_preferences( (Head :- Body), Rules ) :-
	prime(Head,Head1),
	add_primed_nots(Body,NewBody1),flatten_conjunction(NewBody1,NewBody), % PATCH!!!
	Rules = ((Head  :- Body),(Head1 :- NewBody)).
add_preferences( F, (F,F1) ) :-
	prime(F,F1).

add_preferences_body( (Head  :- Body), N, Rules ) :-
        Body = (Body1,Body2) ->
             add_preferences_body((Head  :- Body1),N,Rules1),
             add_preferences_body((Head  :- Body2),N,Rules2),
             conjoin(Rules1,Rules2,Rules);
        Body = (not Literal) ->
	     prime(Literal,Literal1),
             Rules = ( (bl(N) :- ok(N), Literal,Literal1),
	               (ex(N) :- Head, Literal)           );
        Body =      Literal  ->
	     prime(Literal,Literal1),
             Rules = (bl(N) :- ok(N), not Literal, not Literal1).

add_primed_nots( Body, NotBody ) :-
        Body = (Body1,Body2) ->
             add_primed_nots(Body1,NotBody1),
             add_primed_nots(Body2,NotBody2),
	     conjoin(NotBody1,NotBody2,NotBody);
        Body = (not Literal) ->
	     prime(Literal,Literal1),
	     NotBody = (not Literal, not Literal1);
       %Body =      Literal  ->
	     NotBody =      Body.

ok_rules( Rules, OKRules ) :-
        extract_oko_literals_from_rules(Rules,N,OKOLiterals),
        QRule  = (  ok(N)    :- name(N), OKOLiterals                     ),
        CRules = ( (oko(N,M) :- name(N), name(M), not ((N < M))        ),
                   (oko(N,M) :- name(N), name(M),      (N < M) , ap(M) ),
                   (oko(N,M) :- name(N), name(M),      (N < M) , bl(M) ),
                   (oko(N,M) :- name(N), name(M),                ex(M) ) ), % NEW
        conjoin(QRule,CRules,OKRules).

aux_rules( Rules ) :-
	Rules = ( false :- name(N), not ok(N) ) .

prime( Wff, Wff1 ) :-
	Wff = (A :- B) ->
                prime(A,A1),
                prime(B,B1),
		Wff1 = (A1 :- B1);
        Wff = (A , B) ->
                prime(A,A1),
                prime(B,B1),
		Wff1 = (A1 , B1);
        Wff = (A ; B) ->
                prime(A,A1),
                prime(B,B1),
		Wff1 = (A1 ; B1);
        Wff = (not A) ->
                prime(A,A1),
		Wff1 = (not A1);
        Wff = (neg A) ->
                prime(A,A1),
		Wff1 = (neg A1);
	Wff = name(N) ->
		Wff1 = name(N);
        Wff = true ->
		Wff1 = true;
        Wff = ( A < B ) ->
		Wff1 = prec1(A,B);
       (Wff =.. [P|_],builtin(P,_)) ->
	        error(prime(Wff, Wff1));
        Wff =.. [P|Args] ->
	        name(P,L),
		append(L,[49],L1),
	        name(P1,L1),
		Wff1 =.. [P1|Args];
        %true ->
                error(prime(Wff, Wff1)).

% ----------------------------------------------------------------------
% -- Rules to Procedures

builtin(not,1).
builtin(neg,1).
% builtin(-,1).
% builtin(~,1).
% builtin(<,2).

builtin(ok,1).
builtin(oko,2).
builtin(ap,1).
builtin(bl,1).
builtin(ex,1).
