/*
runPrefsDialog
Helper dialog for setting simulation preferences in @model

Part of Garp3 - see copyright notice
2005 Jelmer Jellema, Spin in het Web, spininhetweb.nl
*/

:-pce_begin_class(runPrefsDialog,assistanceDialog
		 ).

%%
initialise(D, Frame):->
	%gp3 0.3.13 rewrite because of assistancebar above
	%we cannot use append etc (again)
	D->+initialise('Simulation preferences','Sim_SimulationPreferences', new(colour(white))), %gp3 0.3.13: helpid + background
	D->>icon(@simulate_icon),
	D->>application(@app),
	%D->>modal(application), %gp3 0.3.12 changed this (problem with other modal dialogs owned by this one)
	D->>transient_for(Frame),
	D->>modal(transient),
	D->>kind(transient),
	D->>can_resize(@off),

	
	%append the basic values
	
	BasicLabel *= label(basicLabel,'Select preferences for running the simulator:',italic),
	D->>display(BasicLabel,point(D?gapX,D?topY)),
	
	new(Basic, menu(basicMenu, toggle)),
	Basic->>show_label(@off),
	
	Basic->>layout(vertical),
	Basic->>columns(2),
	%Basic->>gap(size(0,4)),
	
	%% BASIC ITEMS:
	Basic->>append(menu_item(cw_assumption, label:= 'Assume unknown influences to be zero')), % Oldtext was'Apply closed world assumption in influence resolution')),

	%this one displays checked when the internal value is @off and vice versa
	FMD *= menu_item(free_maxmin_derivative, label:= 'Apply quantity space constraints on extreme values'),
	FMD->>attribute(negate_value,@on),
	Basic->>append(FMD),
	%this one displays checked when the internal value is @off and vice versa
	FZD *= menu_item(free_zero_derivative, label:= 'Apply quantity space constraints on zero as extreme value       '),
	FZD->>attribute(negate_value,@on),
	Basic->>append(FZD),	
	Basic->>append(menu_item(equal_qspace_points, label:= 'Assume equal quantity spaces have equal points')),
	Basic->>append(menu_item(value_branching, label:= 'Generate all values for calculated quantities')),
	Basic->>append(menu_item(fast_path, label:= 'Apply Fastest Path Heuristic')),	
	Basic->>append(menu_item(order_using_correspondences, label:= 'Apply correspondences in ordering')),
	
	Basic->>append(menu_item(epsilon_ordering, label:= 'Apply epsilon ordering')),
	Basic->>append(menu_item(epsilon_merging, label:= 'Apply epsilon merging of immediate terminations')),
	Basic->>append(menu_item(epsilon_derivative_constraints, label:= 'Apply epsilon derivative continuity constraints')),	
	
	
	Basic->>append(menu_item(remove_inactive_quantities, label:= 'Remove inactive quantities after transition')), %gp3 0.3.12 moved this one to basic
	%% END BASIC ITEMS
	
	D->>display(Basic,point(D?gapX,BasicLabel?bottom_side + D?gapY)),

	
	Advb *= button(advanced, ->>(D,onAdvanced)),
	Advb->>label('Advanced >>'),
	D->>display(Advb,point(D?gapX,Basic?bottom_side + D?gapY)),

	new(Advanced, menu(advancedMenu, toggle)),
	Advanced->>show_label(@off),
	Advanced->>layout(vertical),
	Advanced->>columns(2),
	
	%% ADVANCED ITEMS:
	Advanced->>append(menu_item(reasoning_assumptions, label:= 'Allow reasoning assumptions')),
	Advanced->>append(menu_item(assume_conditional_derivatives, label:= 'Allow reasoning assumptions on derivatives')),
	Advanced->>append(menu_item(second_order_derivatives, label:= 'Calculate 2nd order derivatives')),
	Advanced->>append(menu_item(derivative_terminations, label:= 'Generate derivative terminations (based on 2nd order derivatives)')),
	Advanced->>append(menu_item(second_order_continuity, label:= 'Apply 2nd order derivative continuity constraints')),
	Advanced->>append(menu_item(apply_continuity_d_inequalities, label:= 'Apply continuity on derivative inequalities')),
	Advanced->>append(menu_item(order_using_equalities, label:= 'Use constants in ordering')),
	Advanced->>append(menu_item(equal_intervals, label:= 'Assume equal length intervals')),
	Advanced->>append(menu_item(solve_extra_combinations, label:= 'Extra thorough inequality reasoning')),
	Advanced->>append(menu_item(full_branching_derivative_terminations, label:= 'Terminate ambiguous derivatives')),
	Advanced->>append(menu_item(full_branching_equality_terminations, label:= 'Assume inequality terminations')),
	Advanced->>append(menu_item(full_branching_value_terminations, label:= 'Assume value terminations')),	
	Advanced->>append(menu_item(terminate_weak_relations, label:= 'Generate terminations for >= & =<')),
	Advanced->>append(menu_item(extra_termination_interpreter, label:= 'Use extra termination rules')),	

	Advanced->>append(menu_item(order_epsilon_last, label:= 'Apply epsilon ordering last')),
	
	
	Advanced->>append(menu_item(remove_corresponding_equality, label:= 'Remove terminations to unequal for full corresponding quantities')),	
	Advanced->>append(menu_item(use_landmarks, label:= 'Constrain interaction between possible worlds (derive landmark relations)')), % old: 'Derive landmark relations')),

	%% REMOVED ITEMS
	%Advanced->>append(menu_item(allow_d_assumptions_in_reclassifying_mfs, label:= 'Allow assumptions on derivatives in reclassifying MFs')),		

	%this one is also negated
	%NAZ *= menu_item(no_analyse_zero, label:= 'Application of analyse zero equality technique'),
	%NAZ->>attribute(negate_value,@on),
	%Advanced->>append(NAZ),
	%Advanced->>append(menu_item(no_subsumption_specify_all, label:= 'Specify and Match instead of Subsumption')),
	%Advanced->>append(menu_item(use_old_transition_rules, label:= 'Use complete rule based transition procedure')),
	%% END ADVANCED ITEMS
	
	D->>display(Advanced,point(D?gapX,Advb?bottom_side + D?gapY)), %make member, put on right spot, but do not display:
	Advanced->>displayed(@off), %not showing now
	
	
	%% DEPTH LIMIT FIELD
	Depth *= text_item(depth), 
	Depth->>label('Maximum Inequality Reasoning Depth:'),
	D->>display(Depth,point(D?gapX,Advanced?bottom_side + D?gapY)),
	Depth->>displayed(@off), %not showing now
	DepthLabel *= label(depthLabel,'Integers only, 0 is Off',italic),
	D->>display(DepthLabel,point(Depth?right_side + D?gapX, Advanced?bottom_side + D?gapY)),
	DepthLabel->>displayed(@off), %not showing now
	
	
	Save *= imgButton(save, ->>(D,onSave),tt:='Save changes to model'),
	Save->>alignment(left),
	D->>display(Save,point(D?gapX,Advb?bottom_side + D?gapY)),
	
	Defaults *= button(defaults, ->>(D,onDefaults)),
	Defaults->>label('Default settings'),
	Defaults->>tooltip('Restore default simulation preferences'), %gp3 0.4.6
	D->>display(Defaults,point(D?gapX + (Basic?right_side - D?gapX - Defaults?width) / 2,Save?bottom_side - Defaults?height)),
	
	Close *= imgButton(close,->>(D,destroy), tt:='Close this editor'),
	D->>display(Close,point(Basic?right_side - Close?width, Save?top_side)),
	
	D->>updateSpacers,
	D->>loadRunPrefs(@model?runPrefs).
