classdef SimulationHandler < fxptui.Web.CallbackService.CallbackHandler
    % Class to handle simulating the model from FPT.
    
    % Copyright 2017-2019 The MathWorks, Inc.
    
    properties(GetAccess = public, SetAccess = private)
        SimulationInputVariableName = '';
    end
    
    methods
        
        function runName = prepareForIdealizedSimulation(this, runName, simulationInputVariableName)
            % PREPAREFORIDEALIZEDSIMULATION Prepares model for idealized simulated run
            
            % SimulationInputVariableName is the name of the
            % Simulink.SimulationInput object variable the user has specified in
            % the client
            this.SimulationInputVariableName = simulationInputVariableName;
            
            % see if the run already exists
            [~, fptID] = this.DataLayer.getIdFromRunName(this.Converter.TopModel, runName);
            
            % for multiSim only
            if ~isempty(simulationInputVariableName) && ~isempty(fptID)
                facade = this.DataLayer.getWorkflowTopologyFacade(this.Converter.TopModel);
                deriveNode  = facade.query(fptID, 'search', 'exact', 'type', 'Derive');
                if isempty(deriveNode{1})
                    runName = this.Converter.makeRunNameUnique(runName);
                end
            end
            
            % Set Shortcut
            this.setIdealizedSettings(runName);
            
            % In case the given run name is was previously simulated as an embedded
            % run, remove it from the list of embedded runs
            this.DataLayer.removeEmbeddedRunName(this.Converter.TopModel, runName);
            
        end
        
        function [simOut, isMultiSim] = executeSimulation(this, ~)
            % SimulationHandler does not need the client run name because
            % it was already set in setIdealizedSettings
            
            isMultiSim = false;
            
            % if a SimulationInputVariable was provided
            if ~isempty(this.SimulationInputVariableName)
                
                baseWorkspace = Simulink.data.BaseWorkspace;
                % Variables List from base workspace
                allSimulationInputs = baseWorkspace.whos('Simulink.SimulationInput');
                assert(ismember(this.SimulationInputVariableName, allSimulationInputs), ...
                    message('FixedPointTool:fixedPointTool:simulationInputError', this.SimulationInputVariableName));
                
                % evaluate the variable to get the object
                simIn = evalin('base', this.SimulationInputVariableName);
                
                isMultiSim = true;
                
                % used the SimulationInput object for conversion
                simOut = this.Converter.simulateSystem(simIn);
            else
                % use default simulation method
                simOut = this.Converter.simulateSystem();
            end
        end
        
    end
    
end
