function rc = formatPaths(h, input, varargin)
%FORMATPATHS - converts a path between the expanded full path form and the
% internal representation for this buildInfo instance which includes tokenized
% root dir strings such as $(MATLAB_ROOT) and $(START_DIR).  
%
%   bi = RTW.BuildInfo;
%   transformPaths(bi,pathStrs,...)
%
% Argument         description
% pathStrs         A character array or cell array of character arrays
%                  containing the input path string(s) to be transformed.
%                  NOTE: that these strings can be full paths to file names
%                  or just directory names.
% 
% the remaining arguments are property-value pairs which affect the
% behavior and output of the function.
%
%   property   value       description
%   'format' 'expanded'    this is the default behavior.
%                          Replaces any occurrences of this instance of
%                          BuildInfo's internal tokens such as $(MATLAB_ROOT)
%                          with the internally stored path string for them.
%
%   'format' 'tokenized'   Replaces any occurrence of this instance of
%                          BuildInfo's root directories with the internal
%                          tokens used to represent those directories. 
%    
% NOTE: the char array for this BuildInfo instance's internal MATLAB root may be
% slightly different from the value returned by matlabroot(). when converting to
% the expanded format, the internal version is returned.  When converting to the
% tokenized version, both the internal representation as well as the value
% returned by matlabroot() will be converted.
%
        
% Copyright 2004-2019 The MathWorks, Inc.
    
% check the args
opts = locCheckArgs(input, varargin{:});

% Callers of this function can specify whether or not to override the
% replacement of the $(START_DIR) token with the start directory with the
% relative path to the start directory from the current build info context.
% Should the override be enabled we pass the current relative path to
% anchor to getSpecialDirsAndTokens.
if isa(h, 'RTW.BuildInfo') && opts.replaceStartDirWithRelativePath && opts.expanded
    [~, relativePathToAnchor] = h.findBuildArg('RELATIVE_PATH_TO_ANCHOR');
else
    relativePathToAnchor = '';
end

% NOTE: the first dir listed in the 'special dirs' is always matlabroot
sDirs = h.Settings.getSpecialDirsAndTokens(...
    'includeRegexpPats', true,...   
    'relativeAnchorOverride', relativePathToAnchor);

reSDirs = [regexptranslate('escape',matlabroot) sDirs.regexpPats];
reToks = regexptranslate('escape',[sDirs.toks{1} sDirs.toks]);

if opts.expanded
    rc = regexprep(opts.inputCell,reToks,reSDirs);
else
    % Look ahead assertion to match file separator or end of input text
      endOfPathExpr = "(?=\\|\/|$)";

    % If matlabroot is "/MATLAB", do not replace paths like 
    % "/MATLAB workingFolder"
    reSDirsExpr = string(reSDirs)+endOfPathExpr;
    rc = regexprep(opts.inputCell,reSDirsExpr,reToks);
end

% because the input was changed in to a cell array (if not already a cell
% array) for optimization, if it was a char array, then return just the
% first (only) entry in the output vector.
if ischar(input)
    rc = rc{1};
end

function opts = locCheckArgs(input,varargin)

    persistent parser;
    expandedString = 'expanded';
    
    if isempty(parser)
        parser = inputParser();
        parser.FunctionName = 'RTW.BuildInfo.formatPaths';
        parser.CaseSensitive = false;

        % Add inputCell
        paramName = 'inputCell';
        validationFcn = @(v) iscellstr(v) || ischar(v);

        parser.addRequired(paramName, validationFcn);

        % Add format
        paramName = 'format';
        defaultValue = expandedString;
        validationFcn = @(v) ischar(v) && any(strcmp(v, {expandedString, 'tokenized'}));

        parser.addParameter(paramName, defaultValue, validationFcn);          

        % Add replaceStartDirWithRelativePath    
        paramName = 'replaceStartDirWithRelativePath';
        defaultValue = false;
        validationFcn = @islogical;

        parser.addParameter(paramName, defaultValue, validationFcn);
    end

    parser.parse(input, varargin{:});
    opts = parser.Results;
    
    if ischar(opts.inputCell)
        opts.inputCell = {opts.inputCell};
    end

    opts.expanded = strcmpi(opts.format, expandedString);