%%
 
%%
loadRunPrefs(D, Prefs: hash_table):->
	%gp3 0.4.6
	%split code from initialize, we need it to in onDefaults below
	%there we use a different hash_table, not the real prefs, so thats why we use the hash_table as an argument here
	%instead of just using @model?runPrefs
	
	%set the right values
	Item *= var,
	Basic = D<<-basicMenu_member,
	Advanced = D<<-advancedMenu_member,
	Prefs->>for_all(
		and(
			if(assign(Item,?(Basic,member,@arg1)),
				->>(Basic,selected,@arg1,
					when(?(Item,attribute,negate_value),@arg2?negate,@arg2))),
			if(assign(Item,?(Advanced,member,@arg1)),
				->>(Advanced,selected,@arg1,
					when(?(Item,attribute,negate_value),@arg2?negate,@arg2)))
		)
	),
	Depth = D<<-member(depth),
	Max = Prefs<<-member(max_depth), 
	Depth->>value(Max).
%%

%%	
onAdvanced(D):->
	%gp3 0.3 Make sure the advanced menu is hidden of shown and update helpid and display
	
	Advanced = D<<-member(advancedMenu),
	Depth = D<<-member(depth),Depth = D<<-member(depth),
	DepthLabel = D<<-member(depthLabel),
	if
		@on = Advanced<<-displayed
	then
	(
		Advanced->>displayed(@off),
		D?advanced_member->>label('Advanced >>'),
		D->>helpId('Sim_SimulationPreferences'),
	        Depth->>displayed(@off),
	        DepthLabel->>displayed(@off)
	)
	else
	(
		Dlg *= notificationDlg(D,confirm, 'Advanced preferences should in principle not be changed! Correct use of these preferences requires expert knowledge of the Garp3 engine.',@on),
		Result = Dlg<<-confirm_centered(D?frame?area?center),
		Dlg->>destroy,
		if
			Result = @on
		then
		(
			Advanced->>displayed(@on),
			D?advanced_member->>label('Advanced <<'),
			D->>helpId('Sim_SimulationPreferencesAdvanced'),
		        DepthLabel->>displayed(@on),
			Depth->>displayed(@on)
		)
	),
	
	%update display
	
	if
		@on = Advanced<<-displayed
	then
	(
		NextY =	DepthLabel<<-bottom_side,
		MaxX = Advanced<<-right_side
	)
	else
	(
		NextY = D?advanced_member<<-bottom_side,
		MaxX = D?basicMenu_member<<-right_side
	),
	%place close and save
	D?save_member->>set(y:=NextY + D?gapY),
	D?defaults_member->>set(x:= D?gapX + (MaxX - D?gapX - D?defaults_member?width) / 2, y:= D?save_member?bottom_side - D?defaults_member?height),
	D?close_member->>set(x:= MaxX - D?close_member?width, y:= NextY + D?gapY),
	%D->>updateSpacers, %update spacing helpers, see assistanceDialog
	D->>fit.
