function varargout = sldemo_mdlref_util(exampleID, action, varargin)
% sldemo_mdlref_util controls the Model Reference demo callbacks

% Copyright 1990-2017 The MathWorks, Inc.
    
    if strcmp(exampleID, 'sldemo_mdlref_conversion')
        handle_sldemo_mdlref_conversion(exampleID, action, varargin{:});
        
    elseif strcmp(exampleID, 'sldemo_mdlref_fcncall')
        output = handle_sldemo_mdlref_fcncall(exampleID, action, varargin{:});
        if ~isempty(output)
            varargout{1} = output;
        end 
    elseif strcmp(exampleID, 'sldemo_mdlref_dsm')
        output = handle_sldemo_mdlref_dsm(exampleID, action, varargin{:});
        if ~isempty(output)
            varargout{1} = output;
        end 
    elseif strcmp(exampleID, 'sldemo_mdlref_bus')
        output = handle_sldemo_mdlref_bus(exampleID, action, varargin{:});
        if ~isempty(output)
            varargout{1} = output;
        end 
    elseif strcmp(exampleID, 'sldemo_mdlref_protect')
        output = handle_sldemo_mdlref_protect(exampleID, action, varargin{:});
        if ~isempty(output)
            varargout{1} = output;
        end 
    elseif strcmp(exampleID, 'sldemo_mdlref_depgraph')
        output = handle_sldemo_mdlref_depgraph(exampleID, action, varargin{:});
        if ~isempty(output)
            varargout{1} = output;
        end
    elseif strcmp(exampleID, 'sldemo_mdlref_logging_intervals')
        output = handle_sldemo_mdlref_logging_intervals(exampleID, action, varargin{:});
        if ~isempty(output)
            varargout{1} = output;
        end
    elseif strcmp(exampleID, 'sldemo_working_with_big_data')
        output = handle_sldemo_working_with_big_data(exampleID, action, varargin{:});
        if ~isempty(output)
            varargout{1} = output;
        end            
    end
end


function output = handle_sldemo_mdlref_depgraph(~, action, varargin)
    output = [];
    switch(action)
      case('cleanup')
        clear mex; %#ok<CLMEX>
        
        startdir = varargin{1};
        tempDir  = varargin{2};
        
        cd(startdir);
        rmpath(startdir);
        rmdir(tempDir, 's');
    end 
end


function output = handle_sldemo_mdlref_protect(~, action, varargin)
    output = [];
    switch(action)
      case('cleanup')
        startdir = varargin{1};
        tempDir  = varargin{2};
        
        cd(startdir);
        rmpath(startdir);
        rmdir(tempDir, 's');
    end
end


function output = handle_sldemo_mdlref_dsm(modelName, action, varargin)
    output = [];
    switch(action)
        % setup for demo
      case {'setup'} 

        output = pwd;
        newdir = tempname;
        mkdir(newdir);
        cd(newdir);
        
      case{'sim'} 
        
        if (isempty(find_system('Name',modelName)))
            open_system(modelName); 
        end
        evalc('sim(modelName)');
        assignin('base','dsmout',dsmout);
        
        plot(tout, yout);
        title('Simulation of model hierarchy sharing data store ErrorCond');
        ylabel('Input to model block A, and output of Switch');
        xlabel('Time (sec)');        
        
      case{'close'} 
        
        evalin('base','bdclose sldemo_mdlref_dsm');
        evalin('base','bdclose sldemo_mdlref_dsm_bot;');
        evalin('base','bdclose sldemo_mdlref_dsm_bot2;');
        evalin('base','clear tout yout ErrorCond dsmout');
        clear sldemo_mdlref_dsm_bot_msf;
        clear sldemo_mdlref_dsm_bot2_msf;
        newdir = pwd;
        origdir = varargin{1};
        cd(origdir);
        rmdir(newdir,'s'); 
      otherwise
    end
end


function output = handle_sldemo_mdlref_bus(modelName, action, varargin)
    output = [];
    switch(action)
        % setup for demo
      case {'setup'} 

        % Workaround for g1589675 - opening some models locks the temp directory
        output = struct();

        output.origDir = pwd;
        output.newDir = tempname;

        mkdir(output.newDir);
        addpath(output.origDir);
        
      case{'sim'} 
        
        if (isempty(find_system('Name',modelName)))
            open_system(modelName); 
        end
        evalc('sim(modelName)');
        assignin('base','topOut',topOut);       
        
      case{'close'} 
        
        evalin('base','bdclose sldemo_mdlref_bus;');
        evalin('base','bdclose sldemo_mdlref_counter_bus;');
        evalin('base','clear topOut subOut yout COUNTERBUS LIMITBUS;');
        newdir = pwd;
        origdir = varargin{1};
        rmpath(origdir);
        cd(origdir);
        rmdir(newdir,'s'); 
      otherwise
    end
end


