% SLCOVERAGE.SFCNSELECTOR S-Function filter selector class
%   Selects S-Function block for filtering by it properties.
%   so = slcoverage.SFcnSelector(type, blockH, fileName, funName, expr, exprIdx) - creates a selector object
%       type     - slcoverage.SFcnSelectorType
%       blockH   - block handle, Simulink ID or property name
%       fileName - c++/c file name
%       funName  - c++/c function name
%       expr     - expression to filter
%       exprIdx  - expression index
%
% SLCOVERAGE.SFCNSELECTOR methods:
%   slcoverage.SFcnSelector.allSelectors(blockH) - all SFcnSelectors
%                                                  for a block
% See also: SLCOVERAGE.SFCNSELECTORTYPE, SLCOVERAGE.FILTERRULE,
%           SLCOVERAGE.FILTER

% Copyright 2017 The MathWorks, Inc.

classdef SFcnSelector < slcoverage.Selector 
properties (SetAccess = private)
    FileName  = '';
    FunctionName = '';
    Expr = '';
end    
properties (Hidden = true)
    ExprIndex = [];
    IsDec = [];
end
methods

    function  this = SFcnSelector (type, name, varargin)
        narginchk(2, 6);        
        
        [status, msgId] = SlCov.CoverageAPI.checkCvLicense;
        if status == 0
            error(message(msgId));
        end
        
        [varargin{:}] = convertStringsToChars(varargin{:});
        
        p = inputParser;
        typeValidationFcn = @(x)validateattributes(x, {'slcoverage.SFcnSelectorType'}, {'scalar'}, 'SFcnSelector', 'type', 1);
        p.addRequired('type', typeValidationFcn);
        parse(p, type);
        type = p.Results.type;
        constructorCode = 'slcoverage.SFcnSelector(';
        sid = '';
        id = '';
        try 
            name = Simulink.ID.getSID(name);
        catch
        end

        if contains(name, ':') || Simulink.ID.isValid(name)
            sidValidationFcn = @(x)validateattributes(x, {'char'}, {'vector'}, 'SFcnSelector', 'sid', 1);
            p1 = inputParser;
            p1.addRequired('sid', sidValidationFcn);
            parse(p1, name);
            sid = p1.Results.sid;
            id = sid; 
            constructorCode = [constructorCode sprintf('%s, ''%s'', ', mat2str(type), id)];
        elseif isequal(type, slcoverage.SFcnSelectorType.SFcnName)
             sfcnNameValidationFcn = @(x)validateattributes(x, {'char'}, {'vector'}, 'SFcnName', 'SFcnName', 1);                        
             p1 = inputParser;
             p1.addRequired('SFcnName', sfcnNameValidationFcn );
             parse(p1, convertStringsToChars(name));
             id = p1.Results.SFcnName;
             constructorCode = [constructorCode sprintf('%s, ''%s''', mat2str(type), id)];
        end
        this@slcoverage.Selector(sid, type, id);
        p2 = inputParser;
        p2.StructExpand = false;        
        alwaysTrue = @(x)true;
        switch type
            case  { slcoverage.SFcnSelectorType.SFcnInstanceCppDecision, slcoverage.SFcnSelectorType.SFcnInstanceCppCondition}
                    fileNameValidationFcn = @(x)validateattributes(x, {'char'}, {'vector'}, 'SFcnSelector', 'FileName', 1);        
                    funNameValidationFcn = @(x)validateattributes(x, {'char'}, {'vector'}, 'SFcnSelector', 'FunName', 2);        
                    exprValidationFcn = @(x)validateattributes(x, {'char'}, {'vector'}, 'SFcnSelector', 'Expr', 3);        
                    exprIdxValidationFcn = @(x)validateattributes(x, {'numeric'}, {'positive', 'nonzero','scalar'}, 'SFcnSelector', 'ExprIdx', 4);
                    p2.addRequired('FileName', fileNameValidationFcn);
                    p2.addRequired('FunName', funNameValidationFcn);
                    p2.addRequired('Expr', exprValidationFcn);
                    p2.addRequired('ExprIdx', exprIdxValidationFcn);
                    parse(p2, varargin{:});
                    
                    this.FileName  = p2.Results.FileName;
                    this.FunctionName = p2.Results.FunName;
                    this.Expr = p2.Results.Expr;
                    this.ExprIndex = p2.Results.ExprIdx;
                    this.IsDec = isequal(type, slcoverage.SFcnSelectorType.SFcnInstanceCppDecision);
                    constructorCode = [constructorCode sprintf('''%s'', ''%s'', ''%s'', %s', this.FileName, this.FunctionName, this.Expr, mat2str(this.ExprIndex))];
                   
            case {slcoverage.SFcnSelectorType.SFcnInstanceCppFunction}
                    fileNameValidationFcn = @(x)validateattributes(x, {'char'}, {'vector'}, 'SFcnSelector', 'FileName', 1);        
                    funNameValidationFcn = @(x)validateattributes(x, {'char'}, {'vector'}, 'SFcnSelector', 'FunName', 2);        
                    p2.addRequired('FileName', fileNameValidationFcn);
                    p2.addRequired('FunName', funNameValidationFcn);
                    p2.addOptional('Expr', '', alwaysTrue);  
                    p2.addOptional('ExprIdx', [], alwaysTrue);
                    parse(p2, varargin{:});
                    this.FileName  = p2.Results.FileName;
                    this.FunctionName = p2.Results.FunName;
                    constructorCode = [constructorCode sprintf('''%s'', ''%s''', this.FileName, this.FunctionName)];

            case {slcoverage.SFcnSelectorType.SFcnInstanceCppFileName}
                    fileNameValidationFcn = @(x)validateattributes(x, {'char'}, {'vector'}, 'SFcnSelector', 'FileName', 1);        
                    p2.addRequired('FileName', fileNameValidationFcn);
                    p2.addOptional('FunName', '', alwaysTrue);
                    p2.addOptional('Expr', '', alwaysTrue);  
                    p2.addOptional('ExprIdx', [], alwaysTrue);                    
                    parse(p2, varargin{:});
                    this.FileName  = p2.Results.FileName;
                    constructorCode = [constructorCode sprintf('''%s''', this.FileName)];
        end

        constructorCode = [constructorCode ')'];
    	this.setConstructorCode(constructorCode );
    end
end
%===================
methods  (Static = true)    
    function s = allSelectors(blockH)
        s = slcoverage.Selector.allSelectors(blockH, 'Type', 'slcoverage.SFcnSelectorType');
    end
end


end
