function b = addvars(a, varargin)
%ADDVARS Add variables to codistributed table or timetable.
%   T2 = ADDVARS(T1, VAR1, ..., VARN)
%   T2 = ADDVARS(..., 'Before', LOCATION) 
%   T2 = ADDVARS(..., 'After',  LOCATION)
%   T2 = ADDVARS(..., 'NewVariableNames', NEWNAMES)
%   
%   See also TABLE, CODISTRIBUTED.
%   


%   Copyright 2018-2020 The MathWorks, Inc.

if ~istable(a) && ~istimetable(a)
    % Throw the same error as for in-memory
    msg = message('MATLAB:legacy_two_part:UndefinedFunctionTextInputArgumentsType', mfilename, underlyingType(a));
    error(message('MATLAB:UndefinedFunction', getString(msg)));
end

% a must be codistributed, vars must not
distributedutil.CodistParser.verifyNonCodistributedInputs([{a}, varargin]);
varargin = distributedutil.CodistParser.gatherIfCodistributed(varargin);
if ~isa(a, 'codistributed')
    % Not distributed. Run replicated.
    b = addvars(a, varargin{:});
    return;
end

% Call the in-memory version to do input checking and get the desired
% output table template. We need to convert all distributed inputs into local
% templates first.
bProto = distributedutil.validateSyntax(@addvars, [{a}, varargin]);

aProto = getTableTemplate(a);
inNumVars = width(aProto);
numNewVars = width(bProto) - inNumVars;

% Since variable names are unique, we can reverse engineer where the new
% variables were inserted from the prototype. We can then use concatenation
% to build our new tall table.
oldVarNames = aProto.Properties.VariableNames;
allVarNames = bProto.Properties.VariableNames;
[newVarNames,newIdxs] = setdiff(allVarNames, oldVarNames, "stable");

% Put the new variables into their own table using the names deduced by
% validateSyntax.
newTable = table(varargin{1:numNewVars}, 'VariableNames', newVarNames);

if height(newTable) ~= height(a)
    error(message("MATLAB:table:RowDimensionMismatch"));
end

% Now concatenate the new table in between parts of the old
idxsBefore = 1:(min(newIdxs)-1);
idxsAfter = setdiff(1:inNumVars, idxsBefore);

aBefore = subsref(a, substruct('()', {':', idxsBefore}));
aAfter = subsref(a, substruct('()', {':', idxsAfter}));

b = horzcat(aBefore, newTable, aAfter);

% Make sure the output carries the rowtimes/names from the original
if istimetable(b)
    subs = substruct('.','Properties','.','RowTimes');
else
    subs = substruct('.','Properties','.','RowNames');
end
b = subsasgn(b, subs, subsref(a, subs));
