/* **************************************************
	tr_appl module
*************************************************** */

:- export bulkins/2, bulkdel/1, assign_to/2, simple_assign/2.
:- import insertnewdbrule/5, do_insert/2
	  from tr_basics3.
:- import insertedname/2, deletedname/2, dbname/2
	  from naming3.
:- import getlist/3, insertlist/1,
	  inserting/1, deleting/1 from basic_funs3.

:- op(850,xfy,[from]).
:- op(900,xfy,[assign_to]).


% bulk insertion (always true, i.e. weak)
%
bulkins(FromFun,ToFun) :- 
	ToFun =.. [ToName|ToArgs],
	dbname(ToName,DBName),
	insertedname(ToName,IName),
	deletedname(ToName,DName), 
	DBPred =.. [DBName|ToArgs],
	(
	predicate_property(DBPred,(dynamic)) ->
		do_bulkinsert(FromFun,IName,DName,ToFun)
	;
	not(predicate_property(DBPred,(dynamic))),
	functor(DBPred,DBName,NArgs),
	insertnewdbrule(ToName,DBName,IName,DName,NArgs), !,
	deleting(tr),
	do_bulkinsert(FromFun,IName,DName,ToFun),
	inserting(tr)).

do_bulkinsert(FromFun,IName,DName,ToFun) :-
	getlist(ToFun,FromFun,List),!,
	do_insertlist(IName,DName,List).

% weak insert all predicates in the list
do_insertlist(_,_,[]).
do_insertlist(IName,DName,[ToFun|Rest]) :-
	do_weakinsert(IName,DName,ToFun),
	do_insertlist(IName,DName,Rest).

% weak insert, i.e. it succeeds if Pred is already in the database
do_weakinsert(_,_,ToFun) :-
	call(ToFun).
do_weakinsert(IName,DName,ToFun) :-
	ToFun =.. [_|Args],
	IPred =.. [IName|Args],
	do_insert(IPred,DName).

% bulk deletion (always true)
%
bulkdel(X) :-
	X =.. [Name|Args],
	deletedname(Name,DName),
	DTerm =.. [DName|Args],
	(predicate_property(DTerm,(dynamic)) -> bulk_erase(X,DTerm)
	;
	not(predicate_property(DTerm,(dynamic)))).

% Unlike bulkins, there is only one term for bulk_erase, so database(Term)
% works the same as removing tr flag first.
bulk_erase(Term,DTerm) :-
	inserting(tr),
	getlist(DTerm,Term,DList),
	deleting(tr),
	insertlist(DList).

% assignment
% For example,  assign q(X,Y) from p(X,Y)
% syntax:       assign_to(q, from([X,Y],p(X,Y))
%           or  assign_to(q, p(X,Y))
%
assign_to(OutPred,TestPred) :-
	OutPred =.. [OutName|ArgList],
	dbname(OutName,DBName),
	insertedname(OutName,IName),
	deletedname(OutName,DName), 
	DBPred =.. [DBName|ArgList],
	(
	predicate_property(DBPred,(dynamic)) -> true
	;
	functor(DBPred,DBName,NArgs),
	insertnewdbrule(OutName,DBName,IName,DName,NArgs)), !,
	simple_assign(OutName,ArgList,TestPred).

% bulk delete OutPred first and then bulk insert from TestPred to OutPred
simple_assign(OutName,ArgList,TestPred) :-
	insertedname(OutName,IName),	
	deletedname(OutName,DName),
	OutPred =.. [OutName|ArgList],
	deleting(tr),
	getlist(OutPred,TestPred,BufferList), % copy output to buffer
	inserting(tr),
	DPred =.. [DName|ArgList],
	bulk_erase(OutPred,DPred),
	do_insertlist(IName,DName,BufferList).

