/*************************************************************************

         name: lexicon_vcr_english.pl 
      version: 
  description: 
       author: Staffan Larsson
 
*************************************************************************/

:- module( lexicon_vcr_english, [resource_of_type/1,
				 output_form/2, input_form/2,
				 yn_answer/1]).

resource_of_type(lexicon).


:- discontiguous output_form/2, input_form/2, plan/2, postcond/2.



:- use_module( library(lists), [ member/2, select/3, append/3 ] ).
:- use_module( library(charsio), [ format_to_chars/3 ] ).

:- ensure_loaded( library(lexicon_numbers) ).
:- ensure_loaded( library(digits_english) ).
%:- ensure_loaded( library(lexicon_general_english) ).

:- ensure_loaded( library( semsort_vcr ) ).


%:- multifile( output_form/2 ).
%:- multifile( input_form/2 ).

/*----------------------------------------------------------------------
     output_form( +Move, -String )
     -- Canned output
----------------------------------------------------------------------*/

% ask-moves

output_form( ask(X^(action(X))), ['What can I do for you?'] ).

output_form( ask(action(T)), Str ):-
	output_form(action(T), StrT ),
	append( ['Do you want to '], StrT, Str0 ),
	append( Str0, ['?'], Str).


output_form( ask(X^new_channel(X)),
	     ['What channel do you want?'] ).

output_form( ask(X^channel_to_store(X)),
	     ['What channel do you want?'] ).
output_form( ask(X^date_to_store(X)),
	     ['What date?'] ).
output_form( ask(X^start_time_to_store(X)),
	     ['What time do you want to start recording?'] ).
output_form( ask(X^stop_time_to_store(X)),
	     ['What time do you want to stop recording?'] ).

output_form( ask(X^program_to_delete(X)),
	     ['What program to want to delete?'] ).

output_form( ask(X^new_clock(X)),
	     ['What time?'] ).

% action

output_form( action(change_language), ['change language'] ).
output_form( action(change_domain), ['change domain'] ).

output_form( action(vcr_top), ['go the VCR manager'] ).
output_form( action(vcr_change_play_status), ['change play status'] ).
output_form( action(vcr_timer_recording), ['go to timer recording'] ).
output_form( action(vcr_settings), ['go to settings'] ).
%output_form( action(vcr_query), ['make a query'] ).
output_form( action(vcr_new_channel), ['change channel'] ).
output_form( action(vcr_play), ['play'] ).
output_form( action(vcr_stop), ['stop'] ).
output_form( action(vcr_ff), ['fast-forward'] ).
output_form( action(vcr_rew), ['rewind'] ).
output_form( action(vcr_pause_still), ['pause'] ).
output_form( action(vcr_still_adv), ['advance'] ).
output_form( action(vcr_rec), ['record'] ).
output_form( action(vcr_add_program), ['add a program'] ).
output_form( action(vcr_add_program1), ['add a program'] ).
output_form( action(vcr_delete_program), ['delete a program'] ).
output_form( action(vcr_delete_program1), ['delete a program'] ).
output_form( action(vcr_set_clock), ['set the clock'] ).
%output_form( action(vcr_query_status), ['query the current play status'] ).
%output_form( action(vcr_query_channel), ['find out what channel is on'] ).

% special SL021125
output_form( stop_time_to_store(T), [until|S]):-
	output_form(time(T), S).
output_form( start_time_to_store(T), [from|S]):-
	output_form(time(T), S).


output_form( action(vcr_turnontv), ['turn on the t v'] ).
output_form( action(vcr_turnofftv), ['turn off the t v'] ).

output_form( icm:acc*neg:action(vcr_turnofftv), ['Sorry, I cannot control the TV set.'] ).
output_form( icm:acc*neg:action(vcr_turnontv), ['Sorry, I cannot control the TV set.'] ).