function output = handle_sldemo_mdlref_fcncall(modelName, action, varargin)
    output = [];
    switch(action)
      case {'setup'} 
        output = pwd;
        newdir = tempname;
        mkdir(newdir);
        cd(newdir);
        
      case{'sim'} 
        if (isempty(find_system('Name', modelName)))
            open_system(modelName); 
        end
        cmd = ['sim(''', modelName, ''')']; 
        evalc(cmd);
        
      case{'close'} 
        newdir = pwd;
        origdir = varargin{1};
        close_system(modelName, 0);
        close_system([modelName,'_cntr'], 0);
        clear sldemo_mdlref_fcncall_cntr_msf;
        clear sldemo_mdlref_fcncall_sfun;
        if ~isempty(origdir)
            cd(origdir);
            rmdir(newdir,'s'); 
        end
    end
end

function handle_sldemo_mdlref_conversion(modelName, action, varargin)
    mdlRef = 'sldemo_bus_counter';
    if strcmp(action, 'convert')
        
        % Convert the model
        open_system(modelName);
        
        ssBlk = find_system(modelName, ...
                            'SearchDepth',1,...
                            'BlockType','SubSystem', ...
                            'Name', 'Bus Counter');
        
        if isempty(ssBlk)                   % Fix for g272298
            list = find_mdlrefs(modelName);
            dp = DAStudio.DialogProvider;
            if any(strcmp(list, mdlRef)) 
                msg = DAStudio.message('simdemos:sldemo_mdlref_util:modelRefHasBeenCreated', ...
                                       'Bus Counter', modelName);
                dp.msgbox(msg, 'Info', true);
            else            
                msg = DAStudio.message('simdemos:sldemo_mdlref_util:noSubsystem', ...
                                       'Bus Counter', modelName);            
                dp.errordlg(msg, 'Error', true);
            end        
        else
            clean_mdlref_conversion_l(modelName, mdlRef);
            
            %% make sure the model name is unique. Otherwise, the conversion
            %% tool will report an error
            
            thisModel = 'sldemo_bus_counter';
            idx = 0;
            newModel = thisModel;
            while exist(newModel) || exist([newModel,'_bus']) %#ok
                idx = idx + 1;
                intPostFix = sprintf('%d',idx);
                newModel = [thisModel, intPostFix];
            end
            if ~strcmp(thisModel, newModel)
                DAStudio.warning('simdemos:sldemo_mdlref_util:existingModelRef',...
                                 thisModel, newModel);
            end
            thisModel = newModel;
            
            % This may throw an error message
            Simulink.SubSystem.convertToModelReference('sldemo_mdlref_conversion/Bus Counter', thisModel, ...
                                                       'ReplaceSubsystem', true, varargin{:}); 
            close_system(thisModel);
        end
    elseif strcmp(action,'exit')
        if bdIsLoaded('sldemo_mdlref_conversion')
            close_system('sldemo_mdlref_conversion', 0);
        end
        
        clean_mdlref_conversion_l(modelName, mdlRef)
    end
end

function output = handle_sldemo_mdlref_logging_intervals(~, action, varargin)
    output = [];
    modelName = 'sldemo_mdlref_bus';
    switch(action)
      case('openConfigDialog')
        open_system(modelName);
        set_param(modelName,'ReturnWorkspaceOutputs','on');
        set_param(modelName, 'LoggingIntervals','[9,10.5; 14.5,30]');
        configset.highlightParameter(modelName,'LoggingIntervals');
      case('sim')
        open_system(modelName);
        open_system([modelName '/Scope']);
        set_param(modelName,'ReturnWorkspaceOutputs','on');
        set_param(modelName, 'LoggingIntervals','[9,10.5; 14.5,30]');
        out=sim(modelName);     
        assignin('base','out',out);       

        fig = findobj('type','figure','name', ...
            'sldemo_mdlref_logging_intervals_figure');
        if isempty(fig)
             fig = figure('Name', 'sldemo_mdlref_logging_intervals_figure');
        end
        set(0,'currentFigure',fig);
        stem(out.get('topOut').get('OUTERDATA').Values.Time, ...
             out.get('topOut').get('OUTERDATA').Values.Data, ':.', 'MarkerSize',10);
        axis tight;
        grid on;
        xlabel('Simulation Time');
        ylabel('OUTERDATA');
        xlim([0 34]);
        ylim([0 44]);
    
      case('close')
        fig = findobj('type','figure','name', ...
            'sldemo_mdlref_logging_intervals_figure');
        if ~isempty(fig)
            close(fig);
        end
        bdclose({'sldemo_mdlref_bus','sldemo_mdlref_counter_bus'});
        evalin('base','clear COUNTERBUS LIMITBUS INCREMENTBUS out;');
    end
end

function output = handle_sldemo_working_with_big_data(~, action, varargin)
    output = [];
    modelName = 'sldemo_mdlref_bus';
    switch(action)
      case('openConfigDialog')
        open_system(modelName);
        configset.highlightParameter(modelName,'LoggingToFile');
      case('close')        
        bdclose({'sldemo_mdlref_bus','sldemo_mdlref_counter_bus'});
        evalin('base','clear COUNTERBUS LIMITBUS INCREMENTBUS out;');
    end
end

% This function closes the models and clear workspace variables 
% added for sldemo_mdlref_conversion demo.
function clean_mdlref_conversion_l(modelName, mdlRef)
    closeModel(mdlRef);

    % Delete generated files
    deleteFile([mdlRef, '.*']);
    deleteFile([modelName,'_conversion_data.mat']);
    
    % Clean up workspace
    clearVariables;
end


function closeModel(modelReference)
    if bdIsLoaded(modelReference)
        close_system(modelReference, 0);
    end
end


function deleteFile(fileName)
    list = dir(fileName);
    numberOfFiles = length(list);
    for fileIdx = 1:numberOfFiles
        delete(list(fileIdx).name);
    end
end


function clearVariables()
    evalin('base','clear COUNTERBUS COUNTERBUSOUT LIMITBUS');
end
