function result = cat(dim, varargin)
%CAT Concatenate arrays.
%   C = CAT(DIM,A,B,...)
%   
%   The data format of all inputs A, B, ... must match, or all inputs must
%   be unformatted. Mixed formatted and unformatted inputs are supported.
%   If any of the inputs is formatted, output C is formatted with the same
%   dimension labels.
%
%   See also CAT, VERTCAT, HORZCAT, DLARRAY.

%   Copyright 2019 The MathWorks, Inc.

if isa(dim, 'dlarray')
    % If only dim is a dlarray, we want to dispatch to a different cat
    % method.
    result = cat(extractdata(dim), varargin{:});
    return
end

if length(varargin) == 1
    result = varargin{1};
    return
end

% First dlarray input defines the required format
dimDescResult = '';
for ii=1:length(varargin)
    x = varargin{ii};
    if isa(x, 'dlarray') && hasFormat(x)
        dimDescResult = dims(x);
        break;
    end
end

dataArgs = cell(1, length(varargin));
for ii=1:length(varargin)
    x = varargin{ii};
    if isa(x, 'dlarray')
        if hasFormat(x) && ~isequal(dims(x), dimDescResult)
            error(message('deep:cat:DimsMismatch'));
        end
        x = permuteExplicitly(x);
        [~, xdata] = extractData(x.FormattedData);
        dataArgs{ii} = xdata;
    else
        deep.internal.dlarray.validateNonDlarray(x);
        dataArgs{ii} = x;
    end
end

resultdata = cat(dim, dataArgs{:});

result = dlarray;
result.FormattedData = insertData(result.FormattedData, resultdata);
if ~isempty(dimDescResult)
    if length(dimDescResult) < ndims(resultdata)
        dimDescResult(end+1:ndims(resultdata)) = 'U';
    end
    result.FormattedData.DimensionMetadata = dimDescResult;
end
end
