function rmidemo_callback(action, object, varargin)
% A collection of safely wrapped calls to rmi.
% Used by slvnvdemo_fuelsys_req demo.

% Copyright 2009-2018 The MathWorks, Inc.
%

    persistent current_object;

    switch action
        case 'open'
            try
                open_system(object);
            catch Mex %#ok: user might try to open a subsystem when system is closed
                parts = textscan(object, '%s', 'Delimiter', '/');
                system = '';
                for idx = 1:length(parts{1})
                    if isempty(system)
                        system = parts{1}{idx};
                    else
                        system = [system '/' parts{1}{idx}]; %#ok
                    end
                    open_system(system);
                end
            end
            
        case 'highlight'
            try
                get_param(object, 'Handle');  % we want this to error if model is not open
                rmi('highlightModel', object);
            catch Mex %#ok: user might have closed the system
                rmidemo_callback('open', object);
                rmi('highlightModel', object);
            end
            current_object = [];
            
        case 'open_highlight'
            try
                open_system(object);
            catch Mex %#ok: user might have closed the parent system
                rmidemo_callback('open', object);
            end
            rmi('highlightModel', object);
            current_object = [];
            
        case 'view'
            if ~isempty(strfind(object,':')) % SSID provided for stateflow objects
                target = sfprivate('ssIdToHandle', object);
                if isempty(target) % model must have been closed by user
                    model = strtok(object,'/');
                    open_system(model);
                    target = sfprivate('ssIdToHandle', object);
                end
            else  % plain full path for simulink objects
                target = object;
            end
            try 
                rmi('view', target, varargin{1});
            catch Mex %#ok - this happens if model is not open
                model = strtok(object,'/');
                open_system(model);
                rmi('view', target, varargin{1});
            end
            
        case 'locate' 
            unhighlight(current_object);
            if iscell(object)
                for i = 1:length(object)
                    locate_sl(object{i});
                end
            else
                locate_sl(object);
            end
            current_object = object;
                     
        case 'locate_sf' % sf object name expected in 'object'
            unhighlight(current_object);
            current_object = [];
            % get sf handle from name
            try
                target = sfprivate('ssIdToHandle', object);
            catch ME %#ok<NASGU> model must have been closed by user
                target = [];
            end
            if isempty(target) 
                model = strtok(object,'/');
                open_system(model);
                target = sfprivate('ssIdToHandle', object);
            end
            target = get(target, 'Id');
            % unhighlight chart
            chart = obj_chart(target);
            sf('Open', chart);
            sf('Highlight', chart, []);
            sf('ClearAltStyles', chart);
            sf('Redraw', chart);
            % highlight this object
            sf_update_style(target, 'req');
            
        case 'signalgroup' % object should be a sigbuilder, varargin should be a tab index
            unhighlight(current_object);
            try
                rmidemo_callback('open', object);
            catch Mex %#ok - this happens if model is not open
                model = strtok(object,'/');
                open_system(model);
                rmidemo_callback('open', object);
            end
            signalbuilder(object, 'activeGroup', varargin{1});
            set_param(object, 'hiliteAncestors', 'reqInside');
            current_object = object;
            
        case 'report'
            try
                rmi('report', object);
            catch Mex %#ok
                model = strtok(object,'/');
                open_system(model);
                rmi('report', model);
            end
            
        case 'filter'
            rmidemo_callback('open', object);
            filterSettings = rmi.settings_mgr('get', 'filterSettings');
            if isempty(varargin)
                filterSettings.enabled = false;
                filterSettings.tagsRequire = {};
                filterSettings.tagsExclude = {};
            else
            filterSettings.enabled = true;
            filterSettings.tagsRequire = varargin(1);
            filterSettings.tagsExclude = {};
            end
            rmi.settings_mgr('set','filterSettings', filterSettings);
            modelH = rmisl.getmodelh(object);
            rmisl.highlight(modelH);
            current_object = [];
            
        case 'check'
            rmidemo_callback('open', object);
            cd(tempdir);
            rmi('check', object, 'modeladvisor');
            
        case 'doc'
            docname = object;
            [~,~,ext] = fileparts(docname);
            if strncmp(ext, '.doc', 4)
                docPath = [matlabroot '\toolbox\slrequirements\slrequirementsdemos\' docname];
                [hWord, ~] = openWordDoc(docPath);
                if ~isempty(varargin)
                    switch varargin{1}
                        case 'find'
                            hWord.Selection.Find.Text = varargin{2};
                            hWord.Selection.Find.Execute;
                        case 'bookmark'
                            bId = ['@' varargin{2}];
                            rmi.navigate('linktype_rmi_word', docPath, bId, '');
                        otherwise
                            warning(message('Slvnv:rmidemo_callback:UnsupportedLocationType', varargin{1}));
                    end
                end
            elseif any(strncmp(ext, {'.ppt', '.xls'}, 4))  % minimum support for other needed types
                docPath = [matlabroot '\toolbox\slrequirements\slrequirementsdemos\' docname];
                uiopen(docPath);
            else
                warning(message('Slvnv:rmidemo_callback:TypeNotSupported', docname));
            end
            
        case 'folder'
            localFolder = object;
            folderPath = fullfile(matlabroot, 'toolbox', 'slrequirements', 'slrequirementsdemos', localFolder);
            if exist(folderPath, 'dir') == 7
                eval(['!start ' folderPath ]);
            else
                warning(message('Slvnv:rmidemo_callback:NoSuchFolder', folderPath));
            end
            
        case 'remove'
            % We are given either model name or file name
            try
                filePath = get_param(object, 'FileName');
                close_system(object, 0);
            catch ME %#ok<NASGU>
                localFilename = object;
                filePath = which(localFilename);
            end
            if ~isempty(filePath)
                disp(['Removing ' filePath ' ...']);
                delete(filePath);
            else
                disp(['Removing ' localFilename ' ...']);
                try
                    delete(localFilename);
                catch ME %#ok<NASGU>
                    warning(message('Slvnv:rmidemo_callback:NoSuchFile', localFilename));
                end
            end
            
        case 'embed'
            modelName = object;
            open_system(modelName);
            modelH = get_param(modelName, 'Handle');
            rmidata.RmiSlData.getInstance.copyToModel(modelH);
                        
        case 'details'
            % Configure RMI Settings to include detailed doc fragments in report
            reportSettings = rmi.settings_mgr('get', 'reportSettings');
            reportSettings.detailsLevel = logical(object);
            rmi.settings_mgr('set', 'reportSettings', reportSettings);
            rmi.settings_mgr('set', 'settingsTab', 3); % target report tab
            rmi_settings_dlg(); % will this refresh?
            
        case 'settings'
            tabIdx = object; % second arg overloaded to specify target tab
            rmi.settings_mgr('set', 'settingsTab', tabIdx);
            rmi_settings_dlg();
            
        case 'cleanup'
            % ExternalStorage demo modifies filename associations in user
            % preferences and creates extra files in slrequirementsdemos directory.
            % Call this method to restore the original state.
            disp('Performing cleanup ...');
            extModel = 'slvnvdemo_powerwindowController';
            extModelPath = fullfile(matlabroot, 'toolbox', 'slrequirements', 'slrequirementsdemos', [extModel '.slx']);
            if bdIsLoaded(extModel)
                modelH = get_param(extModel, 'Handle');
                rmidata.RmiSlData.getInstance.discard(modelH);
                close_system(extModel, 0);
            end
            rmimap.StorageMapper.getInstance.forget(extModelPath, true);
            extModelReqs = fullfile(fileparts(extModelPath), [extModel '.req']);
            if exist(extModelReqs, 'file') == 2
                delete(extModelReqs);
            end
            % user might have not removed these other files, and we do not
            % know the workdir, but will, at least check locally:
            otherModel = 'fuelsys_officereq_copy';
            if bdIsLoaded(otherModel)
                otherModelFile = get_param(otherModel, 'FileName');
                close_system(otherModel, 0);
            else
                otherModelFile = which(otherModel);
            end
            if ~isempty(otherModelFile)
                if exist(otherModelFile, 'file') == 2
                    delete(otherModelFile);
                end
                otherModelReqs = fullfile(fileparts(otherModelFile), [otherModel '.req']);
                if exist(otherModelReqs, 'file') == 2
                    delete(otherModelReqs);
                end
            end
            % Finally, in case there is "No requirements ..." popup still hanging
            rmiut.closeDlg(getString(message('Slvnv:reqmgt:highlightObjectsWithReqs')));
            
        case 'emlshow'
            if ischar(object)
                if any(object==':') % if SID
                    obj = Simulink.ID.getHandle(object);
                else
                    mdlName = strtok(object, '/');
                    open_system(mdlName);
                    obj = get_param(object, 'Handle');
                end
            else
                obj = get_param(object, 'Handle');
            end
            if isa(obj, 'double')
                eval(rmi.objinfo(obj));
                sfId = sf('Private', 'block2chart', obj);
                sf('Open', sfId);
            else
                sf('Open', obj.Id)
            end
            
        case 'preload'
            linkType = rmi.linktype_mgr('resolveByRegName', object);
            if isempty(linkType)
                error('Document Type %s is not defined', object);
            else
                linkType.SelectionLinkFcn('preload', varargin{1});
            end

        otherwise
            error(message('Slvnv:rmidemo_callback:UnsupportedAction', action));
    end
end

function [hWord, hDoc] = openWordDoc(docPath)
    hWord = rmicom.wordApp();
    hDocs = hWord.Documents;
    % try to reuse if already open
    found = 0;
    for i = 1:hDocs.Count
        thisDoc = hDocs.Item(i);
        if ~isempty(thisDoc)  
            thisName = thisDoc.FullName;
            if strcmpi(thisName, docPath)
                found = i;
                break;
            end
        end
    end
    if ~hWord.visible 
        hWord.visible = 1; 
    end
    if (strcmpi(hDocs.Parent.WindowState, 'wdWindowStateMinimize'))
        hDocs.Parent.WindowState = 'wdWindowStateNormal';
    end
    hWord.Activate;
    if found == 0
        hDoc = hDocs.Open(docPath, [], 0);
    else
        hDoc = hDocs.Item(found);
    end
    hDoc.Activate;
end
              
    
function unhighlight(object)
    model = bdroot;
    try
        if strcmp(get_param(model, 'ReqHilite'),'on')
            restoreColor = 'reqHere';
        else
            restoreColor = 'off';
        end
    catch ME %#ok<NASGU>
        return; % nothing to do if no model is open
    end
    if ~isempty(object)
        if iscell(object)
            for i = 1:length(object)
                try
                    set_param(object{i}, 'hiliteAncestors', restoreColor);
                catch Mex %#ok
                end
            end
        else
            try
                set_param(object, 'hiliteAncestors', restoreColor);
            catch Mex %#ok
            end
        end
    end
end

function locate_sl(object)
    % make sure the model is loaded
    model = strtok(object,'/');
    load_system(model);
    % now open the parent subsyste and label the object using 'find' style
    subsystem = get_param(object, 'Parent');
    open_system(subsystem);
    set_param(object, 'hiliteAncestors', 'find');
end
    
