%
%  Natural language semantic analyser
%
%  Extracts semantic information from subtrees
%  of parse tree. Currently assumes that actor,
%  object, object_s, date and env are terminal
%  values in the grammar & knowledge base.
%

analyseSemantics(actor, ActorTree) :-
	parseSemantics(OldActor, Object, Date, Env),
	extractActor([actor|ActorTree], Actor),
	string_length(Actor, ActLen),
	string_length(OldActor, OldLen),
	((ActLen > OldLen ; OldActor = 'unknown') -> NewActor = Actor
	; NewActor = OldActor),
	retractall(parseSemantics(_,_,_,_)),
	asserta(parseSemantics(NewActor, Object, Date, Env)),
	!.
analyseSemantics(object, ObjectTree) :-
	parseSemantics(Actor, OldObject, Date, Env),
	extractObject([object|ObjectTree], Object),
	string_length(Object, ObjLen),
	string_length(OldObject, OldLen),
	((ObjLen > OldLen ; OldObject = 'unknown') -> NewObject = Object
	; NewObject = OldObject),
	retractall(parseSemantics(_,_,_,_)),
	asserta(parseSemantics(Actor, NewObject, Date, Env)),
	!.
analyseSemantics(object_s, Object_sTree) :-
	parseSemantics(Actor, OldObject, Date, Env),
	extractObject([object_s|Object_sTree], Object),
	string_length(Object, ObjLen),
	string_length(OldObject, OldLen),
	((ObjLen > OldLen ; OldObject = 'unknown') -> NewObject = Object
	; NewObject = OldObject),
	retractall(parseSemantics(_,_,_,_)),
	asserta(parseSemantics(Actor, NewObject, Date, Env)),
	!.
analyseSemantics(date, DateTree) :-
	parseSemantics(Actor, Object, OldDate, Env),
	extractDate([date|DateTree], Date),
	string_length(Date, DateLen),
	string_length(OldDate, OldLen),
	((DateLen > OldLen ; OldDate = 'unknown') -> NewDate = Date
	; NewDate = OldDate),
	retractall(parseSemantics(_,_,_,_)),
	asserta(parseSemantics(Actor, Object, NewDate, Env)),
	!.
analyseSemantics(env, EnvTree) :-
	parseSemantics(Actor, Object, Date, OldEnv),
	extractEnv([env|EnvTree], Env),
	string_length(Env, EnvLen),
	string_length(OldEnv, OldLen),
	((EnvLen > OldLen ; OldEnv = 'unknown') -> NewEnv = Env
	; NewEnv = OldEnv),
	retractall(parseSemantics(_,_,_,_)),
	asserta(parseSemantics(Actor, Object, Date, NewEnv)),
	!.
analyseSemantics(whoClause,_) :-
	parseSemantics(Actor, Object, Date, Env),
	(Actor = 'unknown' -> NewActor = 'goal'
	; NewActor = Actor),
	retractall(parseSemantics(_,_,_,_)),
	asserta(parseSemantics(NewActor, Object, Date, Env)).
analyseSemantics(whatClause,_) :-
	parseSemantics(Actor, Object, Date, Env),
	(Object = 'unknown' -> NewObject = 'goal'
	; NewObject = Object),
	retractall(parseSemantics(_,_,_,_)),
	asserta(parseSemantics(Actor, NewObject, Date, Env)).
analyseSemantics(whenClause,_) :-
	parseSemantics(Actor, Object, Date, Env),
	(Date = 'unknown' -> NewDate = 'goal'
	; NewDate = Env),
	retractall(parseSemantics(_,_,_,_)),
	asserta(parseSemantics(Actor, Object, NewDate, Env)).
analyseSemantics(whereClause,_) :-
	parseSemantics(Actor, Object, Date, Env),
	(Env = 'unknown' -> NewEnv = 'goal'
	; NewEnv = Env),
	retractall(parseSemantics(_,_,_,_)),
	asserta(parseSemantics(Actor, Object, Date, NewEnv)).
analyseSemantics(_,_) :-
	!.

extractActor([], []).
extractActor([actor|TreeRemainder], Actor) :-
	TreeRemainder = [ActorPart|ActorRemainder],
	ActorPart = [actorPart, [ActorHead]],
	(ActorRemainder = [] -> 
	Actor = ActorHead
	; [InnerRemainder] = ActorRemainder,
	string_concat(ActorHead, ' ', ActorBeginning),
	extractActor(InnerRemainder, ActorTail),
	string_concat(ActorBeginning, ActorTail, Actor)),
	!.

extractObject([], []).
extractObject([object|TreeRemainder], Object) :-
	TreeRemainder = [ObjectPart|ObjectRemainder],
	ObjectPart = [objectPart, [ObjectHead]],
	(ObjectRemainder = [] -> 
	Object = ObjectHead
	; [InnerRemainder] = ObjectRemainder,
	string_concat(ObjectHead, ' ', ObjectBeginning),
	extractObject(InnerRemainder, ObjectTail),
	string_concat(ObjectBeginning, ObjectTail, Object)),
	!.
