function [fileNames, groups] = getFiles(h, type, concatenatePaths, ...
    replaceMatlabroot, includeGroups, excludeGroups, options)
% getFiles returns a cell array of source files including paths
% 
% files = getFiles(type, concatenatePaths, replaceMatlabroot,...
%                  includeGroupIDs, excludeGroupIDs)
%
%    type               This argument controls which types(include or source
%                       files) of files are returned. It must be one of:
%                       {'include', 'source', 'all'}
%
%    concatenatePaths   logical value, if true will concatenate the path onto
%                       the filename
%   
%    replaceMatlabroot  logical value, if true will automatically replace
%                       $(MATLAB_ROOT) with the hard-coded path.  if
%                       concatenatePaths is false. this arg has no effect.
%
%    includeGroups      This is a cell array of Group IDs.  Only files that
%                       have GroupID in this set will be returned.  If this
%                       is empty, the all files are included
%
%    excludeGroups      This is a cell array of Group IDs. Any files that have
%                       one of these Group ID's will be excluded.

% Copyright 2005-2023 The MathWorks, Inc.

arguments
    h (1,1) RTW.BuildInfoBuildObj
    type (1, :) char ...
        {mustBeMember(type, ...
        {'include', 'preinclude', 'source', 'other', 'all', 'syslib'})}
    concatenatePaths (1, :) logical {mustBeScalarOrEmpty}
    replaceMatlabroot (1, :) logical {mustBeScalarOrEmpty}
    includeGroups (1, :) {mustBeText} = string.empty;
    excludeGroups (1, :) {mustBeText} = string.empty;
    options.SourceFileHandles (1,:) RTW.BuildInfoFile = RTW.BuildInfoFile.empty;
end

[includeGroups, excludeGroups] = ...
    coder.make.internal.buildInfoGroupArgs(includeGroups, excludeGroups);

if strcmp(type, 'include')
    filesArray = h.Inc;
elseif strcmp(type, 'preinclude')
    filesArray = RTW.BuildInfoModules('Includes');
    filesArray.Files = filterByPreinclude(h.Inc.Files);
elseif strcmp(type, 'source')
    filesArray = h.Src;
elseif strcmp(type, 'other')
    filesArray = h.Other;
elseif strcmp(type, 'syslib')
    filesArray = h.SysLib;
else % all
    filesArray = RTW.BuildInfoModules('All');
    filesArray.Files = ...
        [h.Inc.Files; h.Src.Files; h.Other.Files; h.SysLib.Files];
end

% Include/exclude groups filter
keepIdx = coder.make.internal.buildInfoGroupsFilter ...
    (filesArray, 'Files', includeGroups, excludeGroups);
filesFiltered = filesArray.Files(keepIdx);

% Source file handle filter
matchHandlesIdx = i_sourceFileHandleFilter(filesFiltered, options.SourceFileHandles);
filesFiltered = filesFiltered(matchHandlesIdx);
 
% Extract details of selected files
groups = {filesFiltered.Group};
fileNames = {filesFiltered.FileName};
filePaths = {filesFiltered.Path};

% Concatenate the paths, if caller requested them
if (concatenatePaths)
    
    % Replace tokens like $(MATLAB_ROOT), if requested
    if (replaceMatlabroot)
        filePaths = h.Settings.expandPaths(filePaths);
    end

    emptyPaths = cellfun(@isempty,filePaths);

    % Update any fileNames with non-empty path
    fileNames(~emptyPaths) = strcat(filePaths(~emptyPaths),...
                              h.Settings.FileSep,...
                              fileNames(~emptyPaths));
end


% Filter out specified handles
function matchHandlesIdx = i_sourceFileHandleFilter(files, handles)

if ~isempty(handles)
    matchHandlesIdx = ismember(files, handles);
else
    matchHandlesIdx = true(size(files));
end


function preincFiles = filterByPreinclude(files)
    % Filter files by 'IsPreinclude' property
    idx = [files.IsPreinclude] == 1;
    preincFiles = files(idx);
    