output_form( icm:acc*neg:action(vcr_play,already), ['The VCR is already playing.'] ).
output_form( confirm(vcr_play), ['The VCR is now playing.'] ).
output_form( icm:acc*neg:action(vcr_stop, already), ['The VCR is already stopped.'] ).
output_form( confirm(vcr_stop), ['The VCR is now stopped.'] ).
output_form( icm:acc*neg:action(vcr_ff, already), ['The VCR is already fast-forwarding.'] ).
output_form( confirm(vcr_ff), ['The VCR is now fast-forwarding.'] ).
output_form( icm:acc*neg:action(vcr_rewind, already), ['The VCR is already rewinding.'] ).
output_form( confirm(vcr_rew), ['The VCR is now rewinding.'] ).
output_form( icm:acc*neg:action(vcr_pause_still, already), ['The VCR is already paused.'] ).
output_form( confirm(vcr_pause_still), ['The VCR is now paused.'] ).
output_form( icm:acc*neg:action(vcr_rec, already), ['The VCR is already recording.'] ).
output_form( confirm(vcr_rec), ['The VCR is now recording.'] ).

output_form( confirm(vcr_still_adv), ['The VCR is forwarding slowly.'] ).%??
output_form( answer(not(vcr_paused)), ['The VCR is not paused.'] ).
output_form( icm:acc*neg:action(vcr_add_program,no_available_program_slot), ['There is no available program slot.'] ).
output_form( confirm(vcr_set_clock), ['The clock was set.'] ).

output_form( confirm(vcr_change_channel(P)), Cs ) :-
	format_to_chars( 'OK. Switched to channel ~a.\n', [P], Cs ).
output_form( confirm(vcr_new_channel), ['The channel was changed'] ).

output_form( confirm(vcr_add_program(Position,Date,Start,Stop)), Cs ) :-
	date_output(Date,DateOutput),
	atom_chars(Start,[Start1,Start2,Start3,Start4]),
	atom_chars(Stop,[Stop1,Stop2,Stop3,Stop4]),
	format_to_chars( 'OK, I will record channel ~a ~a from ~c~c:~c~c to ~c~c:~c~c.',
			 [Position,DateOutput,
			  Start1,Start2,Start3,Start4,
			  Stop1,Stop2,Stop3,Stop4], Cs ).

output_form( confirm(vcr_add_program), ['The program has been added.'] ).

output_form( answer(programs(Programs)), Cs ) :-
	program_listing( Programs, Listing ),
	append( 'The current programs are\n', Listing, Cs ).

output_form( ask(X^program_to_delete(X)), ['Which program number to you want to delete?'] ).

output_form( icm:acc*neg:action( vcr_delete_program, no_program_to_delete ), ['There is no program to delete.'] ).
output_form( confirm(vcr_delete_program), ['OK. The program was deleted.'] ).
%output_form( report( 'DeleteProgram', failed(no_such_program)), ['No program is stored in that position.'] ).

output_form( icm:acc*neg:program_to_delete(_N), ['No program is stored in that position.'] ).



output_form( icm:acc*neg:new_channel(_), ['Sorry, the available channels are 1 to 99.'] ).


output_form( answer(play_status(S)), ['The VCR is ',SO] ) :-
	status_output(S,SO).

output_form( answer(not(play_status(S))), ['No, the VCR is not ',SO] ) :-
	status_output(S, SO).

%output_form( answer(not(play_statusstatus(S))), Cs ) :-
%	status_output(S,SO),
%	format_to_chars( 'The VCR is not ~a.', [SO], Cs ).

%output_form( answer(current_channel(P)), Cs ) :-
%	format_to_chars( 'The current channel is ~a.', [P], Cs ).
output_form( answer(current_channel(P)), ['The current channel is', P ] ).



output_form( greet, ['Welcome to the VCR manager!'] ).
output_form( quit, ['Good bye!'] ).


output_form( new_clock(T), S ):-
	output_form( time(T), S );
	input_form( S, answer(time(T)) ).

%output_form( start_time_to_store(T), [from,S]):-
%	output_form(time(T), S).

% o'clock case for time output (others handled by inputform)
% SL 021125
output_form( time(T), [S]):-
	name( T, TS),
	TS = [HS,48,48],
	append( [HS], " o clock",SS),
	name(S, SS).



output_form( ask(X^language(X)), ['What language do you want to use?'] ).
output_form( ask([language(_X)|_]), ['Do you want to use English or Swedish?'] ). % HACK

%SL 021125
output_form( ask(X^domain(X)), ['What domain do you want?'] ).
output_form( ask([domain(_X)|_]), ['Do you want to use the VCR or the telephone?'] ). % HACK


date_output(today,today) :- !.

