
%

%   Copyright 2014-2020 The MathWorks, Inc.

classdef InactiveMPSwitch < Transform.SwitchMSSwitchTransform
    properties
        pivotBlockType = 'MultiPortSwitch';
    end

    methods
        function yesno = applicable(obj, bh, cvd)
            yesno = strcmp(get(bh,'BlockType'), 'MultiPortSwitch');
        end

        function [inactiveV, inactiveIn, contextH] = analyze(obj, bh, ...
                                                             ~, cvd, ~)
            %  Make sure the model is in compiled stage
 
            [inactiveIn, red] = getInactiveMPSwitchInputs(bh, cvd);

            inactiveV = [];
            contextH = [];

            % Add redundant switches
            if isempty(obj.redundant)
                obj.redundant = red;
            else
                obj.redundant = [obj.redundant; red];
            end
        end


        function obj = InactiveMPSwitch()
        % Constructor
            obj.redundant = struct('handle', {}, 'index', {});
        end


        function keeps = filterDeadBlocks(obj, handles)
            if ~isempty(obj.redundant)
                s = [obj.redundant.handle];
                filter = arrayfun(@(x)~any(handles==x), s);
                obj.redundant = obj.redundant(filter);
            end
            keeps = [];
        end
    end
end

function [inactiveIn, red] = getInactiveMPSwitchInputs(bh, cvd)
    [~, detail] = cvd.getDecisionInfo(bh);


    % MPSwitch block, each outcome is associated with an input port
    % outcome 1 --> input 2
    % outcome 2 --> input 3
    % ...
    activeIdx = [];
    inactiveIn = [];
    ph = get(bh, 'PortHandles');

    % Early return for Muxed inputs into data port
    if (length(ph.Inport) == 2)
        red = struct('handle', {}, 'index', {});
        return;
    end

    %%
    % MultiPort Switch block might be scalar-expanded
    n = length(detail.decision);
    m = length(detail.decision(1).outcome);
    D = false(n, m);
    for k = 1:length(detail.decision)
        for i=1:length(detail.decision(k).outcome)
            D(k,i) = detail.decision(k).outcome(i).executionCount > 0;
        end
    end

    d = any(D, 1);
    for i=1:length(d)
        if ~d(i)
            inactiveIn = [inactiveIn; ph.Inport(i+1)]; %#ok<AGROW>
        else
            activeIdx = [activeIdx; i]; %#ok<AGROW>
        end
    end


    % If only one is active, the switch is redundant
    if length(activeIdx) == 1
        % The control port is also inactive
        inactiveIn = [inactiveIn; ph.Inport(1)];
        % The switch block is redundant
        red = struct('handle', bh, 'index', activeIdx+1);
    else
        red = struct('handle', {}, 'index', {});
    end

end



