:- use_module(library(lists)).
:- use_module(library(system)).

neq(A,B) :- A \== B.


main(Input,Len) :-
	name(Input,IList),
	append("tr13_",IList,Ilist1),
	name(Output,Ilist1),
	tell(Output),
	compile(Input),
	translate(Len),
	seen,told.

translate(Len) :-
	dump_fluents,nl,
	dump_actions,nl,
	dump_initially,nl,
	make_time(Len),nl,
	axioms(Len),nl,
	holds,nl,
	make_exec,nl,
	make_causes,nl,
	make_caused,nl,
	make_goal(Len),nl,
	ending.

dump_fluents :-
	setof(F,fluent(F),List),
	sub_dump_list(List,fluent).

dump_actions :-
	setof(A,action(A),List),
	sub_dump_list(List,action).

dump_initially :-
	setof(F,initially(F),List),
	sub_dump_list(List,initially).

sub_dump_list([],_).
sub_dump_list([X|Xs],Pred):-
	format("~q(~q).~n",[Pred,X]),
	sub_dump_list(Xs,Pred).

make_time(N) :-
	format("time(0..~q).~n",[N]).


axioms(N) :-
	format("literal(Fl) :- fluent(Fl).~n",[]),
	format("literal(mneg(Fl)) :- fluent(Fl).~n",[]),
	format("1{occ(Act,Ti):action(Act)}1 :- time(Ti), Ti < ~q.~n",[N]),
	format("opposite(Fl,mneg(Fl)) :- fluent(Fl).~n",[]),
	format("opposite(mneg(Fl),Fl) :- fluent(Fl).~n",[]),
	format(":- time(Ti), fluent(Fl), hold(Fl,Ti), hold(mneg(Fl),Ti).~n",[]),
	format(":- occ(Act,Ti), action(Act), time(Ti), not exec(Act,Ti).~n",[]).

 
ending :-
	format("#hide exec(U,V).~n #hide initially(U).~n #hide literal(V).~n",[]),
	format("#hide fluent(V).~n #hide action(V). ~n #hide opposite(V,U). ~n",[]),
	format("#hide causes(V,U).~n #hide ok(U,V,W). ~n #hide time(U).~n",[]),
	format("#hide caused(U,V). ~n #hide hold(U,V). ~n",[]).
	

holds :-
	initial_hold,
	regular_hold.

initial_hold :-
	format("hold(Fl,0) :- initially(Fl).~n",[]).

regular_hold :-
	format("hold(Fl,Ti+1) :- time(Ti), literal(Fl), occ(Act,Ti), causes(Act,Fl), ok(Act,Fl,Ti), exec(Act,Ti).~n",[]),
	format("hold(Fl,Ti) :- time(Ti), literal(Fl), caused(Ti,Fl).~n",[]),
	format("hold(Li,Ti+1) :- time(Ti), literal(Li), hold(Li,Ti), opposite(Li,Lu), not hold(Lu,Ti+1).~n",[]).


make_exec :-
	setof(A,action(A),List),
	sub_make_exec(List).
sub_make_exec([]).
sub_make_exec([A|B]) :-
	(executable(A,List) ->
	    (format("exec(~q,Ti) :- time(Ti)",[A]),
	    sub_submake_exec(List),
	    format(".~n",[]));
	    true 
         ),
	sub_make_exec(B).
sub_submake_exec([]).
sub_submake_exec([A|B]) :-
	format(",hold(~q,Ti) ",[A]),
	sub_submake_exec(B).

make_causes :-
	causes(Act,Flu,Conds),
	format("causes(~q,~q).~n",[Act,Flu]),
	format("ok(~q,~q,Ti) :- time(Ti)",[Act,Flu]),
	sub_make_causes(Conds), fail.
make_causes.

sub_make_causes([]) :-
	format(".~n",[]).
sub_make_causes([A|B]) :-
	format(", hold(~q,Ti)", [A]),
	sub_make_causes(B).


make_caused :-
	caused(Cond,Fl),
	format("caused(Ti,~q) :- time(Ti) ",[Fl]),
	sub_make_caused(Cond), fail.
make_caused.

sub_make_caused([]) :-
	format(".~n",[]).
sub_make_caused([A|B]) :-
	format(", hold(~q,Ti)",[A]),
	sub_make_caused(B).


make_goal(N) :-
	setof(G, goal(G), [Fluent|Fluents]),
	format(":- not goal.~n",[]),
	format("goal :- hold(~q,~q)",[Fluent,N]),
	sub_make_goal(N,Fluents).
sub_make_goal(_N,[]) :-
	format(".~n",[]).
sub_make_goal(N,[A|B]) :-
	format(", hold(~q,~q)",[A,N]),
	sub_make_goal(N,B).




