function sldvDvirOutData = genDvirSimOutData(model, testcomp)
%

%   Copyright 2012-2022 The MathWorks, Inc.


if ischar(model)
    try
        modelH = get_param(model,'Handle');
    catch myException %#ok<NASGU>
        modelH = [];
    end
    modelName = model;
else
    modelH = model;
    modelName = get_param(model, 'Name');
end

if isempty(testcomp)
    error(message('Sldv:DataUtils:NoTestComp'));
end

% Add model information
ModelInformation = Sldv.DataUtils.getModelInformation(modelH,'datagen',testcomp);

% Add all analysis information such as root level input/output types
AnalysisInformation = Sldv.DataUtils.getAnalysisInformation(testcomp, modelH);

[~, AnalysisInformation.ReplacementInfo] = ...
    Sldv.DataUtils.getReplacementInfo(testcomp);

% Construct test cases
%     warningIds = Sldv.DataUtils.getWarningIds;
%     warningStatus = Sldv.DataUtils.turnOffAndStoreWarningStatus(warningIds);
busMap = containers.Map('KeyType','char','ValueType','any');
dataAcc = Simulink.data.DataAccessor.create(modelName);
funTs = sldvprivate('mdl_fundamental_ts', modelH, testcomp);
SimOutputs = {};
simOutputs = sldvprivate('sldv_datamodel_get_simoutputs',testcomp);
simOutputsTranspose = simOutputs';
for idx = 1:length(simOutputsTranspose)
    simout = simOutputsTranspose(idx);
    if isempty(simout.down)
        SimOutputs = addSimOutput(modelName, dataAcc, busMap, simout, funTs, SimOutputs, ...
            AnalysisInformation.OutputPortInfo);
    end
end

%     Sldv.DataUtils.restoreWarningStatus(warningStatus, warningIds);

%%% Putting it all together
sldvDvirOutData.ModelInformation = ModelInformation;
sldvDvirOutData.AnalysisInformation = AnalysisInformation;
if ~isempty(SimOutputs)
    sldvDvirOutData.DvirSimOutputs = SimOutputs;
end
sldvDvirOutData = Sldv.DataUtils.setVersionToCurrent(sldvDvirOutData);
end

function SimOutputs = addSimOutput(modelName, dataAcc, busMap, simout, funTs, SimOutputs, portInfo)
[timeValues, dataValues] = getDataValue(simout, funTs);

if isempty(timeValues) || isempty(dataValues)
    return;
end

dataSLDataSet = Sldv.DataUtils.convertToSLDataSet(modelName, dataAcc, busMap, dataValues, timeValues, ...
    portInfo, funTs, ...
    length(SimOutputs)+1, 'DV IR Simulation', ... %NO_L10N
    false, true);

newSimOut = checkConstantSampleTimes(dataSLDataSet, portInfo);

if isempty(SimOutputs)
    SimOutputs = newSimOut;
else
    SimOutputs(end+1) = newSimOut;
end
end

function [time, data, step] = getDataValue(simout, funTs)
time = [];
data = [];
step = [];
rawData = simout.simoutData;
if isempty(rawData) || (iscell(rawData) && isempty(rawData{1}))
    return;
end

data = rawData;
stepCnt = simout.length;
stepCnt = double(stepCnt);
time = funTs*(0:stepCnt-1);
end

function simOut = checkConstantSampleTimes(dataSLDataSet, portInfo)
simOut = Simulink.SimulationData.Dataset;
simOut.Name = dataSLDataSet.Name;
for idx=1:dataSLDataSet.getLength
    simoutElem = dataSLDataSet.getElement(idx);
    simOut = simOut.addElement(checkElemConstantSampleTime(simoutElem.Values, portInfo{idx}),sprintf('%d',idx));
end
end

function simoutElem = checkElemConstantSampleTime(simoutElem, portInfo)
if isa(simoutElem,'timeseries')
    portTs = portInfo.ParentSampleTime;
    numTimeSamples = length(simoutElem.Time);
    if portTs(1)~=0 && ...
            length(portTs)==1 && ...
            isinf(portTs) && ...
            numTimeSamples>1
        % A constant block is feeding the time we just need one sample
        % time.
        % Let's verify that data stored all have the same value !!!
        data = simoutElem.Data;
        data = reshape(data,[1 prod(size(data))]); %#ok<PSIZE>
        n = length(data);
        for idx=2:n
            assert(data(idx)==data(1));
        end
        simoutElem = delsample(simoutElem,'Index',2:numTimeSamples);
        simoutElem.DataInfo.Interpolation = tsdata.interpolation('linear');
    end
else
    elems = fieldnames(simoutElem);
    n = numel(simoutElem);
    for i=1:n
        for idx=1:length(elems)
            simoutElem(i).(elems{idx}) = ...
                checkElemConstantSampleTime(simoutElem(i).(elems{idx}), portInfo{idx+1});
        end
    end
end
end

% LocalWords:  datamodel
