function objects = prepareObjects(opts, data, createLink, justifiedInfo)
%

%   Copyright 2008-2023 The MathWorks, Inc.

    if nargin < 4
        justifiedInfo.objectives = [];
        justifiedInfo.rationales = [];
    end

    if isempty(data.ModelObjects)
        objects = [];
        return;
    end
    objects = struct('designModel', [], 'observerModel', []);

    for i = 1:length(data.ModelObjects)
        modelObj = data.ModelObjects(i);
        if ~isempty(modelObj.objectives)
            [sid, modelName] = Sldv.ReportUtils.getSidFromModelObjectData(data, modelObj);
            if isempty(sid)
                sid = modelObj.descr;
            end

            % If current block belongs to any of the Observers, we need to
            % add it to the observer section
            if isfield(modelObj, 'modelScope') && strcmp(modelObj.modelScope, 'ObserverReference')
                % Get the observer model name
                modelToLink = Sldv.ReportUtils.getModelNameFromSid(sid);
                sectionToReport = 'observerModel';
            else
                modelToLink = modelName;
                sectionToReport = 'designModel';
            end

            if isempty(modelToLink)
                modelToLink = Sldv.ReportUtils.getAnalyzedModelName(data);
            end

            link = Sldv.ReportUtils.externalLink(...
                sid, getString(message('Sldv:RptGen:View')), modelToLink, true);
            objects.(sectionToReport)(end+1).label = modelObj.descr;
            if createLink
                objects.(sectionToReport)(end).link = { link };
            else
                objects.(sectionToReport)(end).link = { };
            end
            objects.(sectionToReport)(end).table = buildObjectivesTable(opts, data, modelObj.objectives, createLink, justifiedInfo);
         end
    end

    % If there are no observers, remove the observer section
    if ~isfield(data.ModelObjects,'modelScope')
        objects = rmfield(objects, 'observerModel');
    end
end

function table = buildObjectivesTable(opts, data, objIndices, createLink, justifiedInfo)
    objIndices = filterReportedObjectives(opts, data, objIndices);
    sldvOptions = data.AnalysisInformation.Options;
    if isempty(objIndices)
        table = {};
    else        
        colHeaders = ({...
                        getString(message('Sldv:RptGen:HashColon')),...
                        getString(message('Sldv:RptGen:Type')),...
                        getString(message('Sldv:RptGen:Description')),...
                        getString(message('Sldv:RptGen:Status')),...
                        getString(message('Sldv:RptGen:TestCase'))...
                    });
        if Sldv.utils.isPathBasedTestGeneration(sldvOptions)
            colHeaders = {colHeaders{(1:3)} ...
                getString(message('Sldv:RptGen:DetectionStatus')) ...
                colHeaders{(4:end)}};
        end
        
        table = cell(length(objIndices)+1, length(colHeaders));
        table(1,:) = deal(colHeaders);

        % Need a special action for SIL-based objectives
        isXilData = Sldv.DataUtils.isXilSldvData(data);

        for j=1:length(objIndices)
            coi = objIndices(j);
            objective = data.Objectives(coi);

            % Check if this objective was justified after analysis
            justifiedIdx = sldvshareprivate('util_get_obj_idx_in_list', objective, justifiedInfo.objectives);
            
            strId = num2str(coi);
            if isempty(justifiedIdx) && isfield(objective, 'testCaseIdx') && ~isempty(objective.testCaseIdx)
                link = Sldv.ReportUtils.internalLink('TestCase', objective.testCaseIdx);
            else
                link = getString(message('Sldv:KeyWords:NA'));
            end

            if isXilData
                coDescr = sldv.code.xil.ReportDataUtils.makeRptCodeLink(objective, createLink);
            else
                coDescr = objective.descr;
            end

            if ~isempty(justifiedIdx)
                objStatus = 'Justified';
            else
                objStatus = objective.status;
            end
            reportedObjective = { strId, ...
                     sldvprivate('util_translate_ObjectiveType', objective.type), ...
                     coDescr, ...
                     sldvprivate('util_translate_status', objStatus), ...
                     link };
                 
            if Sldv.utils.isPathBasedTestGeneration(sldvOptions)
                observabilityData = Sldv.ReportUtils.getObservabilityInformation( ...
                    objective);
                reportedObjective = {reportedObjective{(1:3)} ...
                    observabilityData ...
                    reportedObjective{(4:end)}};
            end
            table(j+1,:) = deal(reportedObjective(:));
        end
    end
end

function reportedObjs = filterReportedObjectives(opts, data, objs)
    if opts.short
        reportedObjs = [];
        for i=1:length(objs)
            o = data.Objectives(objs(i));
            if ~strcmp(o.status, 'Satisfied')
                reportedObjs = [ reportedObjs objs(i) ]; %#ok<AGROW>
            end
        end
    else
        reportedObjs = objs;
    end
end
