function runPauseResumeButtonPushed(obj, event)
%RUNPAUSERESUMEBUTTONPUSHED Callback for the button pushed event of the
%simulation start/pause/resume button.
%   This callback is responsible for running/pausing/continuing a
%   simulation. Based on the status of the simulation, states of multiple
%   app components are updated. Panes are also expanded/collapsed as
%   needed.

%   Copyright 2021-2024 The MathWorks, Inc.

    app = obj.App;
    disableMenusForActiveSimulation = @()setSimulationInactiveControls(obj,'off');

    if slsim.SimulationStatus(app.Simulation.Status) == slsim.SimulationStatus.Inactive
      obj.createSimInp();
      obj.createSimulation();
    end
    
    try
        switch (slsim.SimulationStatus(app.Simulation.Status))
          case slsim.SimulationStatus.Inactive
            % Play button pressed => issue sim command
            assert(isequal(event.Source.Icon,fullfile(app.AssetsFolder, 'images', 'icon_run.png')));
            
            caughtError = [];

            try
                app.SimStatusListener = listener(app.Simulation, 'SimulationStatusChanged', ...
                  @(~,evt) handleSimStatusChanged(obj, evt.NewStatus));

                obj.hidePlotContent();
                % 1. disable UI control, update label
                obj.setUIControlState('off');
                % disable Save/Load menus as simulation is going to be active
                disableMenusForActiveSimulation();
                app.StatusLabel.Text = message("simulinkcompiler:genapp:StartingStatusLabel").getString;
                app.RunPauseResumeButton.Icon = fullfile(app.AssetsFolder, 'images', 'icon_pause.png');
                drawnow limitrate;
                % 2. start simulation and the timer
                obj.debugTrace('Before sim');
                % 3. start simulation
                start(app.Simulation);
                if slsim.SimulationStatus(app.Simulation.Status) == slsim.SimulationStatus.Running
                  app.StatusLabel.Text = message("simulinkcompiler:genapp:RunningStatusLabel").getString;
                end
                drawnow limitrate;
                start(app.refreshTimer);
            catch caughtError
            end

            if ~isempty(caughtError)
                if ~isempty(caughtError.cause), caughtError = caughtError.cause{1}; end
                if isa(caughtError, 'matlab.internal.validation.RuntimeArgumentException')
                    msg = regexprep(caughtError.getReport, '<.*?>', '');
                else
                    msg = caughtError.getReport('extended', 'hyperlinks', 'off');
                end
                % show the uialert
                uialert(app.GUI, msg,'Error');
                app.StatusLabel.Text = message("simulinkcompiler:genapp:ErrorSimulatingStatusLabel").getString;
            end
          case slsim.SimulationStatus.Running
            % Pause button pressed => issue pause command
            assert(isequal(event.Source.Icon,fullfile(app.AssetsFolder, 'images', 'icon_pause.png')));
            stop(app.refreshTimer);

            obj.setUIControlState('off');
            disableMenusForActiveSimulation();

            app.StatusLabel.Text = message("simulinkcompiler:genapp:PausingStatusLabel").getString;
            app.RunPauseResumeButton.Icon = fullfile(app.AssetsFolder, 'images', 'icon_resume.png');
            drawnow limitrate;
            try
                obj.debugTrace('Before pausing');
                pause(app.Simulation);
                app.StatusLabel.Text = message("simulinkcompiler:genapp:PausedStatusLabel").getString;
                % get the simulation output and update plots
                obj.debugTrace('Paused, getting simout');
                app.modelData.simOut = app.Simulation.SimulationOutput;
                % process the simulation results
                obj.processSimOut();
                % update plots
                obj.updateSigsAndAxesGL();
                % Make sure the bottom panels are visible
                obj.showPanels(["signals", "plots"]);

                obj.setUIControlState('on');
                % Keep the save/load/reset menus for Session as well as Parameters and Inputs disabled
                % as the simulation is still "active". 
                disableMenusForActiveSimulation();

                drawnow limitrate;
            catch
                % NOOP - this is for the edge case where, by the time the
                % call is made to pauseSimulation, the simulation has
                % already stopped.
            end

          case slsim.SimulationStatus.Paused
            % Resume button pressed
            assert(isequal(event.Source.Icon,fullfile(app.AssetsFolder, 'images', 'icon_resume.png')));

            % First apply any pending parameter changes
            if ~isempty(app.modelData.modifiedTunableVariables)
                slVars = obj.tv2slsv(app.modelData.modifiedTunableVariables);
                for slVar = slVars
                  setVariable(app.Simulation, slVar.Name, slVar.Value, "Workspace", slVar.Workspace);
                end
                obj.debugTrace(['Modified ', ....
                                num2str(numel(app.modelData.modifiedTunableVariables)), ....
                                ' parameters']);
                app.modelData.modifiedTunableVariables = []; % reset
            end

            % and then issue resume command
            app.StatusLabel.Text = message("simulinkcompiler:genapp:ResumingStatusLabel").getString;
            app.RunPauseResumeButton.Icon = fullfile(app.AssetsFolder, 'images', 'icon_pause.png');

            obj.setUIControlState('off');
            disableMenusForActiveSimulation();

            drawnow limitrate;
            start(app.refreshTimer);
            resume(app.Simulation);
            obj.debugTrace('Resumed sim');
            
          case slsim.SimulationStatus.Terminating
            % Clicked pause when simulation was terminating
            app.RunPauseResumeButton.Enable = 'off';
          otherwise
            assert(false, 'Invalid simulation status');
        end

    catch ME
        msg = ME.getReport('extended', 'hyperlinks', 'off');
        uialert(app.GUI, msg, 'Error');
    end

end

function handleSimStatusChanged(appHelper, newStatus)
  if ~isequal(newStatus, slsim.SimulationStatus.Inactive)
    return
  end
  appHelper.handleSimulationCompleted();
end

% LocalWords:  uialert NOOP
