%   Copyright 2022-2023 The MathWorks, Inc.


classdef instrumentation

    properties (Access = private, Constant)
        inputs = performance.inputHandler;
    end


    methods (Static, Access = public)

        %% start recording events
        function on()
            performance.instrumentation.versionPrecheck();

            performance.instrument.recorder.clearAllEventData();
            performance.instrument.recorder.start();

            disp("recording events");
        end

        %% stop recording events, do not write to file
        function cancel()
            performance.instrument.recorder.stop();
            performance.instrument.recorder.clearAllEventData();

            disp("recording canceled and previous events cleared");
        end

        %% stop recording events
        function filepath = off(varargin)
            performance.instrumentation.versionPrecheck();

            if ~performance.instrument.recorder.isActive()
                error("no recording in progress");
            end

            [filepath, use_utc, minDuration] = performance.instrumentation.inputs.handleInputs(varargin{:});
            
            performance.instrument.recorder.stop();

            event_traces =  performance.instrumentation.getEventTraces(use_utc, minDuration);
        
            if isempty(event_traces)
                warning('no trace events found, no file will be written');
                performance.instrumentation.inputs.resetFilepath();
                return;
            end

            performance.instrumentation.writeEventTracesToFile(event_traces, filepath);
        
            fprintf("events written to: %s \n", filepath);
        end
        
        %% view event traces
        function filepath = viewer(varargin)
            if verLessThan('matlab', '9.14')
                error("functionality for viewer only supported in R2023a or greater");
            end

            % call off() if recording is in progress
            if performance.instrument.recorder.isActive()
                filepath = performance.instrumentation.off(varargin{:});
            else
                [filepath, ~] = performance.instrumentation.inputs.handleInputs(varargin{:});
            end
    
            fprintf("viewing file: %s\n", filepath);

            performance.perfettoViewer.viewTraceEvents(filepath);
        end

    end


    methods (Static, Access = private)

        function versionPrecheck()
            if verLessThan('matlab', '9.7')
                error("matlab must be R2019b or later. Running release: %s", matlabRelease.Release);
            end
        end

        function event_traces = getEventTraces(use_utc, minDuration)
            if ~verLessThan('matlab', '9.14') % 9.14 = R2023a
                if use_utc
                    event_traces = ...
                        performance.instrument.recorder.getAllCompleteEventsTraceEventJsonWithUTC();
                elseif minDuration.useFilter
                    event_traces = ...
                        performance.instrument.recorder.getAllCompleteEventsTraceEventJsonWithFilter(minDuration.value);
                else
                    event_traces = ...
                        performance.instrument.recorder.getAllCompleteEventsTraceEventJson();
                end
            elseif ~verLessThan('matlab', '9.8')  % 9.8 = R2020a
                if isempty(gcs)
                    error("no model open, this will result in unexpected behavior")
                end
                event_traces = performance.instrument.recorder.getAllEventsTraceEventJson();
            elseif ~verLessThan('matlab', '9.7') % 9.7 = R2019b
                event_traces = performance.instrument.recorder.getAllEvents();
            end
        end

        function writeEventTracesToFile(event_traces, filepath)
            [ event_traces_fid, error_msg ] = fopen( filepath, 'w' );
            if event_traces_fid == -1
                error( 'Failed to open file for writing ''%s'': %s', filepath, error_msg );
            end
        
            if verLessThan('matlab', '9.14') % 9.14 = R2023a
                fprintf( event_traces_fid, '%s', jsonencode(event_traces) );
            else
                fprintf( event_traces_fid, '%s', event_traces );
            end
            fclose( event_traces_fid );
        end
    end
end