function addKeyValuePair(h, Type, varargin)
%ADDTMFKEYVALUEPAIR - Add a key-value pair to one of the internal vectors

% Copyright 2004-2023 The MathWorks, Inc.

%check the args to make sure they all conform to the expected format
[args_ok, Keys, Values, Groups] = locCheckArgs(h, Type, varargin{:});
if ~(args_ok)
    error(message('coder_compile:CoderCompile:badMethodArguments',...
                   'RTW.BuildInfo.addKeyValuePair'));
end

% if any of the Keys are already in the list, remove them.
switch (Type)
  case 'BuildArg'
    cur_keys = get(h.BuildArgs,'Key');
  case 'Token'
    cur_keys = get(h.Tokens,'Key');
  case 'MakeVar'
    cur_keys = get(h.MakeVars,'Key');
end

if ~isempty(cur_keys)
    % this returns the members and indices of Keys that are NOT in
    % cur_keys. 
    idx = ~ismember(Keys,cur_keys);
    % reduce all of the input vectors to the subset of new entries.
    Keys   = Keys(idx);
    Values = Values(idx);
    Groups = Groups(idx);
end

% if all the insertions are duplicates, just return
if isempty(Keys)
    return;
end

cnt = length(Keys);

for i=cnt:-1:1
    % create a new path object and add it to the list
    newKeyValPair(i) = RTW.BuildInfoKeyValuePair(Keys{i}, Values{i},...
                                                 Groups{i}, Keys{i});
end

% note that the newKeyValPair must be transposed , because it is 1xN
% while vector property is Nx1
switch (Type)
  case 'BuildArg'
    h.BuildArgs = [h.BuildArgs; newKeyValPair']; 
  case 'Token'
    h.Tokens    = [h.Tokens; newKeyValPair'];
  case 'MakeVar'
    h.MakeVars    = [h.MakeVars; newKeyValPair'];
end

function [args_ok, Keys, Values, Groups] = locCheckArgs(h, Type, varargin)

args_ok = false;
Keys    = {};
Values  = {};
Groups  = {};

%currently 2-7 arguments can be passed in.
if ((nargin<3) || (nargin>5))
    return;
end

% the first arg is the type of Key Value pair, and affects which list
% it will get added to.
validKeys = {'BuildArg' 'Token', 'MakeVar'};
if ~ischar(Type) || ~any(strcmp(Type, validKeys))
    return;
end

% the next arg is the Key
if ~iscellstr(varargin{1})
    if ~ischar(varargin{1})
        % this is an incompatible data type
        return;
    end
    Keys = varargin(1);
else
    Keys = varargin{1};
end

% the second arg is value for the key
if (nargin >= 4)
    % if the argument is not a cell array (i.e. a single value) create a
    % cell array the same length as Keys and fill it with that value.
    if iscellstr(varargin{2})
        Values = varargin{2};
        % the Keys and Groups cell array must have the same length
        if (length(Keys) ~= length(Values))
            args_ok = false;
            return;
        end
    else
        if ~ischar(varargin{2})
            args_ok = false;
            return;
        end
        Values(1:length(Keys)) = varargin(2);
    end
else
    Values(1:length(Keys)) = {''};
end

% final arg is the group
if (nargin >= 5)
    % if the argument is not a cell array (i.e. a single value) create a
    % cell array the same length as Keys and fill it with that value.
    if iscellstr(varargin{3})
        Groups = varargin{3};
        % the Keys and Groups cell array must have the same length
        if (length(Keys) ~= length(Groups))
            args_ok = false;
            return;
        end
    else
        if ~ischar(varargin{3})
            args_ok = false;
            return;
        end
        Groups(1:length(Keys)) = varargin(3);
    end
else
    Groups(1:length(Keys)) = {''};
end

% remove any duplicate entries if the list is longer than 1
if (length(Keys) > 1)

    [Keys,idx] = RTW.unique(Keys);
    
    % reduce all of the input vectors to the subset of unique entries
    Values = Values(idx);
    Groups = Groups(idx);

    % finally, check for empty Keys.  If the Token is empty, the
    % whole entry should be removed.
    idx = ~strcmp('', Keys);

    Keys   = Keys(idx);
    Values = Values(idx);
    Groups = Groups(idx);
end

% any of the key/values that are labeled as paths (group ends in '_PATH'),
% need to have the file separators adjusted for consistency.
idx = ~cellfun(@isempty,regexp(Groups,'.*_PATH$'));

% make sure all of the fileseps are the 'correct' one
Values(idx) = coder.make.internal.standardizeFileSep(Values(idx), h.Settings.FileSep);

% if we got here the args are OK
args_ok  = true;
