%% :- module(treetologic, [tree_logic/2]).

% Written by anniepoo on [2018-02-11]

tree_logic(Tree, LogicForm) :-
    ground(Tree),
    gensym(v, Root),
    tree_logic(Root, Tree, LogicForm).
tree_logic(Tree, [Root | Rest]) :-
    Root =.. [_, Self | _],
    var_tree([Root | Rest], Self, Tree).


%!      tree_logic(+Self:atom, +Tree:acyclic, -LogicForm:list) is det
%
%  convert a tree of form a(b,c(d))
%  to a list like [a(v1,v2,v3),b(v2),c(v3,v4),d(v4)]
%
%  where the first argument is a 'self' argument
%  and the first self argument is passed in
%
tree_logic(Self, Leaf, [LeafTerm]) :-
    atomic(Leaf),
    LeafTerm =.. [Leaf, Self].
tree_logic(Self, Node, [SelfNode | LogicForm]) :-
    Node =.. [Functor | Args],
    maplist(argvar , Args, Vars),
    SelfNode =.. [Functor, Self | Vars],
    maplist(tree_logic, Vars, Args, UnflatLogicForms),
    flatten(UnflatLogicForms, LogicForm).

argvar(_, Var) :-
    gensym(v, Var).


%!  var_tree(+Children:list, +Var:atom, -Tree:acyclic)
%
%   Given a var and the original list, make a tree
var_tree(Children, Var, Tree) :-
    member(Term, Children),
    Term =.. [Functor, Var | Args],
    maplist(var_tree(Children), Args, SubForest),
    Tree =.. [Functor | SubForest].

test(Logic) :-
    tree_logic(a(b,c(d)), Logic).

test2(Tree) :-
    tree_logic(Tree, [a(v1, v2, v3), b(v2), c(v3, v4), d(v4)]).

test3(Logic) :-
    tree_logic(a(b(c,d),e,f(g,h,i(j,k,l(m,n)))), Logic).

test4(Tree) :-
    tree_logic(Tree, [a(v1,v2,v5,v6), b(v2,v3,v4), c(v3), d(v4), e(v5), f(v6,v7,v8,v9), g(v7), h(v8), i(v9,v10,v11,v12), j(v10), k(v11), l(v12,v13,v14), m(v13), n(v14)]).




%%% aindilis' untested additions to anniepoo's code

convertNestedToFFFOPC(Nested,FFFOPC) :-
	reset_gensym(v),
	tree_logic(Nested,LFs),
	view([lfs,LFs]),
	update_index_1(5,LFs,FFFOPC).

update_index_1(Index,LFs,NewLFs) :-
	findall(NewLF,
		(   
		    member(LF,LFs),
		    LF =.. [P|Args],
		    findall(NewArg,
			    (	
				member(Arg,Args),
				concat_atom([v,Var],Arg),
				atomic_list_concat([v,Index,'_',Var],'',NewArg)
			    ),
			    NewArgs),
		    NewLF =.. [P|NewArgs]
		),
		NewLFs).

%% ?- convertNestedToFFFOPC(a(b(c, d), e, f(g, h, i(j, k, l(m, n)))),FFFOPC).
%% [lfs,[a(v1,v2,v3,v4),b(v2,v5,v6),c(v5),d(v6),e(v3),f(v4,v7,v8,v9),g(v7),h(v8),i(v9,v10,v11,v12),j(v10),k(v11),l(v12,v13,v14),m(v13),n(v14)]]
%% FFFOPC = [a(v5_1,v5_2,v5_3,v5_4),b(v5_2,v5_5,v5_6),c(v5_5),d(v5_6),e(v5_3),f(v5_4,v5_7,v5_8,v5_9),g(v5_7),h(v5_8),i(v5_9,v5_10,v5_11,v5_12),j(v5_10),k(v5_11),l(v5_12,v5_13,v5_14),m(v5_13),n(v5_14)] 


convertFFFOPCToNested(FFFOPC,Nested) :-
	update_index_2(FFFOPC,Tmp),
	tree_logic(Nested,Tmp).

update_index_2(LFs,NewLFs) :-
	findall(NewLF,
		(   
		    member(LF,LFs),
		    LF =.. [P|Args],
		    findall(NewArg,
			    (	
				member(Arg,Args),
				atomic_list_concat([_,Var], '_', Arg),
				atomic_list_concat(['v',Var],'',NewArg)
			    ),
			    NewArgs),
		    NewLF =.. [P|NewArgs]
		),
		NewLFs).

%% ?- convertFFFOPCToNested([a(v5_1,v5_2,v5_3,v5_4),b(v5_2,v5_5,v5_6),c(v5_5),d(v5_6),e(v5_3),f(v5_4,v5_7,v5_8,v5_9),g(v5_7),h(v5_8),i(v5_9,v5_10,v5_11,v5_12),j(v5_10),k(v5_11),l(v5_12,v5_13,v5_14),m(v5_13),n(v5_14)],X).
%% X = a(b(c, d), e, f(g, h, i(j, k, l(m, n)))) 

view(Item) :-
	write_term(Item,[quoted(true)]),nl,!.

%% FIXME: implement actual var(Vars) next, figure out how that should
%% look.

%% ??? a(b(c,d)) <-> [a(v1_1,v1_2),b(v1_2,v1_3,v1_4),c(v1_3),d(v1_4)].

%% ??? a(b(C,d)) <-> [a(v1_1,v1_2),b(v1_2,v1_3,v1_4),c(v1_3,C),d(v1_4)].
%% ??? a(b(C,d)) <-> [a(v1_1,v1_2),b(v1_2,C,v1_4),c(C),d(v1_4)].

%% ??? a(b(C,d)) <-> [a(v1_1,v1_2),b(v1_2,v1_3,v1_4),c(v1_3,'$VAR'(C)),d(v1_4)].
%% ??? a(b(C,d)) <-> [a(v1_1,v1_2),b(v1_2,'$VAR'(C),v1_4),c('$VAR'(C)),d(v1_4)].




%% next interview the serpro

%% a(b(c,d)) <-> a(1351351).  %% serpro(b(c,d),1351351)
%% a(b(c,d)) <-> a(X),X=b(Y,Z).  %% serpro(Y,5489), serpro(Z,5823)

%% a(b(c,d)) <-> [a(v1_1,v1_2),b(v1_2,v1_3,v1_4),c(v1_3),d(v1_4)].

%% a(b(C,d)) <-> %% ??? a(b(C,d)) <-> [a(v1_1,v1_2),b(v1_2,v1_3,v1_4),c(v1_3,C),d(v1_4)].



capabilityEnablesCapability(treetologic,[prologAgent, fLUX, gDL, pDDL, dataIntegration,flowchartGeneration]).



%% next we want to attempt to translate between the Prolog FactBase and PDDL/GDL/FLUX

