:-use_module('aktbus-0.3.1/prolog/src/absl.pl').
:-use_module(library('linda/client')).
:-use_module(library(lists)).
:-use_module(library(sockets)).
:-use_module(library(system)).
:-use_module(library(charsio)).


:-working_directory(_,'C:/Documents and Settings/jessicac/Desktop/sim-fbpml/comm').

find_server(Server, PID) :-
    see('server.addr'),
    read(server(Server, PID)),
    seen.

add_message(Server, PID, From, To, C):-
    my_address(FromMachine),
    address_string(Server, ToMachine),
    compose_message(FromMachine,ToMachine,C,Msg),
    template_to_tuple(C, From, To, Msg, Tuple),
    linda_client(Server:PID),
    out(Tuple),
    %writeq(Tuple),
    close_client.


gatekeeperURI("http://cara.aiai.ed.ac.uk:8000").
gatekeeperM("http://cara.aiai.ed.ac.uk:").

post_competences(Port,Name,OntoName,Competences) :-
	% assumes Competences is some arbitrary bit of prolog
	% SU is uri of SENDER
	% Name is name of solver
	% OntoName is name of the ontology that the solver uses.

	gatekeeperURI(GU),
	current_host(X),
	name(X,H),
	append("http://",H,H1),
	append(H1,":",AgentAd),
	name(Port,P),
	append(AgentAd,P,AU),
	write_to_chars(solver(Name,OntoName,Competences),QC),
	compose_message(AU,GU,QC,Msg),
	send_message(Msg).

post_competences(SU,Name,OntoName,Competences,GPort) :-
	% assumes Competences is some arbitrary bit of prolog
	% SU is uri of SENDER
	% Name is name of solver
	% OntoName is name of the ontology that the solver uses.
	% GPort is port of gatekeeper
	gatekeeperM(GM),
	name(GPort,GP),
	append(GM,GP,GU),
	%current_host(X),
	%name(X,H),
	%append("http://",H,H1),
	%append(H1,":",AgentAd),
	%name(Port,P),
	%append(AgentAd,P,AU),
	write_to_chars(solver(Name,OntoName,Competences),QC),
	compose_message(SU,GU,QC,Msg),
	send_message(Msg).

post_query(Port,Query) :-
	% assumes Query is some arbitrary bit of prolog
	% Port is port of SENDER
	gatekeeperURI(GU),
	current_host(X),
	name(X,H),
	append("http://",H,H1),
	append(H1,":",AgentAd),
	name(Port,P),
	append(AgentAd,P,AU),
	write_to_chars(query(Query),QC),
	compose_message(AU,GU,QC,Msg),
	send_message(Msg).


post_query(Port,Query,GPort) :-
	% assumes query is some arbitrary bit of prolog
	% Port is port of SENDER
	% GPort is port of gatekeeper.
	gatekeeperM(GM),
	name(GPort,GP),
	append(GM,GP,GU),
	current_host(X),
	name(X,H),
	append("http://",H,H1),
	append(H1,":",AgentAd),
	name(Port,P),
	append(AgentAd,P,AU),
	write_to_chars(query(Query),QC),
	compose_message(AU,GU,QC,Msg),
	send_message(Msg).

post_item(Port,Thing,GPort) :-
	% assumes Thing is some arbitrary bit of prolog
	% Port is port of SENDER
	% GPort is port of gatekeeper.
	gatekeeperM(GM),
	name(GPort,GP),
	append(GM,GP,GU),
	current_host(X),
	name(X,H),
	append("http://",H,H1),
	append(H1,":",AgentAd),
	name(Port,P),
	append(AgentAd,P,AU),
	write_to_chars(Thing,QC),
	compose_message(AU,GU,QC,Msg),
	send_message(Msg).

broker_read_message(Sender,C) :-
        % broker reads from local Linda server
        find_server(Server,PID),
        linda_client(Server:PID),
        in_noblock(broker(Sender,_Date,_Time,C)),
        %name(Sender,SenderURI),
        close_client.

wfe_read_message(Sender,C) :-
	% broker reads from local Linda server
	find_server(Server,PID),
	linda_client(Server:PID),
	in_noblock(wfe(Sender,_Date,_Time,C)),
	%name(Sender,SenderURI),
	close_client.

broker_post_reply(BU,To,Reply):-
	% broker reply sent direct - not via gatekeeper/Linda
	%gatekeeperM(GM),
	%name('8888',DP), % dummy value for now...
	%append(GM,DP,BU),
	!,
	write_to_chars(Reply,RC),
	compose_message(BU,To,RC,Msg),
	send_message(Msg).

