function result = action_dispatch(obj, eventdata, type, varargin)

% action_dispatch - dispatch action extension
% -------------------------------------------
%
% result = action_dispatch(obj, eventdata, type)
%
% Input:
% ------
%   obj - callback object
%   eventdata - callback event data
%   type - action type
%
% Output:
% -------
%  result - results of action

%--------------------------------
% Author: Harold Figueroa
%--------------------------------
% $Revision: 1600 $
% $Date: 2005-08-18 17:41:06 -0400 (Thu, 18 Aug 2005) $
%--------------------------------


% NOTE: this is working for sounds and events, not yet for logs

% NOTE: the passing of type around is quirky and should be considered


%--------------------------------------------------------------
% HANDLE INPUT
%--------------------------------------------------------------

%--
% check for valid type input
%--

% NOTE: sometimes 'type' can be inferred at considerable code cost, error is better

if (nargin < 3) || isempty(type)	
	error('Action type is required.');
end

if ~is_action_type(type)
	error('Unrecognized action type.');
end

%--------------------------------------------------------------
% SETUP
%--------------------------------------------------------------

%--
% get callback context
%--

% NOTE: menu is not 'control' but this works

callback = get_callback_context(obj, 'pack');

%--
% get action extension
%--

ext = get_extensions([type, '_action'], 'name', callback.control.name);

if isempty(ext)
	error(['Unable to find action ''', callback.control.name, '''.']);
end
		
%--
% get action target
%--

targets = get_action_target(type, callback);

if isempty(targets)
	return;
end

%--
% compile action context
%--

% NOTE: extensions could declare context fields required and context could be compiled

context.ext = ext; 

context.type = type;

context.target = targets;

context.user = get_active_user; 

context.library = get_active_library;

context.callback = callback;

switch type
	
	case 'event', context.sound = get_browser(callback.par.handle, 'sound');
		
end

%--------------------------------------------------------------
% DISPATCH ACTION
%--------------------------------------------------------------

%-------------------------------------
% GET ACTION PARAMETERS
%-------------------------------------

%--
% initialize parameters
%--

parameter = struct([]);

if ~isempty(ext.fun.parameter.create)
	
	parameter = ext.fun.parameter.create(context);

end

%--
% edit parameters through dialog if needed
%--

if ~isempty(ext.fun.parameter.control.create) || xbat_developer

	%--
	% present action dialog
	%--
	
	out = action_dialog(targets, ext, parameter, context);

	if ~strcmp(out.action, 'ok')
		return;
	end

	%--
	% get parameters from dialog
	%--

	if ~isempty(out.values)
		parameter = struct_update(parameter, out.values);
	end
	
end

%-------------------------------------
% PERFORM ACTION
%-------------------------------------

switch type
	
	case 'event', par = callback.par; data = get_browser(par.handle);
		
end

%--
% create waitbar
%--

% NOTE: the default extension behavior is to have a waitbar

if ext.waitbar
	pal = action_waitbar(context); progress = linspace(0, 1, length(targets));
end

%--
% loop over targets
%--

% NOTE: start time of action execution

started = datestr(now); status = 'done';

for k = 1:length(targets)

	%--
	% cancel on closing of waitbar
	%--
	
	if ~ishandle(pal) 
		status = 'cancel'; break;
	end
	
	%--
	% update waitbar while we get actual target from targets
	%--
	
	switch type
	
		case 'event'
		
			[target, target.userdata] = get_str_event(par.handle, targets{k}, data);
			
			target_name = get_action_target_name(target, type);
			
			waitbar_update(pal, 'PROGRESS', ... 
				'message', ['Reading ', target_name, ' ...'] ...
			);
		
			target = event_sound_read(target, context.sound);

		case 'sound'
			
			target = targets(k);

			target_name = get_action_target_name(target, type);
			
		case 'log'
			
			waitbar_update(pal, 'PROGRESS', ... 
				'message', ['Loading ', targets{k}, ' ...'] ...
			);
		
			target = get_target_log(targets{k}, context);
			
			target_name = targets{k};
			
	end
	
	%--
	% update waitbar message
	%--
	
	waitbar_update(pal, 'PROGRESS', ... 
		'message', ['Processing ', target_name, ' ...'] ...
	);

	%--
	% perform action on target
	%--
	
	result(k) = perform_action(target, ext, parameter, context);
	
	%--
	% update waitbar results
	%--
	
	% TODO: implement interrupt behavior using waitbar closing
	
	if ext.waitbar && ishandle(pal)
		action_waitbar_update(pal, progress(k), result(k), type);
	end
		
end

%-------------------------------------
% PUT RESULT IN WORKSPACE
%-------------------------------------

% NOTE: 'perform_action' wraps action instance info, wrap again to add action info

last_action.name = ext.name;

% NOTE: consider using when we implement interrupt behavior

last_action.status = status;

last_action.started = started;

elapsed = sum([result.elapsed]);

last_action.elapsed = elapsed;

last_action.result = result;

assignin('base', 'last_action', last_action);

%-------------------------------------
% INDICATE COMPLETION
%-------------------------------------

%--
% indicate completion in waitbar
%--

if ext.waitbar && ishandle(pal)
	
	%--
	% close waitbar if needed
	%--
	
	if get_control(pal, 'close_after_completion', 'value')
		close(pal); return;
	end
	
	%--
	% present completion message if we did not close
	%--
	
	if elapsed > 2
		time = sec_to_clock(elapsed);
	else 
		time = [num2str(elapsed, 4), ' sec'];
	end
	
	message = [integer_unit_string(numel(targets), type), ' processed in ', time];
		
	waitbar_update(pal, 'PROGRESS', ...
		'message', message ...
	);
	
end


%-------------------------------------
% GET_TARGET_LOG
%-------------------------------------

function log = get_target_log(str, context)

%--
% try to get log file
%--

file = [context.library.path, strrep(str, filesep, [filesep, 'Logs', filesep]), '.mat'];

% NOTE: this should not happen, handle error here

if ~exist(file, 'file')
	error('Unable to find log for action.');
end

%--
% load log from file
%--

log = log_load(file);

