function  [traceMcdcTrue, traceMcdcFalse] = processMcdcTrace( ...
    rootId, lhs_cvdata, rhs_cvdata, ...
    lhsMetricDataAll, rhsMetricDataAll, ...
    joinedAggregatedTestInfo)
%
                                           
%   Copyright 2019 The MathWorks, Inc.


    persistent mcdcEnumVal
    if isempty(mcdcEnumVal)
        mcdcEnumVal = cvi.MetricRegistry.getEnum('mcdc');  
    end
    
    metricSize = size(lhs_cvdata.metrics.mcdc);
    traceMcdcTrue = cell(metricSize);
    traceMcdcFalse = cell(metricSize);
    if (lhs_cvdata.modelinfo.mcdcMode == SlCov.McdcMode.Masking) && ...
       (rhs_cvdata.modelinfo.mcdcMode == SlCov.McdcMode.Masking)
        % Find all mcdcentry objects under specified root.
        cvId = cv('get',rootId,'.topSlsf');
        allSlsfObjs = cv('DecendentsOf',cvId);
        mcdcObjs = cv('MetricGet', allSlsfObjs, mcdcEnumVal,'.baseObjs');
        mcdcObjs(mcdcObjs == 0) = [];

        for mcdcIdx=1:length(mcdcObjs)
            [numPredicates, predSatisfied] = cv('get', mcdcObjs(mcdcIdx), ...
                '.numPredicates', '.dataBaseIdx.predSatisfied');
            for predIdx = 1:numPredicates
                predSatIdx = predSatisfied + predIdx; % Index into predSatisfied section of data
                [traceT, traceF] = processMaskingMcdcTraceForPredicate(predSatIdx, ...
                                        lhs_cvdata, rhs_cvdata, ...
                                        lhsMetricDataAll, rhsMetricDataAll, ...
                                        joinedAggregatedTestInfo);
                                    
                traceMcdcTrue{predSatIdx} = traceT; %#ok<AGROW>
                traceMcdcFalse{predSatIdx} = traceF; %#ok<AGROW>
            end
        end
    end
end


function  [cTrace_T, cTrace_F]  = processMaskingMcdcTraceForPredicate(predSatIdx, ...
    lhs_cvdata, rhs_cvdata, ...
    lhsMetricDataAll, rhsMetricDataAll, ...
    joinedAggregatedTestInfo)

    % This might be empty if the metric is not present, treat as zero
    lhsPredSat = SlCov.PredSatisfied.Unknown;
    if ~isempty(lhsMetricDataAll)
        lhsPredSat = lhsMetricDataAll(predSatIdx);
    end
    rhsPredSat = SlCov.PredSatisfied.Unknown;
    if ~isempty(rhsMetricDataAll)
        rhsPredSat = rhsMetricDataAll(predSatIdx);
    end

    lhs_isTrueExecuted = isTrueOutHit(lhsPredSat);
    lhs_isFalseExecuted = isFalseOutHit(lhsPredSat);
    rhs_isTrueExecuted = isTrueOutHit(rhsPredSat);
    rhs_isFalseExecuted = isFalseOutHit(rhsPredSat);

    cTrace_T = combineTrace('mcdcTrue', lhs_isTrueExecuted, rhs_isTrueExecuted);
    cTrace_F = combineTrace('mcdcFalse', lhs_isFalseExecuted, rhs_isFalseExecuted);
    
    
    
    function cTrace = combineTrace(type, lhs_isOutcomeExecuted, rhs_isOutcomeExecuted)
        lhs_ExistingTrace = [];
        if isfield(lhs_cvdata.trace, type)
            lhs_ExistingTraceAll = lhs_cvdata.trace.(type);
            if ~isempty(lhs_ExistingTraceAll)
                lhs_ExistingTrace = lhs_ExistingTraceAll{predSatIdx};
            end
        end
        rhs_ExistingTrace = [];
        if isfield(rhs_cvdata.trace, type)
            rhs_ExistingTraceAll = rhs_cvdata.trace.(type);
            if ~isempty(rhs_ExistingTraceAll)
                rhs_ExistingTrace = rhs_ExistingTraceAll{predSatIdx};
            end
        end
        
        lTraceContrib = cvdata.getTraceContributionForSide(...
            lhs_cvdata, lhs_ExistingTrace, ...
            lhs_isOutcomeExecuted, rhs_isOutcomeExecuted, ...
            joinedAggregatedTestInfo, false);

        rTraceContrib = cvdata.getTraceContributionForSide(...
            rhs_cvdata, rhs_ExistingTrace, ...
            rhs_isOutcomeExecuted, lhs_isOutcomeExecuted, ...
            joinedAggregatedTestInfo, true);

        cTrace = unique([lTraceContrib rTraceContrib], 'stable');
    end
end
function res = isTrueOutHit(predSatStatus)
    res = (predSatStatus == SlCov.PredSatisfied.True_Only) || (predSatStatus == SlCov.PredSatisfied.Fully_Satisfied);
end

function res = isFalseOutHit(predSatStatus)
    res = (predSatStatus == SlCov.PredSatisfied.False_Only) || (predSatStatus == SlCov.PredSatisfied.Fully_Satisfied);
end