post_reply(Port,To,Reply):-
	% SenderP Port,To atom
	% reply sent direct - not via gatekeeper
	number(Port),
	!,
	current_host(X),
	name(X,H),
	append("http://",H,H1),
	append(H1,":",AgentAd),
	name(Port,P),
	append(AgentAd,P,AU),
	write_to_chars(Reply,RC),
	compose_message(AU,To,RC,Msg),
	writeq(Msg),
	send_message(Msg).

post_reply(Sender,To,Reply):-
	% Sender,To are URI atoms
	% reply sent direct - not via gatekeeper
	%atom(Sender),
	!,
	write_to_chars(Reply,RC),
	compose_message(Sender,To,RC,Msg),
	writeq(Msg),
	send_message(Msg).



agent_read_message(Port,SenderURI,Message) :-
	% agent waits for message on Port
	create_aktbus_receiver(Port,RHandle),
	format("Port ~d opened\n", [Port]),
	receive_message(RHandle,Msg),
	%write(Msg),
	destroy_aktbus_receiver(RHandle),
	get_message_sender(Msg,SenderURI),
	get_message_content(Msg,Message).

agent_read_message_h(RHandle,SenderURI,Message) :-
	% agent waits for message on RHandle
	receive_message(RHandle,Msg),
	get_message_sender(Msg,SenderURI),
	get_message_content(Msg,Message).
	

get_message_sender(Msg,S):-
	get_env(Msg, 'aktbus:hasSenderURI',_,[S|_]).
get_message_content(Msg,C):-
	% this assumes that the prology content will be stored
	% as, essentially, as string in the hasSimpleMessage field.
	% jiggery-pokery to get proper parse of content!
	get_env(Msg, 'aktbus:hasSimpleMessage',_,[Content|_]),
	name(Content, TC1),
	append(TC1,".",TC), % need to append full stop!
	read_from_chars(TC,C).


read_message(Server, PID, From, To, C) :-
    template_to_tuple(C, From, To, Msg, Tuple),
    linda_client(Server:PID),
%    in(Tuple),
    in_noblock(Tuple),
    get_env_attrib_value(Msg, 'aktbus:hasSimpleMessage', _, C),
    close_client.

read_message_block(Server, PID, From, To, C) :-
    template_to_tuple(C, From, To, Msg, Tuple),
    linda_client(Server:PID),
    in(Tuple),
%    in_noblock(Tuple),
%    rd_noblock(Tuple), % doesn't remove Tuple from tspace.
    get_env_attrib_value(Msg, 'aktbus:hasSimpleMessage', _, C),
    close_client.

await_message(_, Server, PID, From, To, Goal) :-
    read_message(Server, PID, From, To, Goal), !.
await_message(N, Server, PID, From, To, Goal) :-
    sleep(1),
    N > 0, N1 is N - 1, !,
    await_message(N1, Server, PID, From, To, Goal).

template_to_tuple(solver(_,_,_), From, To, MSg, so(From,To,MSg)).
template_to_tuple(ontology(_), From, To, MSg, on(From,To,MSg)).
template_to_tuple(bridge(_), From, To, MSg, br(From,To,MSg)).
template_to_tuple(query(_), From, To, MSg, qu(From,To,MSg)).
template_to_tuple(query(_,_), From, To, MSg, que(From,To,MSg)).
template_to_tuple(answer(_), From, To, MSg, an(From,To,MSg)).
template_to_tuple(brokered(_,_), From, To, MSg, bs(From,To,MSg)).
template_to_tuple(gen_site(_,_,_), From, To, MSg, gs(From,To,MSg)).

my_address(AddressString) :-
    current_host(Machine),
    address_string(Machine, AddressString).

address_string(Machine, AddressString) :-
    concat('http://', Machine, Address),
    name(Address, AddressString).

concat(Atom1, Atom2, Concatenated) :-
    name(Atom1, A1),
    name(Atom2, A2),
    append(A1, A2, AA),
    name(Concatenated, AA).

concat_list([X], X).
concat_list([H|T], Atom) :-
    \+ T = [],
    concat_list(T, AT),
    concat(H, AT, Atom).

assert_if_new(Fact) :-
    \+ Fact,
    assert(Fact), !.
assert_if_new(_).

%assert_list([H|T]) :-
%    assert(H),
%    assert_list(T).
%assert_list([]).


assert_list([c(A,B,C,D)|T],Name) :-
	assert(capability(Name,A,B,C,D)),
	assert_list(T,Name).
assert_list([],_).

assert_list([H|T]) :-
    \+ H = c(_A,_B,_C,_D),
    assert(H),
    assert_list(T).
assert_list([]).


set_timeout(Secs:MSecs) :-
    integer(Secs),
    Secs >= 0,
    integer(MSecs),
    MSecs >= 0, MSecs < 1000,
    linda_timeout(_, Secs:MSecs).
