%
% KRAFT service layer of config file handling
%
:- module(ksl,[	read_agent_config/0,	%get config from either command line or file
		read_config/1,		%read a config file into memory
		set_config/2,		%set value of a config parameter in memory
		get_config/2,		%get config parameter value
		clear_config/0		%clear up config in memory
	]).

:- [prolog_detect].
:- [cmdline].
:- ['../pillow/pillow'].

:- prolog_detect:prolog(Prolog),
	(	(	Prolog=sicstus,
			!,
			use_module(library(lists))
		);
		(	Prolog=pfdm,
			!,
			use_module(library(lists))
		);
		(	Prolog=eclipse,
			!,
			[retractall]
		),
		true
	).


:- dynamic(config/2).

%
% get agent config from command line or file
% command line arguments have higher priority & overrides config in file
%
read_agent_config :-
	read_config_file_if_any(Hf,Pf),
	read_text_address_file_if_any(Ht,Pt),
	read_prolog_address_file_if_any(Hp,Pp),
	read_xml_address_file_if_any(Hx,Px),
	read_command_line_if_any(Hc,Pc),
	get_first_instantiated([Hc,Hx,Hp,Ht,Hf],Host),
	get_first_instantiated([Pc,Px,Pp,Pt,Pf],Port),

	set_config(linda_host,Host),
	set_config(linda_port,Port).

%
% go through a list and a value from it
% elements later in the list take higher priority
%
get_first_instantiated([],_).
get_first_instantiated([H|_],H) :-
	nonvar(H).
get_first_instantiated([H|T],Value) :-
	var(H),
	get_first_instantiated(T,Value).


%
% read config file & instantiate host+port, if possible
%
read_config_file_if_any(Host,Port) :-
	cmdline:get_command_line('-c',Config_file),
	read_config(Config_file),
	(	(	get_config(linda_host,Host),
			!
		);
		true
	),
	(	(	get_config(linda_port,Port),
			!
		);
		true
	),
	!.
read_config_file_if_any(_,_).

%
% get host+port from command line if possible
%
read_command_line_if_any(Host,Port) :-
	(	cmdline:get_command_line('-lh',Host),
		!;
		true
	),
	(	cmdline:get_command_line('-lp',Port),
		!;
	true
	).



read_text_address_file_if_any(_Host,_Port) :-
%	cmdline:get_command_line('-at',Filename),
%	see(Filename),
%	seen,
	!.
%read_text_address_file_if_any(_,_).

%
% read host+port from a Prolog file
%
read_prolog_address_file_if_any(Host,Port) :-
	cmdline:get_command_line('-ap',Filename),
	open(Filename,read,Read_stream),
	read(Read_stream,linda_host(Host)),
	read(Read_stream,linda_port(Port)),
	close(Read_stream),
	!.
read_prolog_address_file_if_any(_,_).

%
% read host+port from an XML file by HTTP
%
read_xml_address_file_if_any(Host,Port) :-
	cmdline:get_command_line('-ax',Url_as_atom),
	pillow:url_info(Url_as_atom,Url_as_term), 				%make URL into a term
	pillow:fetch_url(Url_as_term,[],Response),				%fetch URL
	member(status(success,_,_),Response),				%check for success
	member(content(Content_string),Response),
	pillow:xml2terms(Content_string,Xml_tree),				%parse into XML tree
	member(env(linda_server,_,Linda_server_subtree),Xml_tree),	%look for 'linda_server' environment
	member(env(host,_,[Host_string]),Linda_server_subtree),		%look for host & port under it
	member(env(port,_,[Port_string]),Linda_server_subtree),
	name(Host,Host_string),						%convert strings back to atom/integer
	name(Port,Port_string),
	!.
read_xml_address_file_if_any(_,_).



%
% read in a config file
%

read_config(Filename) :-
	clear_config,
	open(Filename,read,R),
	read_entries(R),
	close(R),
	!.

read_entries(R) :-
	repeat,
	read(R,Term),
	(	Term=end_of_file;
		(store_config(Term),
		fail)
	).

%
% store a parameter value into memory
%
store_config(config(A,B)) :-
	call(config(A,B)),	%same tuple exist
	!.
store_config(config(A,B)) :-
	call(config(A,X)),	%same key but different value
	!,
	retract(config(A,X)),	%remove old one
	assert(config(A,B)).	%assert new one
store_config(config(A,B)) :-
	assert(config(A,B)).	%just assert it


%
% clear old config
%

clear_config :-
	retractall(config(_,_)).

get_config(Name,Value) :-
	config(Name,Value).

set_config(Name,Value) :-
	store_config(config(Name,Value)).

