function [ret, groups] = getFiles(h, type, concatenatePaths, replaceMatlabroot, varargin)
%GETFILES - returns a cell array of source files including the fully
%qualified paths.  this function is called like this:
% 
% 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.
%
%    includeGroupIDs    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
%
%    excludeGroupIDs    This is a cell array of Group IDs. Any files that have
%                       one of these Group ID's will be excluded.
%
% includeGroupIDs and excludeGroupIDs are optional


% Copyright 2005-2019 The MathWorks, Inc.

%check the args to make sure they all conform to the expected format
[argsOK, concatPaths, repMLR, incGroups, excGroups] = ...
    locCheckArgs(type, concatenatePaths, replaceMatlabroot, varargin{:});
if ~(argsOK)
    DAStudio.error('RTW:buildInfo:badMethodArguments',...
                   'RTW.BuildInfoBuildObj.getFiles');
end

ret = {};
groups = {};

fileNames  = {};
filePaths  = {};
fileGroups = {};

if any(strcmp(type, {'include', 'all'})) && ~isempty(h.Inc.Files)
    fileNames  = [fileNames  {h.Inc.Files.FileName}];
    filePaths  = [filePaths  {h.Inc.Files.Path}];
    fileGroups = [fileGroups {h.Inc.Files.Group}];
end

if any(strcmp(type, {'source', 'all'})) && ~isempty(h.Src.Files)
    fileNames  = [fileNames  {h.Src.Files.FileName}];
    filePaths  = [filePaths  {h.Src.Files.Path}];
    fileGroups = [fileGroups {h.Src.Files.Group}];
end

if any(strcmp(type, {'other', 'all'})) && ~isempty(h.Other.Files)
    fileNames  = [fileNames  {h.Other.Files.FileName}];
    filePaths  = [filePaths  {h.Other.Files.Path}];
    fileGroups = [fileGroups {h.Other.Files.Group}];
end

if strcmp(type, 'syslib') && ~isempty(h.SysLib.Files)
    fileNames  = [fileNames  {h.SysLib.Files.FileName}];
    filePaths  = [filePaths  {h.SysLib.Files.Path}];
    fileGroups = [fileGroups {h.SysLib.Files.Group}];
end

% if all the paths are empty, this vector will be empty, we need to create a
% dummy vector with empty paths.
if isempty(filePaths)
    filePaths(1:length(fileNames)) = {''};
end

if isempty(fileGroups)
    fileGroups(1:length(fileNames)) = {''};
end

if isempty(incGroups)
    includeIdx = true(1, length(fileNames));    
else
    includeIdx = ismember(fileGroups, incGroups);
end

if isempty(excGroups)
    excludeIdx = false(1, length(fileNames));    
else
    excludeIdx = ismember(fileGroups, excGroups);
end

includeIdx = includeIdx & (~excludeIdx);

fileNames = fileNames(includeIdx);
% if there are no files left, then return an empty cell array
if isempty(fileNames)
    return;
end

% concatenate the paths, if the caller requested them
if (concatPaths)
    filePaths = filePaths(includeIdx);
    
    % should special tokens like $(MATLAB_ROOT) be replaced?
    if (repMLR)
        specialDirs = h.Settings.getSpecialDirsAndTokens('includeRegexpPats',...
                                                         true);
        sToks = regexptranslate('escape',specialDirs.toks);
        filePaths = regexprep(filePaths, sToks, specialDirs.regexpPats);    
    end

    emptyPaths = cellfun(@isempty,filePaths);
    
    ret(~emptyPaths) = strcat(filePaths(~emptyPaths),...
                              h.Settings.FileSep,...
                              fileNames(~emptyPaths));
    ret(emptyPaths) = fileNames(emptyPaths);
else
    ret = fileNames';
end

groups    = fileGroups(includeIdx);

if ~iscell(ret)
    ret = {ret};
    groups = {groups};
end

ret = reshape(ret,1,[]);
groups = reshape(groups,1,[]);

function [argsOK, concatPaths, repMLR, incGroups, excGroups] =...
    locCheckArgs(type, concatenatePaths, replaceMatlabroot, varargin)

argsOK      = true;
concatPaths = false;
repMLR      = false;
incGroups   = {};
excGroups   = {};

% make sure the type was specified correctly
tf = strcmp(type,{'include', 'source', 'other', 'all','syslib'});
if ~any(tf)
    argsOK = false;
    return;
end

% for concatenatePaths, replaceMatlabroot just check for non-zero versus 0
% value, it is not critical that they are actually logicals.
concatPaths = (concatenatePaths ~= 0);
repMLR      = (replaceMatlabroot ~= 0);

nargs = length(varargin);
% all of the args must be cell arrays for the caller.  If a char array
% or scalar is sent int, just convert them to cell arrays

% the first arg is the incGroups
if (nargs >= 1)
    if ~iscellstr(varargin{1})
        if ~ischar(varargin{1})
            % this is an incompatible data type
            argsOK = false;
            return;
        end
        % Only use this arg if it is not ''.
        if ~isempty(varargin{1})
            incGroups = varargin(1);
        end
    else
        %get the unique list, just in case there are dups
        incGroups = unique(varargin{1});
    end
end

% the second arg is the excGroups
if (nargs >= 2)
    if ~iscellstr(varargin{2})
        if ~ischar(varargin{2})
            % this is an incompatible data type
            argsOK = false;
            return;
        end
        % Only use this arg if it is not ''.
        if ~isempty(varargin{2})
            excGroups = varargin(2);
        end
    else
        %get the unique list, just in case there are dups
        excGroups = unique(varargin{2});
    end
end
