function [ext, ix, context] = get_browser_extension(type, par, name, data)

% get_browser_extension - get extension with up to date browser state
% -------------------------------------------------------------------
%
% [ext, ix, context] = get_browser_extension(type, par, name, data)
%
% Input:
% ------
%  type - extension type
%  par - parent browser
%  name - extension name
%  data - browser state
%
% Output:
% -------
%  ext - extension
%  ix - index of extension in browser store
%  context - context used

% TODO: handle extension exceptions and produce extension warnings

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

%--
% check browser and get state if needed
%--

if ~is_browser(par)
	error('Input handle is not browser handle.');
end

if (nargin < 4) || isempty(data)
	data = get_browser(par);
end

%--
% check extension type and existence of browser store for type
%--

if ~ismember(type, get_extension_types)
	error(['Unrecognized extension type ''', type, '''.']);
end

% NOTE: we set empty outputs because we do not want to throw errors here

ext = []; ix = []; context = [];

if ~isfield(data.browser, type)
	return;
end

if isempty(data.browser.(type).ext)
	return;
end 

%-------------------------
% GET EXTENSION
%-------------------------

%--
% get extension from browser registry by name
%--

ix = find(strcmp(name, {data.browser.(type).ext.name}));

if isempty(ix)
	return;
end

ext = data.browser.(type).ext(ix);

%--
% compile context
%--

% TODO: create extension type dependent context compilation function

% context.sound = data.browser.sound; 

context.sound = sound_update(data.browser.sound, data); 

context.ext = ext; 

%--
% consider if and what we need to do to get updated extension
%--
	
pal = get_palette(par, name, data); compile = ext.fun.parameter.compile;

if ~isempty(ext.parameter) && isempty(pal)
	
	% NOTE: we compile to ensure fresh context
	
	if ~isempty(compile)
		
		try
			ext.parameter = compile(ext.parameter, context);
		catch
			extension_warning(ext, 'Parameter compilation failed.', lasterror);
		end
		
	end
	
	return;

end

%--
% get control values
%--

if ~isempty(pal)
	ext.control = get_control_values(pal);
end

%--
% create extension parameters if needed
%--

create = ext.fun.parameter.create;

if isempty(create)
	return;
end

try
	ext.parameter = create(context);
catch
	extension_warning(ext, 'Parameter creation failed.', lasterror);
end
		
if isempty(ext.parameter)
	return;
end

%--
% update extension parameters using palette and compile if needed
%--

if ~isempty(pal)
	
	% NOTE: update must be configured to be shallow
	
	opt = struct_update; opt.flatten = 0;
	
	ext.parameter = struct_update(ext.parameter, ext.control, opt);
	
end

if ~isempty(compile)
	
	try
		ext.parameter = compile(ext.parameter, context);
	catch
		extension_warning(ext, 'Parameter compilation failed.', lasterror);
	end

end




