function [fPathNames, names] = getFullFileList(h, ftype, varargin)
%getFullFileList - package all files in a buildInfo object into a zip file.
%    This function returns all files contained within the buildInfo.  The first
%    return is the fully qualified path to the file, while the second return is
%    just the filenames.  The second arg is used mainly for doing dup checks.
%    Note that because the same header file can be declared in both standalone
%    sources, as well as in one or more libraries, they must be reduced before
%    returning the vectors.

% Copyright 2006-2023 The MathWorks, Inc.

    if nargin > 1
        ftype = convertStringsToChars(ftype);
    else
        ftype = '';
    end
    fPathNames = {};
    names = {};

    getSrc   = true;
    getInc   = true;
    getNB    = true;
    
    matchedFtype = validatestring(ftype, {'source', 'include', 'nonbuild', ''});
    switch matchedFtype
        case 'source'
            getInc = false;
            getNB  = false;
        case 'include'
            getSrc = false;
            getNB  = false;
        case 'nonbuild'
            getSrc = false;
            getInc = false;
        otherwise
            % Use defaults
    end
    
    % The name-value pair arguments are undocumented
    p = inputParser;  
    addParameter(p, 'GetBuildInfos', false);
    addParameter(p, 'GetCMakeLists', false);

    parse(p, varargin{:});
    
    % get the standalone files first.  both the fullpath name and just
    % the filename are needed for dup checks on the flat zip files.
    if getSrc
        fPathNames = h.getSourceFiles(true,true);    
        names      = h.getSourceFiles(false,false);
    end
    if getInc
        fPathNames = [fPathNames h.getIncludeFiles(true,true)];
        names      = [names h.getIncludeFiles(false,false)];
    end
    if getNB
        fPathNames = [fPathNames h.getNonBuildFiles(true,true)];
        names      = [names h.getNonBuildFiles(false,false)];
    end
    
    % now add all of the library sources, or if it is a link only lib, get that
    % file.
    for i=1:length(h.Linkables)
        lLinkObj = h.Linkables(i);
        lLinkObjPath = formatPaths(h, lLinkObj.Path);

        isSharedSrcLib = strcmp(h.Linkables(i).Group, 'SHARED_SRC_LIB');
        isModelRefLib = strcmp(h.Linkables(i).Group, 'MDLREF_LIB');
        
        if isSharedSrcLib || isModelRefLib
            % Reusable Library Subsystems is one more case of a linkable with a serialized
            % buildInfo.mat
            % RLS are currently not supported.
            % See g2544356
            if p.Results.GetCMakeLists
                lLinkObjCMakeListsPath = fullfile(lLinkObjPath, 'CMakeLists.txt');
                fPathNames = [fPathNames lLinkObjCMakeListsPath]; %#ok<AGROW>
                names      = [names 'CMakeLists.txt']; %#ok<AGROW>
            end
            lLinkObjBuildInfoPath = fullfile(lLinkObjPath, 'buildInfo.mat');
            if ~isfile(lLinkObjBuildInfoPath)
                error(message('RTW:buildInfo:UnfoundMdlRefBuildInfo', lLinkObjBuildInfoPath));
            end
            if p.Results.GetBuildInfos
                fPathNames = [fPathNames lLinkObjBuildInfoPath]; %#ok<AGROW>
                names      = [names 'buildInfo.mat']; %#ok<AGROW>
            end
        end
            
        if (lLinkObj.LinkOnly && getNB) && ~isSharedSrcLib
            % for link only objects, there are no source or include files, just
            % the lib or obj file itself.
            fPathNames =  [fPathNames fullfile(lLinkObjPath,...
                lLinkObj.Name)]; %#ok<AGROW>
            names      = [names lLinkObj.Name]; %#ok<AGROW>
        else
            if ~isempty(lLinkObj.BuildInfoHandle)
                % If this is a lightweight link object that is backed by a buildInfo.mat
                % we collect the artifacts directly from the backing buildInfo 
                lLinkObj = lLinkObj.BuildInfoHandle;
            end
            lLinkObj.updateFilePathsAndExtensions();
            if getSrc
                fPathNames = [fPathNames lLinkObj.getSourceFiles(true,true)]; %#ok<AGROW>
                names      = [names lLinkObj.getSourceFiles(false,false)]; %#ok<AGROW>
            end
            
            if getInc
                fPathNames = [fPathNames lLinkObj.getIncludeFiles(true,true)]; %#ok<AGROW>
                names      = [names lLinkObj.getIncludeFiles(false,false)]; %#ok<AGROW>
            end
            
            if getNB
                tmpFullPathNonBuild = lLinkObj.getNonBuildFiles(true,true);
                tmpNameNonBuild     = lLinkObj.getNonBuildFiles(false,false);
                if isModelRefLib
                    % there are multiple defines.txt files, one for each model ref.  we
                    % only want the parents defines.txt so drop the model ref
                    % versions.
                    idx = ~strcmp(tmpNameNonBuild,'defines.txt');
                    tmpFullPathNonBuild = tmpFullPathNonBuild(idx);
                    tmpNameNonBuild     = tmpNameNonBuild(idx);
                end
                fPathNames = [fPathNames tmpFullPathNonBuild]; %#ok<AGROW>
                names      = [names tmpNameNonBuild]; %#ok<AGROW>
            end

            [cmakeFragmentPathNames, cmakeFragmentNames] = ...
                includeCMakeFragmentsUnderMatlabRoot(p.Results.GetCMakeLists, ...
                lLinkObj);
            fPathNames = [fPathNames cmakeFragmentPathNames];
            names = [names cmakeFragmentNames];

        end
    end

    % any files that start with '..' should be fixed to have the full
    % path.  There will be 2 potential variants of the slprj dirs
    % '../slprj' (top model build) and '../../../slprj' (grandchild model
    % include dir).  in both of these cases the path is really pointing to
    % the same slprj dir.
    %
    %
    % For example:
    % 
    % assume start dir is /home/user/project
    %
    % original path:  ../slprj/ert/sub_model/sub_model.c
    % new path:       /home/user/project/slprj/ert/sub_model/sub_model.c
    %
    % original path:  ../../../slprj/ert/sub_model2/sub_model2.c
    % new path:       /home/user/project/slprj/ert/sub_model2/sub_model2.c
    rePat = '^\.\.';
    idx = ~cellfun(@isempty,regexp(fPathNames,rePat,'once'));

    if any(idx)
        bd  = h.getIncludePaths(true,'BuildDir');
        tmpPaths = strcat(bd, h.Settings.FileSep, fPathNames(idx));
        fPathNames(idx) = cellfun(@RTW.reduceRelativePath,...
                                  tmpPaths,...
                                  'uniformOutput',false);
    end
    
    
    % remove any dup's that have the full path the same.  in other words
    % if there are 2 entries that point to the exact same file, then
    % we only need one.
    [fPathNames, idx] = RTW.unique(fPathNames);
    names             = names(idx);



function [pathNames, names] = includeCMakeFragmentsUnderMatlabRoot(getCMakeLists, lLinkObj)
    if getCMakeLists && isa(lLinkObj, 'RTW.BuildInfo')
        % If CMake, then check if we need to include .cmake
        % fragments from under MATLAB_ROOT.
        fragments = coder.make.internal.cmake.CMakeFragments.getRequiredFragments(lLinkObj);
        fragments = strrep(fragments, '$(MATLAB_ROOT)', matlabroot);
        [~,fragmentNames,fragmentExts] = fileparts(fragments);
        pathNames = fragments;
        names = strcat(fragmentNames, fragmentExts);
    else
        pathNames = {};
        names = {};
    end
