/* ************************************************************
	module for basic transaction functions
************************************************************* */

:- export inserted/1, deleted/1, checkconj/2, dbase/1, insertnewdbrule/1.
:- export createpreds/2, ins/1, del/1, do_insert/1, do_delete/1.
:- export basicsinit/0.
:- export database/1.
:- import retract/1, assert/1 from assert.
:- import inserting/1, deleting/1, on_backtracking/1 from basic_funs1.

:- op(450,fx,[ins,del]).
:- op(710,fx,[not]).

database(X) :- inserted(X), not(deleted(X)).

basicsinit :-
	dynamic(inserted(_)), dynamic(deleted(_)).

% basic strong insertions
%
ins(X) :- 
	predicate_property(X,(dynamic)) -> do_insert(X)
	;
	insertnewdbrule(X),
	do_insert(X).

% For initial inserts, assert the insert tag.
do_insert(X) :-
	IPred = inserted(X),
	not(IPred),
	assert(IPred), !,
%	checkconj(i,IPred),
	undo_ins1(IPred).

% For all subsequent inserts, simply remove the delete tag.
do_insert(X) :-
	inserted(X),
	DPred = deleted(X),
	retract(DPred), !,
%	checkconj(d,DPred),
	undo_ins2(DPred).

undo_ins1(_).
undo_ins1(IPred) :- 
	retract(IPred), !, fail.
undo_ins2(_).
undo_ins2(DPred) :- 
	asserta(DPred), !, fail.


% basic strong delete
%
del(X) :- 
	predicate_property(X,(dynamic)) -> do_delete(X)
	;
	insertnewdbrule(X),
	do_delete(X).

% strong delete, so insert a delete tag
do_delete(X) :- 
	database(X),
	DPred = deleted(X),
	assert(DPred),
%	checkconj(i,DPred),
	undo_del(DPred).

undo_del(_).
undo_del(DPred) :- retract(DPred), !, fail.


% create a list of N unique and uninstantiated args
%
createpreds(0,[]).
createpreds(N,[_|L]) :-
	N>0, M is N-1, createpreds(M,L).

% define not
%
not(X) :- call(X), !, fail
	  ;
	  true.

checkconj(Info,Data) :-
	(tracking -> savetrack(Info,Data)
	;
	not(tracking)).

savetrack(Info,Data) :-
	retract(track(L)), assert(track([(Info,Data)|L])),
	on_backtracking(( retract(track(_)), assert(track(L)) )).


dbase(Pred) :-  
		deleting(tr),
		call(Pred),
		inserting(tr).


insertnewdbrule(X) :- true.
%	assert((X :- database(X))).
