function X = struct_update(X, Y, opt)

% struct_update - update a structure using another
% ------------------------------------------------
%
% opt = struct_update
%
%   X = struct_update(X, Y, opt)
%
% Input:
% ------
%  X - structure to update
%  Y - source structure
%  opt - update options structure
%
% Output:
% -------
%  opt - default update options structure
%  X - updated structure

%--------------------------------
% Author: Harold Figueroa
%--------------------------------
% $Revision: 1554 $
% $Date: 2005-08-10 18:31:35 -0400 (Wed, 10 Aug 2005) $
%--------------------------------

%--
% set default options
%--

if (nargin < 3) || isempty(opt)
	
	%--
	% set default options
	%--
	
	opt.equal = 0; % NOTE: require structures to be equal
	
	opt.flatten = 1; % NOTE: flatten structures to perform update
	
	opt.level = -1;
	
	%--
	% output options if needed
	%--
	
	if ~nargin
		X = opt; return;
	end 
	
end 

if ~isfield(opt, 'level')
	opt.level = -1;
end

%--
% flatten structures if needed
%--

if opt.flatten	
	X = flatten_struct(X, opt.level); Y = flatten_struct(Y, opt.level);
end

%--
% get fieldnames
%--

X_field = fieldnames(X); Y_field = fieldnames(Y);

%--
% check for equal structures if needed
%--

if opt.equal
	
	% NOTE: equality is a check on contents and order, not a set operation
	
	% TODO: consider allowing order to be omitted
	
	if ~isequal(X_field, Y_field)
		
		if (opt.flatten)
			error('Flattened input structures have different forms.');
		else
			error('Input structures have different forms.');
		end
		
	end 
	
end

%--
% update structure fields
%--

% TODO: develop struct merge, and various modes for update

% NOTE: loop over shorter set of fields

if (length(X_field) < length(Y_field))
	
	for k = 1:length(X_field)

		match = find(strcmp(Y_field, X_field{k}));
		
		if ~isempty(match)
			X.(X_field{k}) = Y.(X_field{k});
		end

	end
	
else
	
	for k = 1:length(Y_field)

		match = find(strcmp(X_field, Y_field{k}));
		
		if ~isempty(match)
			X.(Y_field{k}) = Y.(Y_field{k});
		end

	end
	
end

%--
% unflatten structures if needed
%--

if opt.flatten
	X = unflatten_struct(X); Y = unflatten_struct(Y);
end