extractObject([object_s|TreeRemainder], Object) :-
	TreeRemainder = [ObjectNode|Object_sRemainder],
	ObjectNode = [object|[ObjectPart]],
	ObjectPart = [objectPart, [ObjectHead]],
	(Object_sRemainder = [] -> 
	Object = ObjectHead
	; [InnerRemainder] = Object_sRemainder,
	string_concat(ObjectHead, ' ', ObjectBeginning),
	extractObject(InnerRemainder, ObjectTail),
	string_concat(ObjectBeginning, ObjectTail, Object)),
	!.
extractObject([objectPart_s|TreeRemainder], Object) :-
	[InnerRemainder] = TreeRemainder,
	[Object_s] = InnerRemainder,
	string_concat(Object, 's', Object_s),
	!.

extractDate([], []).
extractDate([date|TreeRemainder], Date) :-
	TreeRemainder = [DatePart|DateRemainder],
	(DatePart = [datePart, [DateHead]] ; DatePart = [year, [DateHead]]),
	(DateRemainder = [] -> 
	InnerRemainder = [],
	Date = DateHead
	; [InnerRemainder] = DateRemainder,
	string_concat(DateHead, ' ', DateBeginning),
	extractDate(InnerRemainder, DateTail),
	string_concat(DateBeginning, DateTail, Date)),
	!.

extractEnv([], []).
extractEnv([env|TreeRemainder], Env) :-
	TreeRemainder = [EnvPart|EnvRemainder],
	EnvPart = [envPart, [EnvHead]],
	(EnvRemainder = [] -> 
	InnerRemainder = [],
	Env = EnvHead
	; [InnerRemainder] = EnvRemainder,
	string_concat(EnvHead, ' ', EnvBeginning),
	extractEnv(InnerRemainder, EnvTail),
	string_concat(EnvBeginning, EnvTail, Env)),
	!.

%
%  Match up semantic information with the event knowledge base
%

makeQuery :-
	parseSemantics(Actor, Object, Date, Env),
	(Actor = 'unknown' -> true
	; (Actor = 'goal' ->
		outputGoals(ActorGoal, ObjectGoal, DateGoal, EnvGoal),
		retractall(outputGoals(_,_,_,_)),
		asserta(outputGoals(yes, ObjectGoal, DateGoal, EnvGoal))
		; string_to_atom(Actor, QueryActor))),
	(Object = 'unknown' -> true
	; (Object = 'goal' ->
		outputGoals(ActorGoal, ObjectGoal, DateGoal, EnvGoal),
		retractall(outputGoals(_,_,_,_)),
		asserta(outputGoals(ActorGoal, yes, DateGoal, EnvGoal))
		; string_to_atom(Object, QueryObject))),
	(Date = 'unknown' -> true
	; (Date = 'goal' ->
		outputGoals(ActorGoal, ObjectGoal, DateGoal, EnvGoal),
		retractall(outputGoals(_,_,_,_)),
		asserta(outputGoals(ActorGoal, ObjectGoal, yes, EnvGoal))
		; string_to_atom(Date, QueryDate))),
	(Env = 'unknown' -> true
	; (Env = 'goal' ->
		outputGoals(ActorGoal, ObjectGoal, DateGoal, EnvGoal),
		retractall(outputGoals(_,_,_,_)),
		asserta(outputGoals(ActorGoal, ObjectGoal, DateGoal, yes))
		; string_to_atom(Env, QueryEnv))),
	findall(QueryActor, event_frame(QueryActor, QueryObject, QueryDate, QueryEnv), ActorList),
	findall(QueryObject, event_frame(QueryActor, QueryObject, QueryDate, QueryEnv), ObjectList),
	findall(QueryDate, event_frame(QueryActor, QueryObject, QueryDate, QueryEnv), DateList),
	findall(QueryEnv, event_frame(QueryActor, QueryObject, QueryDate, QueryEnv), EnvList),
	createResponse(ActorList, ObjectList, DateList, EnvList).

createResponse([], [], [], []) :-
	parseSemantics(Actor, Object, Date, Env),
	nl, nl,
	write('Sorry, but there was no information available about '),
	((Actor = 'unknown' ; Actor = 'goal') -> write('anybody')
	; write(Actor)),
	write(' inventing '),
	((Object = 'unknown' ; Object = 'goal') -> write('anything')
	; write('the '), write(Object)),
	((Date = 'unknown' ; Date = 'goal') -> true
	; write(' in '), write(Date)),
	((Env = 'unknown' ; Env = 'goal') -> true
	; write(' in '), write(Env)),
	write('.'),
	!.
createResponse([Actor], [Object], [Date], [Env]) :-
	nl,
	parseSemantics(_, ObjectSem, DateSem, EnvSem),
	write(Actor), 
	write(' invented'), 
	(ObjectSem = 'unknown' -> true
	; write(' the '), write(Object)),
	(DateSem = 'unknown' -> true
	; write(' in '), write(Date)),
	(EnvSem = 'unknown' -> true
	; write(' in '), write(Env)),
	write('.'),
	!.
createResponse(ActorList, ObjectList, DateList, EnvList) :-
	write('There was no single response that matched to your query.'), nl,
	write('However, the following events contained related information that may answer your question: '), nl,
	displayResponses(ActorList, ObjectList, DateList, EnvList).

displayResponses([], [], [], []).
displayResponses([Actor|ActorList], [Object|ObjectList], [Date|DateList], [Env|EnvList]) :-
	write('      '),
	createResponse([Actor], [Object], [Date], [Env]), nl,
	displayResponses(ActorList, ObjectList, DateList, EnvList).