%%

%%
onSave(D):->
 	%gp3 0.3: save the prefs
	NewPrefs *= hash_table,
	D?advancedMenu_member?members->>for_all(
		->>(NewPrefs,append,@arg1?value,
			when(?(@arg1,attribute,negate_value),
				@arg1?selected?negate,
				@arg1?selected))),
	D?basicMenu_member?members->>for_all(
		->>(NewPrefs,append,@arg1?value,
			when(?(@arg1,attribute,negate_value),
				@arg1?selected?negate,
				@arg1?selected))),
	Depth = D<<-member(depth), 
	Value = Depth<<-value,
	% first check the depth value
	(   
	  checkValue(Value, Max)
	->  
	  NewPrefs ->>append(max_depth, Max),	
	  % value is ok, check logical combinations:
	  (   
	    D->>checkChoices(NewPrefs)
	  ->  
	    % combinations ok: save and close
	    @model->>changeRunPrefs(NewPrefs), 
	    %gp3 0.3.13: this might close this dialog, so we check before destroy
	    if
		object(D)
	    then
		D->>destroy
	  ;   
	    true % save cancelled by user because of illogical combination
	  )
	 
	;	
	   % wrong value: notify
	  Dlg *= notificationDlg(D, notification, 'Please fill in a valid number in the depth field',@on),
	  Dlg<<-confirm_centered(D?frame?area?center),
	  Dlg->>destroy
	).

%%

%%
onDefaults(D):->
	%gp3 0.4.6: reset to defaults
	
	Defaults *= hash_table,
	@model->>initRunPrefs(Defaults), %fill Defaults instead of the real thing
	D->>loadRunPrefs(Defaults).
