function [xdata, fd, XHasNoObservationDim, channelDim, observationDim, timeDim] = flattenDimOfRecurrentInput(X)
% flattenDimOfRecurrentInput   Flatten spatial dimenions into channels for recurrent ops

%   Copyright 2019 The MathWorks, Inc.

XSpatialDimensions = finddatadim(X, 'S');
XHasSpatialDimensions = ~isempty(XSpatialDimensions);

if XHasSpatialDimensions
    % Force permutation to have the correct dimension order for flattening
    X = permuteExplicitly(X);
    numSpatialDims = length(XSpatialDimensions);
end

% Extract the input data
fd = X.FormattedData;
[fd,xdata] = extractData(fd);

% Retrieve channel, time and observation dimensions
timeDim = finddatadim(X, 'T');
observationDim = observationIndex(fd);
channelDim = channelIndex(fd);

% Ensure there is a T dimension and no non-singleton U dimensions
hasNoTimeDim = isempty(timeDim);
XHasNoObservationDim = isempty(finddatadim(X, 'B'));
sizeXData = size(xdata);
XDataIsAVector = isvector(xdata);
hasNonSingletonU = ~isempty(finddatadim(X, 'U')) && (~XDataIsAVector ...
    || (~hasNoTimeDim && XDataIsAVector && sizeXData(timeDim) == 1) && ~all(sizeXData==1));
if hasNoTimeDim || hasNonSingletonU
    error(message('deep:dlarray:LstmInvalidFirstInput'))
end

% Ensure the time dimension is non-empty
nDimsXData = numel(sizeXData);
if (timeDim <= nDimsXData) && (sizeXData(timeDim) == 0)
    error(message('deep:dlarray:RecurrentEmptyTimeDim'))
end

% Flatten the spatial dimensions
if XHasSpatialDimensions
    % Find the other dimensions (at minimum, the index of the T dimension).
    otherDims = indexOfLabels(fd, 'BTU');
    % Expand sizeXData to include singleton dimensions if necessary
    if nDimsXData < max(otherDims)
        sizeXData = [sizeXData ones(1, max(otherDims) - nDimsXData)];
    end
    sizeOtherDims = num2cell(sizeXData(otherDims));
    % Flatten
    xdata = reshape(xdata, [], sizeOtherDims{:});
    % Offset the other dimensions indices depending on if 'C' was specified
    if ~any(fd.DimensionMetadata == 'C')
        offset = -numSpatialDims + 1;
        % Offset the observationDim with -1 to ignore the implicit channel
        % dimension, only if it is before the observation dimension
        observationDim = observationDim + offset - (observationDim > channelDim);
    else
        offset = -numSpatialDims;
        observationDim = observationDim + offset;
    end
    channelDim = 1;
    timeDim = timeDim + offset;
end
end