% SLCOVERAGE.BLOCKSELECTOR Block selector class
%   Selects a block for filtering by its properties.
%   so = slcoverage.BlockSelector(type, name) - creates a selector object
%       type - slcoverage.BlockSelectorType
%       name - property name, block handle or Simulink ID
%
% SLCOVERAGE.BLOCKSELECTOR methods:
%   slcoverage.BlockSelector.allSelectors(blockH) - all BlockSelectors
%                                                   for a block
% See also: SLCOVERAGE.BLOCKSELECTORTYPE, SLCOVERAGE.FILTERRULE,
%           SLCOVERAGE.FILTER

% Copyright 2017-2020 The MathWorks, Inc.

classdef BlockSelector < slcoverage.Selector

properties (SetAccess = private)
end
methods
   function  this = BlockSelector(type, name)
        [status, msgId] = SlCov.CoverageAPI.checkCvLicense;
        if status == 0
            error(message(msgId));
        end
        sid = '';
        if ~isequal(type, slcoverage.BlockSelectorType.Subsystem) && ... % this should be Library
           ~isequal(type,  slcoverage.BlockSelectorType.TemporalEvent) && ...
           ~isequal(type,  slcoverage.BlockSelectorType.BlockType) && ...
           ~isequal(type,  slcoverage.BlockSelectorType.MaskType)
            if ~Simulink.ID.isValid(name)
                try 
                    name = Simulink.ID.getSID(name);
                    sid = name;
                catch
                end
            else
                sid = name;
            end
        end
        p = inputParser;
        typeValidationFcn = @(x)validateattributes(x, {'slcoverage.BlockSelectorType'}, {'scalar'}, 'BlockSelector', 'type', 1);
        sidValidationFcn = @(x)validateattributes(x, {'char'}, {'vector'}, 'BlockSelector', 'name', 2);
        p.addRequired('type', typeValidationFcn);
        p.addRequired('name', sidValidationFcn);
        parse(p, type, convertStringsToChars(name));
        this@slcoverage.Selector(sid, p.Results.type, p.Results.name);
        this.setConstructorCode(sprintf('slcoverage.BlockSelector(%s, ''%s'')', mat2str(p.Results.type), p.Results.name));
   end
end
%===================
methods  (Static = true)   
    function s = allSelectors(blockH)
        s = slcoverage.Selector.allSelectors(blockH, 'Type', 'slcoverage.BlockSelectorType');
    end
end

methods (Hidden = true)
    function codeSelectors = convertToCodeSelectors(this, ccd)
        codeSelectors = {};
        block = ccd.CodeTr.findSLModelElementBySID(this.SId);
        if ~isempty(block)

            % Conditions
            condCovPts = ccd.CodeTr.getConditionPoints(block);
            for c = 1:numel(condCovPts)
                condCovPt = condCovPts(c);
                fcn = condCovPt.node.function;
                funcName = fcn.name;
                file = fcn.location.file;
                fileName = file.shortPath;
                expr = condCovPt.node.getSourceCode();
                exprIdx = find(ccd.CodeTr.getConditionPoints(fcn) == condCovPt);
                codeSelectors{end+1} = slcoverage.CodeSelector(...
                    slcoverage.CodeSelectorType.Condition, ...
                    fileName, funcName, expr, exprIdx); %#ok<AGROW>
            end

            % Decisions
            decCovPts = ccd.CodeTr.getDecisionPoints(block);
            for d = 1:numel(decCovPts)
                decCovPt = decCovPts(d);
                fcn = decCovPt.node.function;
                funcName = fcn.name;
                file = fcn.location.file;
                fileName = file.shortPath;
                expr = decCovPt.node.getSourceCode();
                exprIdx = find(ccd.CodeTr.getDecisionPoints(fcn) == decCovPt);
                codeSelectors{end+1} = slcoverage.CodeSelector(...
                    slcoverage.CodeSelectorType.Decision, ...
                    fileName, funcName, expr, exprIdx); %#ok<AGROW>
            end
        end
    end
end
end