date_output(Date,DateOutput) :-
	atom_chars(Date,Chars),
	format_to_chars('~c~c/~c~c',Chars,DateOutputCs),
	atom_chars(DateOutput,DateOutputCs).

status_output(ff,'fast-forwarding') :- !.
status_output(S,S).

altlist2altstr_and( [D], Str ):-
	alt2altstr( D, Str1 ),
	append( " and ", Str1, Str ).
altlist2altstr_and( [D|Ds], Str ):-
	alt2altstr( D, Str1 ),
	altlist2altstr_and( Ds, Str2 ),
	append( Str1, ", ", Str3 ),
	append(Str3, Str2, Str ).

altlist2altstr_or( [D], Str ):-
	alt2altstr( D, Str1 ),
	append( " or ", Str1, Str ).
altlist2altstr_or( [D|Ds], Str ):-
	alt2altstr( D, Str1 ),
	altlist2altstr_or( Ds, Str2 ),
	append( Str1, ", ", Str3 ),
	append(Str3, Str2, Str ).

alt2altstr( D, Str ):-
	output_form( D, Str ).

alt2altstr( D, Str ):-
	name( D, Str ).

program_listing( [], "" ).

program_listing( [N:(Position,Date,Start,Stop)|Programs], Listing ) :-
	atom_chars(Date,[Date1,Date2,Date3,Date4]),
	atom_chars(Start,[Start1,Start2,Start3,Start4]),
	atom_chars(Stop,[Stop1,Stop2,Stop3,Stop4]),
	format_to_chars( 'Number ~d: position ~a, ~c~c/~c~c, from ~c~c:~c~c to ~c~c:~c~c;\n',
			 [N,Position,
			  Date1,Date2,Date3,Date4,
			  Start1,Start2,Start3,Start4,
			  Stop1,Stop2,Stop3,Stop4], This ),
	program_listing( Programs, Rest ),
	append( This, Rest, Listing ).

capitalize(A,[CC|Cs]) :-
	atom_chars(A,[C|Cs]),
	cap_char(C,CC).

cap_char(A,B) :-
	A >= 0'a,
	A =< 0'z,
	!,
	B is A - 32.

cap_char(A,A).


/*----------------------------------------------------------------------
     input_form( +Phrase, -Move )
     -- Almost canned input
----------------------------------------------------------------------*/

% generic

input_form( [go,up],           request(up) ).
input_form( [language],        request(change_language) ).
input_form( [english], answer(language(english)) ).
input_form( [swedish], answer(language(svenska)) ).
input_form( [svenska], answer(language(svenska)) ).

% SL021125
input_form( [domain], request(change_domain) ).
input_form( [telephone], answer(domain(telephone)) ).
input_form( [vcr], answer(domain(vcr)) ).

% VCR


%input_form( [top],             request(vcr_top) ).
input_form( [top],             request(top) ).
input_form( [play,status],     request(vcr_change_play_status) ).
input_form( [timer,recording], request(vcr_timer_recording) ).
input_form( [add,a,program],   request(vcr_add_program) ).
input_form( [add,program],     request(vcr_add_program) ).
input_form( [delete,program],  request(vcr_delete_program) ).
input_form( [delete,a,program],request(vcr_delete_program) ).
input_form( [settings],        request(vcr_settings) ).
input_form( [clock],           request(vcr_set_clock) ).
% this will be rejected by system
input_form( [turn,off,the,t,v],           request(vcr_turnofftv) ).
input_form( [turn,on,the,t,v],           request(vcr_turnontv) ).

input_form( [change,channel],  request(vcr_new_channel ) ).
input_form( [switch,channel],  request(vcr_new_channel ) ).
input_form( [switch,to],  request(vcr_new_channel ) ).
input_form( [specific,channel],request(vcr_new_channel ) ).

input_form( [increase,channel], [ request(vcr_increase_channel) ] ).
input_form( [next,channel],  [ request(vcr_increase_channel) ] )  .

input_form( [decrease,channel], [ request(vcr_decrease_channel ) ] ).
input_form( [previous,channel], [ request(vcr_decrease_channel ) ] ).

