function MessageHandler(type, arg1, mdlName, UImode)

    % Message Viewer handler for Model Slicer messages
    %
    %   Copyright 2014-2018 The MathWorks, Inc.
    
    persistent mvStage;
    persistent MExp; % Exeption storage for debugging
    
    if ~exist('mvStage','var')
        mvStage = [];
    end
    
    StageName = getString(message('Sldv:ModelSlicer:gui:ModelSlicerProductName'));
    ComponentName = 'Simulink Check';
    CategoryName = 'Model Slicer';
    
    switch type
        case 'open'
            if ~isValidStage(mvStage)
                mvStage = Simulink.output.Stage(StageName,'ModelName', arg1, 'UIMode',true);
            end
        case 'close'
            if isa(mvStage,'Simulink.output.Stage')
                mvStage.delete;
            end
        case 'dump_error'
            dumpError(MExp)
        otherwise
            % Converting from mesage ID to an exception.
            if ischar(arg1)
                try
                    msg = getString(message(['Sldv:ModelSlicer:' arg1]));
                    msgID = arg1;
                catch
                    msg = arg1;
                    msgID = 'ModelSlicer:Unknown';
                end
                Mex = MException(msgID,'%s',msg);
            else
                Mex = arg1;
            end
            switch type
                case 'error'
                    MExp = Mex;
                    if isValidStage(mvStage)
                        Simulink.output.error(Mex,...
                            'Component',ComponentName,...
                            'Category',CategoryName);
                    else
                        throw(Mex);
                    end
                case 'single_error'
                    MExp = Mex;
                    if UImode
                        mvStage = Simulink.output.Stage(StageName,'ModelName', mdlName, 'UIMode',true);
                        Simulink.output.error(Mex,...
                            'Component',ComponentName,...
                            'Category',CategoryName);
                        mvStage.delete
                    else
                        throw(Mex)
                    end
                case 'warning'
                    if isValidStage(mvStage)
                        msle = MSLException(Mex,...
                            'COMPONENT',ComponentName,...
                            'CATEGORY',CategoryName );
                        MSLDiagnostic(msle).reportAsWarning;
                        slmsgviewer.show(mdlName);
                    else
                        if ischar(Mex)
                            warning(Mex);
                        else
                            warning(Mex.identifier,Mex.message);
                        end
                    end
                case 'single_warning'
                    if UImode
                        mvStage = Simulink.output.Stage(StageName,'ModelName', mdlName, 'UIMode',true);
%                         Simulink.output.warning(Mex,...
%                             'Component',ComponentName,...
%                             'Category',CategoryName);
                        msle = MSLException(Mex,...
                            'COMPONENT',ComponentName,...
                            'CATEGORY',CategoryName );
                        MSLDiagnostic(msle).reportAsWarning;
                        slmsgviewer.show(mdlName);
                        mvStage.delete
                    else
                        if ischar(Mex)
                            warning(Mex);
                        else
                            warning(Mex.identifier,Mex.message);
                        end
                    end
                case 'info'
                    Simulink.output.info(Mex,...
                        'Component',ComponentName,...
                        'Category',CategoryName);
                otherwise
                    assert(false);
            end
    end
end
function yesno = isValidStage(stage)
    if isa(stage,'Simulink.output.Stage') && stage.isvalid
        yesno = true;
    else
        yesno = false;
    end
end

function dumpError(me)
    % Dump previously thrown exception into command window
    % for debugging purpose.
    try
        if isstruct(me)
            dispError(me)
        elseif isa(me,'MException')
            dispError(me)
            for n=1:length(me.cause)
                dispError(me.cause{n})
            end            
        end
    catch
    end
    function dispError(mex)
        disp(mex.message)
        disp(mex.identifier)
        if exist([matlabroot, '/toolbox/sldv/slicer/@ModelSlicer/ModelSlicer.m'], 'file') == 2
            installedmatlab = false;
        else
            installedmatlab = true;
        end
        for k=1:length(mex.stack)
            if installedmatlab
                fprintf('[%d] %s:%d\n',k, mex.stack(k).file,mex.stack(k).line);
            else
                [filepath, filename, fileext] = fileparts(mex.stack(k).file);
                if strcmp(fileext, '.p')
                    fileext = '.m';
                end
                filefullpath = [filepath, filesep, filename, fileext];
                hyperlinkinfo = ...
                    ['<a href="matlab:opentoline(''', filefullpath, ''', ', num2str(mex.stack(k).line), ');">', filename, fileext, '</a>'];
                fprintf('[%d] %s:%d\n', k, hyperlinkinfo, mex.stack(k).line);
            end
        end
    end
end
