function varargout = mapOption(argin, varargin)
% maps options to variables including standard values and error handling.
%
% [option_1 option_2 ...] = mapOption(argin, 'option-name-1',
%   default_value_1, 'option-name-2', default_value_2, ...) maps 
%   option strings (option-name-i) to variables (option_i) by using the
%   default value (default_value_i) whenever this option is not contained
%   in argin.
%
% Purpose: Some functions like plot functions have a number of optional 
%   parameters that can be used. These parameters have a reasonable default 
%   value. In addition for the normal way [function(arg_1, arg_2 , ...)] 
%   the parameter sequence is predetermined which is inconvinient for 
%   optional arguments. This function helps to use the template:
%   doingFooBar(..., 'option-name', option_value).
%
%   The program code then looks like this:
%     function fooFunction(required_parameters, varargin)
%     % set optional parameters
%     [option_1, option_2] = mapOption(varargin, ...
%                                   'option-name-1', defauls_value_1, ...
%                                   'option-name-2', default_value_2);
%
% Performance: Usage is not recommended, if your function is called very 
%   often and speed is crucial, due to error handling overhead.
%
% See also: mergeStruct

% MDT: MATLAB developement tools
%   Copyright (C) 2012 Alexander Reinhold
%
% This program is free software: you can redistribute it and/or modify it 
%   under the terms of the GNU Lesser General Public License as published 
%   by the Free Software Foundation, either version 3 of the License, or 
%   (at your option) any later version.
%
% This program is distributed in the hope that it will be useful, but 
%   WITHOUT ANY WARRANTY; without even the implied warranty of 
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
%   Lesser General Public License for more details.
%
% You should have received a copy of the GNU Lesser General Public License 
%   along with this program.  If not, see <http://www.gnu.org/licenses/>.

%% preliminary error handling (varargin >> internal errors)
% Error, if varargin does not contain option-strings
if ~iscellstr(varargin(1:2:end))
    error('Varargin must be {''option-name-1'', default_value_1, ''option-name-2'', default_value_2, ..}');
end
% Warning, if vargin is odd
if mod(length(varargin),2) ~= 0
    error(['The option ''' varargin{end} ''' has no default value']);
end
% Error, if number of inputs/outputs missmatch
if nargout ~= (nargin - 1) / 2
    error('Number of defined option strings should match number of assigned outputs');
end
%% preliminary error handling (argin >> final user errors)
% Error, if cell-array does not contain option-strings
if ~iscellstr(argin(1:2:end))
    error('Argin must be {''option-name-1'', option, ''option-name-2'', option, ..}');
end
% Warning, if argin is odd
if mod(length(argin),2) ~= 0
    error(['The option ''' argin{end} ''' is not mapped: corresponding value is missing.']);
end

%% set default values
for i = 1:2:length(varargin)
    varargout{(i-1)/2+1} = varargin{i+1};
end
%% map options
for i = 1:2:length(argin)
    option_found = 0;
    for j = 1:2:length(varargin)
        if  strcmpi(argin{i}, varargin{j})
            varargout{(j-1)/2+1} = argin{i+1};
            option_found = 1;break;
        end
    end
    if ~option_found
        error(['Specified option ''' argin{i} ''' is unknown.']);
    end
end
