function paramsList = partialMatchParameters(modelParamsList,modelType,varargin)
% Parse name-value pairs specified in model parameters with partial matching 
% Keep unmatched name-value pairs untouched and append to the list

%   Copyright 2020-2023 The MathWorks, Inc.

p = inputParser;
p.StructExpand = true;
p.KeepUnmatched = true;

supportedModelTypes = {'anomaly','classification','regression'};

% assert for internal error reporting
assert(isStringScalar(modelType) || ischar(modelType),'Model type should be a string or char array.');
modelType = lower(modelType);
assert(ismember(modelType,supportedModelTypes),'Unsupported model type passed to partialMatchParameters.');


switch modelType
    case 'anomaly' % add anomaly detection parameters
        predParamsList = incremental.anomaly.utils.anomalyDetectorParameters(); 
    case 'classification' % add classification parameters
        predParamsList = incremental.utils.classificationParameters(); 
    case 'regression' % add regression parameters
        predParamsList = incremental.utils.regressionParameters(); 
end

for ii = 1:numel(predParamsList)
    addParameter(p,predParamsList{ii},[]);
end

if ~isequal(modelType,'anomaly')
    % metrics name-value pairs common to all models
    metricsParamsList = incremental.utils.metricsParameters();
    for ii = 1:numel(metricsParamsList)
        addParameter(p,metricsParamsList{ii},[]);
    end
end

% additional name-value pairs
for ii = 1:numel(modelParamsList)
    addParameter(p,modelParamsList{ii},[]);
end

parse(p,varargin{:});

paramsList = p.Results;

% append unmatched
fields = fieldnames(p.Unmatched);
for ii = 1:numel(fields)
    paramsList.(fields{ii}) = p.Unmatched.(fields{ii});
end

% remove empty fields
fields = fieldnames(paramsList);
emptyfields = cellfun(@(c) isempty(paramsList.(c)), fields);
paramsList = rmfield(paramsList, fields(emptyfields));

end