store_empty( ([],[],[],1,[],[]) ).

store_enquire( Store, Enquires ) :-
	ensure_list( Enquires, ListOfEnqs ),
	enquire_store_1( ListOfEnqs, Store ).

enquire_store_1( [], _Store ).
enquire_store_1( [Enq|Enqs], Store ) :-
	single_enquiry_for_store( Enq, Store ),
	!,
	enquire_store_1( Enqs, Store ).

% single_enquiry_for_store( Enquiry, Store ) :-
single_enquiry_for_store( act(Active), (Active,_Gr,_Rts,_Cnt,_Vs,_Fdi) ).
single_enquiry_for_store( gr(Graph), (_Act,Graph,_Rts,_Cnt,_Vs,_Fdi) ).
single_enquiry_for_store( rts(Roots), (_Act,_Gr,Roots,_Cnt,_Vs,_Fdi) ).
single_enquiry_for_store( cnt(Count), (_Act,_Gr,_Rts,Count,_Vs,_Fdi) ).
single_enquiry_for_store( vs(Variables), (_Act,_Gr,_Rts,_Cnt,Variables,_Fdi) ).
single_enquiry_for_store( fdi(FdIs), (_Act,_Gr,_Rts,_Cnt,_Vs,FdIs) ).
% single_enquiry_for_store( wgt(Weights), (_Act,_Gr,Weights,_Rts,_Cnt,_Vs) ).

store_update( InSt, Updates, OutSt ) :-
	ensure_list( Updates, ListOfUpdates ),
	update_store_1( ListOfUpdates, InSt, OutSt ).

update_store_1( [], Store, Store ).
update_store_1( [Upd|Upds], InSt, OutSt ) :-
	single_update_store( Upd, InSt, MidSt ),
	!,
	update_store_1( Upds, MidSt, OutSt ).

single_update_store( act(Active), (_OldAc,Graph,Roots,Count,Vars,FdIs), 
						    (Active,Graph,Roots,Count,Vars,FdIs)   ).
single_update_store( gr(Graph), (Active,_OldG,Roots,Count,Vars,FdIs), 
						  (Active,Graph,Roots,Count,Vars,FdIs) ).
single_update_store( rts(Roots), (Active,Graph,_OldR,Count,Vars,FdIs), 
						   (Active,Graph,Roots,Count,Vars,FdIs)  ).
single_update_store( cnt(Count), (Active,Graph,Roots,_OldC,Vars,FdIs),
						   (Active,Graph,Roots,Count,Vars,FdIs)  ).
single_update_store( vs(Vars), (Active,Graph,Roots,Count,_OLdV,FdIs),
						 (Active,Graph,Roots,Count,Vars,FdIs)  ).
single_update_store( fdi(FdIs), (Active,Graph,Roots,Count,Vars,_OldF),
						 (Active,Graph,Roots,Count,Vars,FdIs)  ).

store_built( Builts, Store ) :-
	store_empty( Empty ),
	store_update( Empty, Builts, Store ).

next_var( Var, MethodStr, InStore, OutStore ) :-
	store_enquire( InStore, [cnt(Count),act(Active),rts(Roots),gr(Graph)] ),
	mustbe_var( Var ),
	number_codes( Count, NumbCs ),
	append( NumbCs, [0'_], EscCs ),
	atom_codes( Var, EscCs ),
	NxtCount is Count + 1,
	( MethodStr = (Method,RefVar,Cnstr,Prob) -> 
		rationals_is_rat( Prob, RatPrb ),
		OutMethodStr = (NormMethod,RefVar,Cnstr,RatPrb),
		graph_add_constraint( RefVar, Cnstr, Var, Graph, NewGr ),
		NewRts = Roots,
		Nds = [RefVar-Cnstr],
		active_selects_del( [RefVar], Active, [RefVar-RefData], MidAct ),
		data_swap( rqr(ReqBy), RefData, NewReqBy, NewVDt ),
		ord_add_element( ReqBy, Var, NewReqBy ),
		active_additions( [RefVar-NewVDt], MidAct, SecAct )
		;
		Method = MethodStr,
		OutMethodStr = NormMethod,
		ord_add_element( Roots, Var, NewRts ),
		NewGr = Graph,
		Nds = [],
		SecAct = Active
	),
	method_normalise( Method, NormMethod, Fd ),
	ord_add_element( SecAct, Var-[OutMethodStr,Fd,Nds,[]], NewAct ),
	store_update( InStore, 
		[rts(NewRts),act(NewAct),cnt(NxtCount),gr(NewGr)], 
				OutStore ).

next_fdi_var( Var, Method, InStore, OutStore ) :-
	method_to_indexical( Method, Indexical ),
	goal_expansion( Var in Indexical, _, FdInCall ),
	call( FdInCall ),
	store_enquire( InStore, [fdi(FdIs),act(Active),rts(Roots)] ),
	append( FdIs, [Var], NxFdIs ),
	% length( FdIs, CrrCnt ), 
	% number_codes( CrrCnt, CrrCntCs ),
	% append( "fd_intr_v_", CrrCntCs, BBIdxCs ),
	% atom_codes( BBIdx, BBIdxCs ),
	% store_enquire( InStore, [cnt(Count),act(Active),rts(Roots),gr(Graph)] ),
	mustbe_var( Var ),
	OutMethodStr = NormMethod,
	ord_add_element( Roots, Var, NewRts ),
	% NewGr = Graph,
	Nds = [],
	SecAct = Active,
	% find FD and declare the variable as such
	% this is "currently" done in preprocess.pl
	method_normalise( Method, NormMethod, Fd ),
	length( NxFdIs, Nth ),
	( is_an_clpfd_dom(Fd,1) -> 
		( bb_get(Nth,Old) ->
			write( disposing(Nth,Old) ), nl,
			bb_delete( Nth, _ )
			;
			true
		)
		;
		bb_put( Nth, Fd )
	),
	ord_add_element( SecAct, Var-[OutMethodStr,fdv(Var,Nth),Nds,[]], NewAct ),
	store_update( InStore, 
		[rts(NewRts),act(NewAct),fdi(NxFdIs)], 
		% [rts(NewRts),act(NewAct),cnt(NxtCount),gr(NewGr)], 
				OutStore ).

method_to_indexical( Method, Indexical ) :-
	Method =.. [_Name,Dom|_PsblArgs],
	length( Dom, Length ),
	Indexical = 1..Length.

is_an_clpfd_dom( [], _ ).
is_an_clpfd_dom( [H|T], H ) :-
	Nx is H + 1,
	is_an_clpfd_dom( T, Nx ).