input_form( [play],            request(vcr_play) ).
input_form( [stop],            request(vcr_stop) ).
input_form( [forward],         request(vcr_ff) ).
input_form( [rewind],          request(vcr_rew) ).
input_form( [pause],           request(vcr_pause_still) ).
input_form( [advance],         request(vcr_still_adv) ).
input_form( [record],          request(vcr_rec) ).

input_form( [today],           answer(date_to_store(today)) ).

input_form( [playing],         ask( play_status( playing ) ) ).
input_form( [paused],          ask( play_status( paused ) ) ).
input_form( [stopped],         ask( play_status( stopped ) ) ).
input_form( [rewinding],       ask( play_status( rewinding ) ) ).
input_form( [forwarding],      ask( play_status( ff ) ) ).
input_form( [recording],       ask( play_status(recording) ) ).
input_form( [vcr,doing],       ask( X^play_status(X) ) ).

input_form( [what,channel],    ask(X^current_channel(X)) ).
input_form( [which,channel],   ask(X^current_channel(X)) ).

input_form( [ from | [ S1, S2 ] ], answer( start_time_to_store( C ) ) ) :-
	input_form( [ S1, S2 ], answer(time(C)) ).

input_form( [ until | [ S1, S2 ] ], answer( stop_time_to_store( C ) ) ) :-
	input_form( [ S1, S2 ], answer(time(C)) ).
input_form( [ to | [ S1, S2 ] ], answer( stop_time_to_store( C ) ) ) :-
	input_form( [ S1, S2 ], answer(time(C)) ).

%input_form( [ switch, to, channel | S ], answer( new_channel( C ) ) ) :-
%	lexsem( S, C ),
%	sem_sort( C, channel ).

% ???
%input_form( [ record, channel | L ], answer( channel_to_store(P)) ) :-
%	lexsem( S, C ),
%sem_sort( C, channel ).

input_form( [ channel | S ], answer( channel( C ) ) ) :-
	lexsem( S, C ),
%	sem_sort( C, channel ).
	sem_sort( C, number ).



input_form( [ set, the, clock, to | [ S1, S2 ] ], [ request( vcr_set_clock ), answer( new_clock( C ) ) ] ) :-
	input_form( [ S1, S2 ], answer(time(C)) ).


% time: two numbers in sequence

input_form( [S1,S2] , answer( time( C ) ) ) :-
	lexsem( [S1], C1 ),
	sem_sort( C1, number ),
	lexsem( [S2], C2 ),
	sem_sort( C2, number ),
	name( C1, C1S ),
	name( C2, C2S ),
	append( C1S, C2S, CS ),
	name( C, CS ),
	sem_sort( C, time ).

% time: X o'clock
input_form( [S1,oclock] , answer( time( C ) ) ) :-
	lexsem( [S1], C1 ),
	sem_sort( C1, number ),
	name( C1, C1S ),
	append( C1S, "00", CS ),
	name( C, CS ),
	sem_sort( C, time ).


% numbers

input_form( S, answer( number( C ) ) ) :-
	lexsem( S, C ),
	sem_sort( C, number ).



/*----------------------------------------------------------------------
     output_form( +Move, -WordList )
     -- Canned output
----------------------------------------------------------------------*/

% addded 021120 SL, used in positive feedback
output_form( X^play_status(X), ['what the vcr is doing']):-!.
output_form( play_status(playing), ['whether the vcr is playing']):-!.
output_form( play_status(stopped), ['whether the vcr is stopped']):-!.

% object-level clarification and groundnig questions
output_form( ask(C), Output  ):-
	output_form( icm:und*pos:_*C, IcmPos ),
	append( IcmPos0,['.'],IcmPos),
%	append( IcmPos0, [', is that correct?'], Output ).
	append( IcmPos0, ['?'], Output ).


%SL021125
output_form( ask(set([Alt0|Alts])), Output):-
	Alt0=action(_),!,
	output_form(Alt0, Alt0out),
	altlist2alts_or( Alts, AltsOr ),
%	append(['Do you mean'|Alt0out], AltsOr, Output0 ),
	append(['Do you want to '|Alt0out], AltsOr, Output0 ),
	append(Output0, ['?'], Output).
output_form( ask(set([Alt0|Alts])), Output):-
	output_form(Alt0, Alt0out),
	altlist2alts_or( Alts, AltsOr ),
	append(['Do you want '|Alt0out], AltsOr, Output0 ),
