function testCaseCompressed = compressTestCaseData(testCase)
%

%   Copyright 2008-2018 The MathWorks, Inc.

    testCaseCompressed = testCase;

    if isempty(testCaseCompressed.dataValues)
        return;
    end 

    ultimateDataIndex = [];

    for i=1:length(testCaseCompressed.dataValues)   % Loop over each port
        inportDataIndex = generateDataIndexForInport(testCaseCompressed.dataValues{i}, ...
                                                     testCaseCompressed.timeValues);
        if isempty(ultimateDataIndex)
            ultimateDataIndex = inportDataIndex;
        else
            ultimateDataIndex = union(inportDataIndex, ultimateDataIndex);
        end
    end

    finalTimeValues = testCaseCompressed.timeValues(ultimateDataIndex);

    if ~(length(testCaseCompressed.timeValues) == length(finalTimeValues) && ...
         all(testCaseCompressed.timeValues == finalTimeValues))

        % Loop over each port and resample the dataValues
        for i=1:length(testCaseCompressed.dataValues)
            dataValues = constructCompressedDataValues(ultimateDataIndex, ...
                                                     testCaseCompressed.timeValues, ...
                                                     testCaseCompressed.dataValues{i});
            testCaseCompressed.dataValues{i} = dataValues;
        end
        for i=1:length(testCaseCompressed.dataNoEffect)
            dataNoEffect = constructCompressedDataValues(ultimateDataIndex, ...
                                                       testCaseCompressed.timeValues, ...
                                                       testCaseCompressed.dataNoEffect{i});
            testCaseCompressed.dataNoEffect{i} = dataNoEffect;
        end
        testCaseCompressed.timeValues = finalTimeValues;
        testCaseCompressed.stepValues = ultimateDataIndex;
    else
        if isempty(testCaseCompressed.stepValues)
            % If dataValues are in compressed format then it must have
            % the stepValues in sldvData. 

            % This block of code will be executed for the scenario,
            % when the dataValue is changing at every timeStamp, so
            % there is no scope for further compression.
            testCaseCompressed.stepValues = ultimateDataIndex;
       end
    end
end

function inportDataIndex = generateDataIndexForInport(inportTestData, timeValues)
    if ~iscell(inportTestData)
        % inportTestData corresponds to a non-bus / non-bus-array signal
        [Dimensions, numTimeSteps] = Sldv.DataUtils.getDimAndTime(inportTestData, timeValues);

        % If skipData(i) is true, data values at i^th and (i+1)^th time
        % steps are the same. So we can skip the data values at the
        % (i+1)^th time step
        skipData = generateDataDiff(inportTestData, numTimeSteps, Dimensions);

        inportDataIndex(1) = 1;
        counter = 2;
        for i=1:numTimeSteps-1
            if ~skipData(i)
                inportDataIndex(end+1) = counter; %#ok<AGROW>
            end
            counter = counter+1;
        end
        if inportDataIndex(end) ~= numTimeSteps
            inportDataIndex(end+1) = numTimeSteps;
        end
    else
        % inportTestData corresponds to a bus or a bus array. So iterate
        % over each element
        inportDataIndex = [];
        for i=1:numel(inportTestData)
           subInportDataIndex = generateDataIndexForInport(inportTestData{i},...
                                                           timeValues);
           if isempty(inportDataIndex)
               inportDataIndex = subInportDataIndex;
           else
               inportDataIndex = union(inportDataIndex,subInportDataIndex);
           end
        end
    end
end

function skipData = generateDataDiff(inportTestData, numTimeSteps, Dimensions)
    flatData = reshape(inportTestData, [prod(Dimensions) numTimeSteps]);
    skipData = logical(zeros(1, numTimeSteps-1)); %#ok<LOGL>
    for i=1:numTimeSteps-1
        % Compare the data values at i^th and (i+1)^th time steps
        skipData(i) = isequal(flatData(:, i+1), flatData(:, i));
    end
end

function dataValues = constructCompressedDataValues(ultimateDataIndex, ...
                                                    timeValues, ...
                                                    inportTestData)
    if ~iscell(inportTestData)
        % inportTestData corresponds to a non-bus / non-bus-array signal
        [Dimensions, numTimeSteps] = Sldv.DataUtils.getDimAndTime(inportTestData, timeValues);

        dt = Sldv.DataUtils.flattenData(numTimeSteps, Dimensions, inportTestData);
        dt = dt(:, ultimateDataIndex);

        numCompressedTimeSteps = length(ultimateDataIndex);

        dataValues = Sldv.DataUtils.reshapeData(numCompressedTimeSteps, Dimensions, dt);
    else
        % inportTestData corresponds to a bus or a bus array. So iterate
        % over each element
        dataValues = cell(size(inportTestData));
        for i=1:numel(inportTestData)
            dataValues{i} = constructCompressedDataValues(ultimateDataIndex, ...
                                                          timeValues, ...
                                                          inportTestData{i});
        end
    end
end