function origSortedH = fixSortedOrder(origMdlH,sliceMdlH,expandLib,sliceSubSystemH)
%

%   Copyright 2015-2017 The MathWorks, Inc.
    
    if ~isempty(sliceSubSystemH) 
        if Simulink.SubsystemType.isModelBlock(sliceSubSystemH)
            origMdlH = get_param(get_param(sliceSubSystemH,'ModelName'),'handle');
        end
    end
    slicerMap = modelslicerprivate('sliceMdlMapperObj','get',sliceMdlH);
    origSortedH = Analysis.ExpandedSortedlist(origMdlH,expandLib);

    EmptyInd = [];
    sortMapBlockH = [];
    for i = 1:length(origSortedH)
        try
            
            origH = origSortedH(i);
            if bdroot(origH) == origMdlH
                sliceH = slicerMap.findInSlice(origH);
            else
                sliceH = slicerMap.findInSlice(origH,getfullname(bdroot(origH)));
            end
            
            if isempty(sliceH) || ...
                    ~ishandle(sliceH) || ... %g1265898
                    isequal(origH, sliceSubSystemH) %Subsystem extraction already assigns priority
                EmptyInd(end+1) = i; %#ok<*AGROW>
            else
                sortMapBlockH(end+1) = sliceH;
            end
        catch ex %#ok<*NASGU>
            EmptyInd(end+1) = i;
        end
    end

    origSortedH(EmptyInd) = [];
    if isempty(origSortedH)
        return;
    end
    sortMapOrig = containers.Map(origSortedH,1:length(origSortedH));
    
    for i = 1:length(origSortedH)
           if isPriorityValid(sortMapBlockH(i),slicerMap) 
                set_param(sortMapBlockH(i),'Priority',num2str(i)); 
           end  
    end
  
    fixVirtualSubsys(sortMapBlockH,slicerMap);
    
end


function fixVirtualSubsys(sliceBlockH,slicerMap)


% For virtual subsystems, if all blocks underneath are contiguous sorted-order wise
% apply the lowest child priority.

    VirtSubsysMap = containers.Map('keytype','double','ValueType','any');


    for i=1:length(sliceBlockH)

        parentH = get_param(get_param(sliceBlockH(i),'parent'),'handle');

        % Every block propogates its index (priority) up the heirarchy.
        % Virtual subsystem parents check if they have seen the previous
        % index, in which case blocks are contiguous till this. If not, set
        % 0 as last seen index to indicate non-contiguity.
        
        while ~strcmp(get_param(parentH,'type'),'block_diagram')
            
            %Build a Map with only the virtual subsystems.
            
            if strcmp(get_param(parentH,'IsSubsystemVirtual'),'on')
                
                if VirtSubsysMap.isKey(parentH)
                    
                    val = VirtSubsysMap(parentH);
                    minp = val(1);
                    maxp = val(2);

                    if(maxp ~= 0)
                        if(i ~= maxp+1)
                           maxp = 0; %Non-contiguous Virtual subsystem
                        else
                           maxp = i;
                        end

                        VirtSubsysMap(parentH) = [minp,maxp];
                    end
                else
                    %This virtual subsystem is seen for the first time. If
                    %blocks happen to be contiguous, the lowest possible
                    %priority would be the current value of i.
                    
                    VirtSubsysMap(parentH) = [i,i];
                end
                
            end 
            
            %Go up the heirarchy.
            parentH =  get_param(get_param(parentH,'parent'),'handle');

        end

    end
    
    vSubsys = keys(VirtSubsysMap);
    
    for i = 1:length(vSubsys)
        
        val = VirtSubsysMap(vSubsys{i});
        
        p = val(1);
        valid = val(2);
        
        if valid
            
           vSubsysH = vSubsys{i};           
           if isPriorityValid(vSubsysH,slicerMap)
               set_param(vSubsysH,'Priority',num2str(p));
           end
           
        end
        
    end

end


function flag = isPriorityValid(blockh,slicerMap)

%Function to determine if we should set priority for a block
    try
        bType = get_param(blockh,'blocktype');
        
        if ~strcmp(bType,'SubSystem')
            
            if strcmp(get(blockh, 'Virtual'), 'on') %Not reliable unless model is in compiled state.
                
                if strcmp(bType,'Outport') %Outports are non-virtual only at the root level
                    flag = (get_param(get_param(blockh,'parent'),'handle') == bdroot(blockh));
                    return;
                end
                
                % Do not assign  priorities to ports that maybe virtual.
                flag = false;
                return;
            end
            flag = true;
            return;
        end
        
        % Do not set priorities for Function-call subsystems
        
        
        origH = slicerMap.findInOrig(blockh);
        
        if(isempty(origH))
            %Newly introduced subsystem. Should not be Function-Call
            flag = true;
            return;
        end
        
        %Original model is in compiled state. Get compiled port info.
        ssPorts = get_param(origH,'CompiledPortDataTypes');
        if strcmp(ssPorts.Trigger,'fcn_call')
            flag = false;
            return;
        end
        flag = true;
    catch 
        flag = false;
    end

end
