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-2019 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
    
    p = inputParser;
    addParameter(p, 'MinimalHeaders', true, @islogical);
    addParameter(p, 'IgnoreParseError', false, @islogical);   
    addParameter(p, 'GetBuildInfos', 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.LinkObj)
        
        isSharedSrcLib = strcmp(h.LinkObj(i).Group, 'SHARED_SRC_LIB');
        if isSharedSrcLib
            % For the SHARED_SRC library, query the corresponding buildInfo
            % to locate shared utility source files
            [lLinkObj, lLinkObjBuildInfoPath] = loc_loadBuildInfo...
                (h.Settings.LocalAnchorDir, h.LinkObj(i).Path, ...
                 p.Results.MinimalHeaders, p.Results.IgnoreParseError);

            if p.Results.GetBuildInfos
                fPathNames = [fPathNames lLinkObjBuildInfoPath]; %#ok<AGROW>
                names      = [names 'buildInfo.mat']; %#ok<AGROW>
            end
        else
            lLinkObj = h.LinkObj(i);
        end
            
        if (h.LinkObj(i).LinkOnly && getNB) && ~isSharedSrcLib
            % for link only objects, there are no source or include files, just
            % the lib or obj file itself.
            linkLibPath = formatPaths(h, h.LinkObj(i).Path);
            fPathNames =  [fPathNames fullfile(linkLibPath,...
                lLinkObj.Name)]; %#ok<AGROW>
            names      = [names h.LinkObj(i).Name]; %#ok<AGROW>
        else
            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
                fPathNames = [fPathNames lLinkObj.getNonBuildFiles(true,true)]; %#ok<AGROW>
                names      = [names lLinkObj.getNonBuildFiles(false,false)]; %#ok<AGROW>
            end
        end
    end

    % now add all of the ModelRef library sources file.
    for i=1:length(h.ModelRefs)
        
        [mdlRefBuildInfo, mdlRefObjBuildInfoPath] = loc_loadBuildInfo...
                (h.Settings.LocalAnchorDir, h.ModelRefs(i).Path, ...
                 p.Results.MinimalHeaders, p.Results.IgnoreParseError);
                
        if p.Results.GetBuildInfos
            fPathNames = [fPathNames mdlRefObjBuildInfoPath]; %#ok<AGROW>
            names      = [names 'buildInfo.mat']; %#ok<AGROW>
        end
        if getSrc
            fPathNames = [fPathNames mdlRefBuildInfo.getSourceFiles(true,true)]; %#ok<AGROW>
            names      = [names mdlRefBuildInfo.getSourceFiles(false,false)]; %#ok<AGROW>
        end
        if getInc
            fPathNames = [fPathNames mdlRefBuildInfo.getIncludeFiles(true,true)]; %#ok<AGROW>
            names      = [names mdlRefBuildInfo.getIncludeFiles(false,false)]; %#ok<AGROW>
        end
        if getNB
            % there are multiple defines.txt files, one for each model ref.  we
            % only want the parents defines.txt so drop the model ref
            % versions.
            tmpFPNB   = mdlRefBuildInfo.getNonBuildFiles(true,true);
            tmpNB     = mdlRefBuildInfo.getNonBuildFiles(false,false);
            
            idx        = ~strcmp(tmpNB,'defines.txt');
            fPathNames = [fPathNames tmpFPNB(idx)]; %#ok<AGROW>
            names      = [names tmpNB(idx)]; %#ok<AGROW>
        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 [lBuildInfo, buildInfoLoadPath] = loc_loadBuildInfo...
    (anchorDir, lPath, minimalHeaders, ignoreParseError)
% Load and update the buildInfo

[lBuildInfo, buildInfoLoadPath] = coder.internal.loadSharedSourceBuildInfo...
    (anchorDir, lPath);

if isempty(lBuildInfo)
    DAStudio.error('RTW:buildInfo:UnfoundMdlRefBuildInfo', buildInfoLoadPath);
end

% Ensure paths and extensions are up to date
updateFilePathsAndExtensions(lBuildInfo);

% Search for all include files needed by any of the registered source files
findIncludeFiles(lBuildInfo, ...
                 'minimalHeaders', minimalHeaders,...
                 'ignoreParseError', ignoreParseError);