%	append([''|Alt0out], AltsOr, Output0 ),
	append(Output0, ['?'], Output).

altlist2alts_or( [Alt], ['or'|OutputAlt] ):-
	output_form(Alt, OutputAlt ).
altlist2alts_or( [Alt|Alts], [','|Output] ):-
	output_form(Alt, OutputAlt ),
	altlist2alts_or(Alts, AltsOr),
	append( OutputAlt, AltsOr, Output).

output_form( Alt, OutputAlt ):-
	input_form( OutputAlt, answer( Alt ) ).



% db entries

output_form( answer( db_entry( _PropList, set(NewPropList), P ) ), [''|Output ] ):-
	output_forms( NewPropList, NewPropListOut ),
	output_form( answer( P ), AnswerOut ),
	append( AnswerOut, NewPropListOut, Output ).

%output_form( answer( db_entry( set( List )  ) ), Output ):-
%	output_forms( List, Output ).

output_forms( [], [] ).
output_forms( [ Move | Moves ], Output1 ):-
	output_form( Move, Output ),
	output_forms( Moves, Outputs ),
	append( Output, Outputs, Output1 ).
	


				%
				%output_form( answer( db_entry( PropList, P ) ), Output ):-
%	output_forms( PropList, PropOutput ),
%	output_form( answer( P ), AnsOutput ),
%	append( PropOutput, ['.'.


output_form( answer(notexist(X,Q)), ['Sorry, there is nothing matching your request about '|InputQDot]):-
	input_form( InputQ, ask(X^Q) ),
	append( InputQ, ['.'], InputQDot ).
output_form( answer(unknown(Q)), ['Sorry, there is nothing matching your request about '|InputQDot]):-
	input_form( InputQ, ask(Q) ),
	append( InputQ, ['.'], InputQDot ).

% for asking metaissue clarification question
output_form( issue(Q), ['to ask about'|Out] ):-
	input_form( Out, ask( Q ) ).


% for asking metaissue clarification question
%output_form( action(Action), ['to '|Out] ):-
%	input_form( Out, request( Action ) ).

% ICM

% contact
output_form( icm:con*neg, ['Hello?'] ).


% perception
output_form( icm:per*int, ['Pardon?'] ).
output_form( icm:per*int, ['What did you say?'] ).
output_form( icm:per*neg, ['Sorry, I didnt hear what you said.'] ).

output_form( icm:per*pos:String, ['I heard you say',Name,'. '] ):-
	name( Name, String ).

output_form( icm:sem*int, ['What do you mean'] ).
output_form( icm:sem*neg, ['Sorry, I dont understand.'] ).
output_form( icm:sem*pos:Move, InputDot ):-
	input_form( Input, Move ),
	append( Input, ['.'], InputDot ).



% understanding(pragmatic)
output_form( icm:und*neg, ['I dont quite understand.']  ).

% first clause added 021120 SL
output_form( icm:und*pos:usr*issue(Q), ['You want to know '|AnsPDot]  ):-
	output_form( Q, AnsP ),
	append(AnsP,['.'],AnsPDot).

output_form( icm:und*pos:usr*issue(Q), ['You want to know about'|AnsPDot]  ):-
	input_form( AnsP, ask( Q ) ),
	append(AnsP,['.'],AnsPDot).
output_form( icm:und*pos:usr*(not issue(Q)), ['You did not ask about'|AnsPDot]  ):-
	input_form( AnsP, ask( Q ) ),
	append(AnsP,['.'],AnsPDot).


output_form( icm:und*pos:usr*(not P), AnsNotPDot  ):-
	output_form( icm:und*pos:usr*P, AnsPDot  ),
	append( ['not'],AnsPDot,AnsNotPDot ).

output_form( icm:und*pos:usr*P, AnsPDot  ):-
	( output_form(P, AnsP);
	    input_form( AnsP, answer(P) ) ),
	append(AnsP,['.'],AnsPDot).

% special cases; could make use of isa-hierarchy
%output_form( icm:und*pos:usr*channel_to_store(X), IcmPos  ):-
%	output_form( icm:und*pos:usr*channel(X), IcmPos ).
%output_form( icm:und*pos:usr*new_channel(X), IcmPos  ):-
%	output_form( icm:und*pos:usr*channel(X), IcmPos ).

% 020702 SL
output_form( icm:und*pos:usr*PX, IcmPos ):-
	PX =.. [P,X],
	isa( P, P1 ),
	P1X =.. [P1,X],
	output_form( icm:und*pos:usr*P1X, IcmPos ).



output_form( icm:und*int:usr*C, IcmInt  ):-
	output_form( ask(C), IcmInt ).
	%output_form( icm:und*pos:C, IcmPos ),
	%append( IcmPos0,['.'],IcmPos),
	%append( IcmPos0, [', is that correct?'], IcmInt ).

%output_form( icm:und*int:usr*C, IcmInt  ):-
%	input_form( answer(C), IcmInt ).


output_form( icm:und*int:usr*C, Output  ):-
	output_form( icm:und*pos:_*C, IcmPos ),
	append( IcmPos0,['.'],IcmPos),
	append( IcmPos0, [', is that correct?'], Output ).




% clarification question
output_form( icm:und*int:usr*AltQ, Output):-
	output_form( ask(AltQ), Output).



% "acceptance"/integration

% icm-Type(-Polarity(-Args))
output_form( icm:acc*pos, ['Okay.'] ).

% reject(issue(Q))
output_form( icm:acc*neg:issue(Q), ['Sorry, I cannot answer questions about'|InputQDot]):-
	input_form( InputQ, ask(Q) ),
	append( InputQ, ['.'], InputQDot ).

% reject proposition P
output_form( icm:acc*neg:P, ['Sorry, '|Rest]):-
	input_form( InputP, answer(P) ),
	append( InputP, [' is not a valid parameter.'], Rest ).

% indicate loading a plan (pushed by findPlan)
%output_form( icm:loadplan, ['I need some information.'] ).
output_form( icm:loadplan, ['Lets see.'] ).


% reraise issue explicitly (feedback on user reraise, or system-initiated)
output_form( icm:reraise:Q, ['Returning to the issue of '|InputQDot]):-
	( input_form( InputQ, ask(Q) ); output_form( ask(Q), InputQ ) ),
	append( InputQ, ['.'], InputQDot ).

% reraise action explicitly (feedback on user reraise, or system-initiated)
output_form( icm:reraise:A, ['Returning to '|InputQDot]):-
	( input_form( InputQ, request(A) ); output_form( action(A), InputQ ) ),
	append( InputQ, ['.'], InputQDot ).

% reraise issue (system-initiated, where question follows immediately after)
output_form( icm:reraise, ['So,']).

% accommodation
output_form( icm:accommodate:_, ['Alright.']  ).

output_form( icm:reaccommodate:Q, ['Returning to the issue of'|AnsPDot]  ):-
	input_form( AnsP, ask( Q ) ),
	append(AnsP,['.'],AnsPDot).



output_form( not C, ['Not'|S] ):- output_form( C, S ).



/*----------------------------------------------------------------------
     input_form( +Phrase, -Move )
     -- Almost canned input
----------------------------------------------------------------------*/


	

	

%input_form( S, answer(C) ):- lexsem( S, C ), sem_sort( C, country ).


% general negation 010419
input_form( [not|S], answer(not(C))):- input_form(S,answer(C)).



input_form( [yes], answer(yes) ).
input_form( [no], answer(no) ).


% simple stuff

input_form( [hello], greet ).
input_form( [bye], quit ).
input_form( [quit], quit ).

% ICM

input_form( [pardon], icm:per*neg ).
input_form( [okay], icm:acc*pos ).
input_form( [dont, know], icm:acc*neg:issue ).



/*----------------------------------------------------------------------
     yn_answer( ?YN )
----------------------------------------------------------------------*/

yn_answer(A):-
	A = 'yes';
	A = 'no'.










/*----------------------------------------------------------------------
     lexsem( ?Word, ?Concept )
     -- Lexical semantics
----------------------------------------------------------------------*/

% use semantics as surface forms (only possible for english)
lexsem( Word, Concept ):-
	synset( Words, Concept ),
	member( Word, Words ).

synset( [[vcr],[video],[v,c,r]], vcr ).

%synset( [[DigitWord]], Digit ):- digit_word( DigitWord, DigitString ), name( Digit, DigitString ).

synset( [NumberPhrase], Number ):- number_phrase( NumberPhrase, Number ).