%   Copyright 2023 The MathWorks, Inc.

classdef (Hidden = true) perfettoViewer

    methods (Access = ?performance.instrumentation, Static)
        
        function viewTraceEvents(filepath)
            json_url = performance.perfettoViewer.createJsonURL(filepath);
        
            [width, height, left, top] = performance.perfettoViewer.calculateScreenBounds();

            html = performance.perfettoViewer.generateHTML(json_url, width, height, left, top);

            html_filename = performance.perfettoViewer.writeHtmlToFile(html);
        
            performance.perfettoViewer.openWebWindow(html_filename);
        end

    end


    methods (Access = private, Static)

        function json_url = createJsonURL(filepath)
            fileInfo = dir(filepath);
            % add the folder that contains the provided file to the connector's webserver host
            contentUrlPath = connector.addStaticContentOnPath('jsonLoc', fileInfo.folder);
            json_url = connector.getUrl([contentUrlPath '/' fileInfo.name]);
        end

        function [width, height, left, top] = calculateScreenBounds()
            graphicsRootObj = groot();
            screenSize = graphicsRootObj.ScreenSize;
            width = int32(6/8 * screenSize(3));
            height = int32(6/8 * screenSize(4));
            left = int32(1/8 * screenSize(3));
            top = int32(1/8 * screenSize(4));
        end

        function html_filename = writeHtmlToFile(html)
            ts = datestr(now,'yyyy_mm_dd_HH_MM_SS');
            html_filename = ['index_',  ts , '.html'];
            destinationDir = fullfile(tempdir(), html_filename);
            html_fid = fopen( destinationDir, 'w' );
            fprintf( html_fid, '%s', html );
            fclose( html_fid );
        end

        function openWebWindow(html_filename)
            % add tempdir (where the html file was written) to the connector's webserver host
            contentUrlPath = connector.addStaticContentOnPath('htmlLoc', tempdir());
            html_url = connector.getUrl([contentUrlPath, '/', html_filename]);
        
            window = matlab.internal.webwindow(html_url);
            window.show();
            window.hide();
        end

        function html = generateHTML(json_url, width, height, left, top)
            % create an html file using deep linking to view the event results in perfetto
            html = [ ...
            '<!DOCTYPE html> ' newline ...
            '<html lang="en"> ' newline ...
            '<head> ' newline ...
            '    <title>Perfetto UI</title> ' newline ...
            '    <meta charset="utf-8"> ' newline ...
            '    <script> ' newline ...
            '        const ORIGIN = "https://ui.perfetto.dev"; ' newline ...
            '        const TARGET_URL = "' json_url '"; ' newline ...
            '        async function fetchAndOpen(traceUrl) { ' newline ...
            '            const resp = await fetch(traceUrl); ' newline ...
            '            const blob = await resp.blob(); ' newline ...
            '            const arrayBuffer = await blob.arrayBuffer(); ' newline ...
            '            openTrace(arrayBuffer); ' newline ...
            '        } ' newline ...
            '        function openTrace(arrayBuffer) { ' newline ...
            '            const win = window.open(ORIGIN,"Perfetto","resizable=1,left=' num2str(left) ',top=' num2str(top) ',width=' num2str(width) ',height=' num2str(height) '"); ' newline ...
            '            const timer = setInterval(() => win.postMessage("PING", ORIGIN), 50); ' newline ...
            '            const onMessageHandler = (evt) => { ' newline ...
            '                if (evt.data !== "PONG") return; ' newline ...
            '                window.clearInterval(timer); ' newline ...
            '                window.removeEventListener("message", onMessageHandler); ' newline ...
            '                win.postMessage({ ' newline ...
            '                perfetto: { ' newline ...
            '                    buffer: arrayBuffer, ' newline ...
            '                    title: "Performance Instrument", ' newline ...
            '                }}, ORIGIN); ' newline ...
            '                window.close();' newline ...
            '            }; ' newline ...
            '            window.addEventListener("message", onMessageHandler); ' newline ...
            '        } ' newline ...
            '        window.onload = fetchAndOpen(TARGET_URL);' newline ...
            '    </script> ' newline ...
            '</head> ' newline ...
            '<body> ' newline ...
            '</body> ' newline ...
            '</html> ' newline ...
            ];
        end
    end
end

