function currentTest = deriveFunctionalTestCase(obj, topLevelLogger, tcIdx)
% Create a test case in Simulink.SimulationData.Dataset format from the raw logging data

%   Copyright 2011-2022 The MathWorks, Inc.

    if isa(topLevelLogger,'Simulink.ModelDataLogs')
        % This is legacy logging method
        convertedDatasetLogger = topLevelLogger.convertToDataset('convertedDatasetLogger');
    elseif isa(topLevelLogger,'Simulink.SimulationData.Dataset')
        convertedDatasetLogger = topLevelLogger;
    else
        obj.generateErrorMessageForLogger;
    end

    %% Step 1: Determine the correct order of logged dataset signals

    % Example: When inports 'In1' and 'In2' are logged, Simulink does not guarantee any order in which they appear in
    % logged dataset. Observe that in the below logged dataset 'In2' appears at dataset index 1. This is not a desired
    % order.
    % ==============================================================
    % Simulink.SimulationData.Dataset 'Test Case:1' with 2 elements
    %
    %                          Name                    BlockPath
    %                          ----------------------  -----------
    %     1  [1x1 Signal]      dvInputSignalLogger_1   model1/In2
    %     2  [1x1 Signal]      dvInputSignalLogger_2   model1/In1
    % ==============================================================
    % Also user may have enabled logging for few additional signals. They must be ignored when generating test cases.

    if obj.isNoModelRef
        dsSignalOrder = getSignalOrderUsingLogginName(obj, convertedDatasetLogger);
    else
        dsSignalOrder = getSignalOrderUsingBlockPath(obj, convertedDatasetLogger);
    end

    %% Step 2: Construct a new dataset with the correct signal order

    currentTest = Simulink.SimulationData.Dataset;
    currentTest.Name = sprintf('%s:%d','Test Case', tcIdx);

    for idx = 1:numel(dsSignalOrder)
       currentTest{idx} = convertedDatasetLogger{dsSignalOrder(idx)};
    end
end

function dsSignalOrder = getSignalOrderUsingBlockPath(obj, ds)
    dsSignalOrder = [];
    portCount = ds.numElements;

    % If a model has bus element ports at root level, multiple bus element ports handles are logged.
    % But their logged values appear as one Simulink.SimulationData.Signal object in dataset.
    % Use block paths to determine the correct order of signals.
    if portCount > 0
        portPath{portCount} = [];

        for idx = 1:portCount
            portBlockPath = ds{idx}.BlockPath;
            portPath{idx} = portBlockPath.getBlock(portBlockPath.getLength);
        end
        res = get_param(portPath, 'PortHandles');
        portHs = cellfun(@(x) x.Outport, res);

        % 'stable' guarantees the correct order
        [~, ~, dsSignalOrder] = intersect(obj.PortHsToLog, portHs, 'stable');
    end
end

function dsSignalOrder = getSignalOrderUsingLogginName(obj, ds)
    dsSignalOrder = [];
    if ds.numElements > 0
        orderedLoggerNames =  string(obj.SignalLoggerPrefix) + (1:numel(obj.PortHsToLog));
        dsNames = string(ds.getElementNames);

        % 'stable' guarantees the correct order
        [~, ~, dsSignalOrder] = intersect(orderedLoggerNames, dsNames, 'stable');
    end
end
