function data = collateMiniBatch(cellData, miniBatchFcn, isDefaultFcn, numInputsMiniBatchFcn, numOutputs)
%COLLATEMINIBATCH  Convert minibatch from a BatchSize x NumVariables cell
% array into a 1xNumOutputVariables cell array where each column contains
% an array. NumVariables is equal to the number of variables in the input
% datastore, and NumOutputVariables can have a different value. Returns a
% 1x(NumOutputVariables+1) cell array where the last index is the current
% minibatch size. 

%   Copyright 2019-2023 The MathWorks, Inc.

sizeData = size(cellData);
% Get the number of variables
numVariables = sizeData(2);

% Capture the inputs to apply the MiniBatchFcn
if numInputsMiniBatchFcn > -1
    numInputToCapture = numInputsMiniBatchFcn;
else
    numInputToCapture = numVariables;
end
inputArgs = cell(1,numInputToCapture);
for i=1:numInputToCapture
    inputArgs{i} = cellData(:,i);
end

% Initialize the output with the number of outputs
data = cell(1,numOutputs);

% Apply the miniBatchFcn
try
    [data{:}] = miniBatchFcn(inputArgs{:});
catch caughtException
    exceptionsFailedCapture = ["MATLAB:unassignedOutputs", ...
        "MATLAB:TooManyOutputs", ...
        "MATLAB:maxlhs"];
    exceptionIsFromMiniBatchFcn = ~isempty(caughtException.stack) && strcmp(caughtException.stack(1).name,func2str(miniBatchFcn));
    couldNotCaptureOutputs = exceptionIsFromMiniBatchFcn &&...
        nargout(miniBatchFcn) == -1 && any(caughtException.identifier == exceptionsFailedCapture);
    
    if caughtException.identifier == "deep:minibatchqueue:CollateNotConsistent" && isDefaultFcn
        % Suggest to use a custom MiniBatchFcn
        e = MException(message("deep:minibatchqueue:MiniBatchFcnCannotCollate"));
    elseif couldNotCaptureOutputs || ...
            (caughtException.identifier == "deep:minibatchqueue:CollateTooManyOutputs" && isDefaultFcn)
        % Indicate the expected numOutputs
        e = MException(message("deep:minibatchqueue:MiniBatchFcnMismatchVarNumOutputs", numOutputs));
    else
        e = MException(message("deep:minibatchqueue:MiniBatchFcnErrored"));
    end
    e = addCause(e,caughtException);
    throw(e)
end
end