%%

checkChoices(D, NewPrefs):-> % check if all switch choices are logical combinations
	D->>checkEpsilon(NewPrefs),
	D->>checkIncompatible(NewPrefs),
	D->>check2ndOrder(NewPrefs).
	%D->>checkGenerate(NewPrefs). %not really a true pair...

checkGenerate(D, NewPrefs):->
	V = NewPrefs<<-member(full_branching_equality_terminations), 
	E = NewPrefs<<-member(full_branching_value_terminations), 
	(   
	 E = V
	->  
	 true % everything ok
	;   
	 % unequal: notify
	  Dlg *= notificationDlg(D,confirm, 'Please consider turning the following preferences on or off simultaneously since they are conceptually related:\n\n - Assume inequality terminations\n - Assume value terminations\n\nWould you like to continue saving?',@on),
	  Result = Dlg<<-confirm_centered(D?frame?area?center),
	  Dlg->>destroy,
	  (   
	    Result = @off
	  ->  
	    fail % cancel save (fail method)
	  ;      
 	    true % continue
	  )
	).
	
checkIncompatible(D, NewPrefs):->
	V = NewPrefs<<-member(full_branching_derivative_terminations), 
	E = NewPrefs<<-member(order_epsilon_last), 
	(   
	 (E = @on, V = E)
	->  
	 % incompatible options turned on: notify
	  Dlg *= notificationDlg(D,confirm, 'The following preferences are incompatible:\n\n - Terminate ambiguous derivatives\n - Apply epsilon last\n\nSimulation results may be incorrect\n\nWould you like to continue saving?',@on),
	  Result = Dlg<<-confirm_centered(D?frame?area?center),
	  Dlg->>destroy,
	  (   
	    Result = @off
	  ->  
	    fail % cancel save (fail method)
	  ;      
 	    true % continue
	  )
	;   
	  true % no problems with incompatible options.
	).
	
check2ndOrder(D, NewPrefs):->
	EO = NewPrefs<<-member(second_order_derivatives), 
	EM = NewPrefs<<-member(derivative_terminations), 
	EDC = NewPrefs<<-member(second_order_continuity),
	(   
	 EO = EM,
	 EM = EDC
	->  
	 true % everything ok
	;   
	 % unequal: notify
	  Dlg *= notificationDlg(D,confirm, 'Please consider turning the following preferences on or off simultaneously since they are conceptually related:\n\n - Calculate 2nd order derivatives\n - Generate derivative terminations (based on 2nd order derivatives)\n - Apply 2nd order derivative continuity constraints\n\nWould you like to continue saving?',@on),
	  Result = Dlg<<-confirm_centered(D?frame?area?center),
	  Dlg->>destroy,
	  (   
	    Result = @off
	  ->  
	    fail % cancel save (fail method)
	  ;      
 	    true % continue
	  )
	).
checkEpsilon(D, NewPrefs):->
	EO = NewPrefs<<-member(epsilon_ordering), 
	EM = NewPrefs<<-member(epsilon_merging), 
	EDC = NewPrefs<<-member(epsilon_derivative_constraints),
	(   
	 EO = EM,
	 EM = EDC
	->  
	 true % everything ok
	;   
	 % unequal: notify
	  Dlg *= notificationDlg(D,confirm, 'Please consider turning the following preferences on or off simultaneously since they are conceptually related:\n\n - Apply epsilon ordering\n - Apply epsilon merging of immediate terminations\n - Apply epsilon continuity constraints\n\nWould you like to continue saving?',@on),
	  Result = Dlg<<-confirm_centered(D?frame?area?center),
	  Dlg->>destroy,
	  (   
	    Result = @off
	  ->  
	    fail % cancel save (fail method)
	  ;      
 	    true % continue
	  )
	).


checkValue('', 0):-
	!, % an empty text field...
	fail.
checkValue(Value, X):-
	atom_codes(Value, Codes), 
	all_number_codes(Codes), 
	number_codes(X, Codes),
	!.

all_number_codes([]).
all_number_codes([H|T]):-
	H > 47, 
	H < 58, 
	all_number_codes(T).

:-pce_end_class.
