"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (g && (g = 0, op[0] && (_ = 0)), _) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.initDrawEngineSingleChart = exports.createSingleInternal = void 0;
// @ts-ignore
var WasmModule2D = require("../../_wasm/scichart2d");
var BuildStamp_1 = require("../../Core/BuildStamp");
var Guard_1 = require("../../Core/Guard");
var logger_1 = require("../../utils/logger");
var licenseManager2D_1 = require("./licenseManager2D");
var SciChartDefaults_1 = require("./SciChartDefaults");
var sciChartInitCommon_1 = require("./sciChartInitCommon");
var SciChartSurface_1 = require("./SciChartSurface");
var SciChartSurfaceBase_1 = require("./SciChartSurfaceBase");
var NativeObject_1 = require("./Helpers/NativeObject");
var DeletableEntity_1 = require("../../Core/DeletableEntity");
var Globals_1 = require("../../Core/Globals");
var LabelCache_1 = require("./Axis/LabelProvider/LabelCache");
var createMaster_1 = require("./createMaster");
var performance_1 = require("../../utils/performance");
var preRun_1 = require("./preRun");
var WebGpuHelper_1 = require("../../Core/WebGpuHelper");
var app_1 = require("../../constants/app");
// Global variables
/** @ignore */
var createSingleInternal = function (divElement, surfaceConstructor, options) { return __awaiter(void 0, void 0, void 0, function () {
    var canvases, loader, loaderDiv, mark, locateFile, preinitializedWebGPUDevice, moduleOptions;
    var _a, _b, _c;
    return __generator(this, function (_d) {
        switch (_d.label) {
            case 0:
                if (!app_1.IS_WEB_GPU) return [3 /*break*/, 2];
                return [4 /*yield*/, WebGpuHelper_1.WebGpuHelper.initializeWebGPUDevice()];
            case 1:
                _d.sent();
                _d.label = 2;
            case 2:
                canvases = sciChartInitCommon_1.default.initCanvas(divElement, options === null || options === void 0 ? void 0 : options.widthAspect, options === null || options === void 0 ? void 0 : options.heightAspect, undefined, (_a = options === null || options === void 0 ? void 0 : options.disableAspect) !== null && _a !== void 0 ? _a : SciChartDefaults_1.SciChartDefaults.disableAspect, options === null || options === void 0 ? void 0 : options.touchAction);
                loader = ((_b = options === null || options === void 0 ? void 0 : options.loader) !== null && _b !== void 0 ? _b : SciChartDefaults_1.SciChartDefaults.defaultLoader);
                loaderDiv = (_c = loader.addChartLoader) === null || _c === void 0 ? void 0 : _c.call(loader, canvases.domDivContainer, options === null || options === void 0 ? void 0 : options.theme);
                mark = performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.EngineInitStart, {
                    parentContextId: canvases.domCanvas2D.id
                });
                locateFile = (0, SciChartSurfaceBase_1.getLocateFile)(SciChartSurface_1.sciChartConfig);
                if (!WebGpuHelper_1.WebGpuHelper.getWebGpuSupported()) return [3 /*break*/, 4];
                return [4 /*yield*/, WebGpuHelper_1.WebGpuHelper.initializeWebGPUDevice()];
            case 3:
                preinitializedWebGPUDevice = _d.sent();
                _d.label = 4;
            case 4:
                moduleOptions = {
                    locateFile: locateFile,
                    noInitialRun: true,
                    canvas: canvases.domCanvasWebGL,
                    preRun: preRun_1.preRun
                };
                if (preinitializedWebGPUDevice) {
                    moduleOptions.preinitializedWebGPUDevice = preinitializedWebGPUDevice;
                }
                return [2 /*return*/, new Promise(function (resolve, reject) {
                        // @ts-ignore
                        new WasmModule2D(moduleOptions)
                            .then(function (wasmContext) {
                            var _a, _b;
                            (_a = loader.removeChartLoader) === null || _a === void 0 ? void 0 : _a.call(loader, canvases.domDivContainer, loaderDiv);
                            // @ts-ignore
                            wasmContext.doNotCaptureKeyboard = true;
                            licenseManager2D_1.licenseManager.applyLicense(wasmContext, "2D single");
                            // TODO replace workaround with proper wasmContext references cleanup
                            // TODO use revocable only for memory debug
                            // if (process.env.NODE_ENV !== "production") {
                            var revocable = (0, DeletableEntity_1.createWasmContextRevocableProxy)(wasmContext, canvases.domCanvas2D.id);
                            var customResolve = function (res) {
                                var _a;
                                if ((_a = options === null || options === void 0 ? void 0 : options.createSuspended) !== null && _a !== void 0 ? _a : SciChartDefaults_1.SciChartDefaults.createSuspended) {
                                    // // @ts-ignore
                                    // sciChartSurface.createSuspended = true;
                                    res.sciChartSurface.suspendUpdates();
                                }
                                res.sciChartSurface.addDeletable({
                                    delete: function () {
                                        revocable.revoke();
                                        revocable = undefined;
                                    }
                                });
                                performance_1.PerformanceDebugHelper.mark(performance_1.EPerformanceMarkType.EngineInitEnd, {
                                    relatedId: mark === null || mark === void 0 ? void 0 : mark.detail.relatedId,
                                    contextId: res.sciChartSurface.id,
                                    parentContextId: canvases.domCanvas2D.id
                                });
                                resolve(res);
                            };
                            (0, exports.initDrawEngineSingleChart)(revocable.proxy, canvases, customResolve, options === null || options === void 0 ? void 0 : options.theme, surfaceConstructor);
                            // return;
                            // }
                            //Flag which ensures Typescript side drives emscripten rendering (one render per draw request)
                            // @ts-ignore
                            wasmContext.TSRSetDrawRequestsEnabled((_b = !(options === null || options === void 0 ? void 0 : options.disableEngineLoop)) !== null && _b !== void 0 ? _b : true);
                            // initDrawEngineSingleChart(wasmContext, canvases, resolve, options?.theme as IThemeProvider);
                            (0, BuildStamp_1.checkBuildStamp)(wasmContext);
                            (0, createMaster_1.monitorWebGL)(wasmContext, false);
                        })
                            .catch(function (err) {
                            var _a;
                            logger_1.Logger.debug(err);
                            (_a = loader.removeChartLoader) === null || _a === void 0 ? void 0 : _a.call(loader, canvases.domDivContainer, loaderDiv);
                            reject("Could not load SciChart WebAssembly module.\n                Check your build process and ensure that your \"scichart2d.wasm\" and \"scichart2d.js\" files are from the same version");
                        });
                    })];
        }
    });
}); };
exports.createSingleInternal = createSingleInternal;
/** @ignore */
var initDrawEngineSingleChart = function (wasmContext, canvases, resolve, theme, surfaceConstructor) {
    Guard_1.Guard.notNull(theme, "theme");
    var width = canvases.domCanvas2D.width;
    var height = canvases.domCanvas2D.height;
    // Not sure why this was needed but it currently breaks as preRun is undefined
    // @ts-ignore
    //wasmContext.preRun.push(() => (ENV.SDL_EMSCRIPTEN_KEYBOARD_ELEMENT = "#chart_WebGL"));
    var scs;
    wasmContext.canvas = canvases.domCanvasWebGL;
    var frameRenderer2D = new wasmContext.SCRTFrameRenderer2D();
    var webGlCanvasId = canvases.domCanvasWebGL.id;
    var chartInitializer = {
        InitializeChart: function () {
            scs = surfaceConstructor(wasmContext, { canvases: canvases });
            scs.applyTheme(theme);
            Globals_1.sciChartSingleDestinations.push({
                canvasElementId: webGlCanvasId,
                sciChartSurface: scs,
                width: width,
                height: height
            });
            scs.setDestinations(Globals_1.sciChartSingleDestinations);
            scs.addDeletable({
                delete: function () {
                    // Fixes bug in WebGL createSingle mode when switching to another example
                    // Halt the engine. In WebGL mode TSRRequestExit's internal C++ teardown
                    // can crash inside _glDeleteBuffers; swallow so the explicit cleanup below
                    // (which performs the actual resource release) still runs.
                    try {
                        wasmContext.TSRRequestExit();
                    }
                    catch (e) {
                        console.warn("TSRRequestExit failed during chart delete (continuing):", e);
                    }
                    frameRenderer2D.delete();
                    wasmContext.SCRTGetGlobalRenderLoopManager().SetFrameRenderer(null);
                    wasmContext.SCRTGetGlobalRenderLoopManager().delete();
                    wasmContext.SCRTSetGlobalRenderLoopManager(null);
                    LabelCache_1.labelCache.resetCache();
                }
            });
            setTimeout(function () {
                scs.invalidateElement();
                licenseManager2D_1.licenseManager.updateLicenseDisplay(scs);
                var unsub = sciChartInitCommon_1.default.subscribeToResize(canvases.domChartRoot, canvases.aspect, scs, canvases.disableAspect);
                scs.addDeletable(unsub);
                scs.addDeletable((0, NativeObject_1.freeCache)(wasmContext));
                scs.setIsInitialized();
                resolve({ wasmContext: wasmContext, sciChartSurface: scs });
            }, 0);
        },
        Draw: function (canvasId) {
            scs.renderSurface.onRenderTimeElapsed();
        },
        Update: function (deltaTime) {
            // Logger.debug("sciChartInitCommon.ts Update");
        },
        ShutDownChart: function () {
            // Logger.debug("sciChartInitCommon.ts ShutDownChart");
        }
    };
    var chartInitObj = wasmContext.SCRTRenderLoopManager.implement(chartInitializer);
    chartInitObj.SetFrameRenderer(frameRenderer2D);
    chartInitObj.SetFPSCounterEnabled(false);
    chartInitObj.SetImmediateBufferSizeKb(SciChartDefaults_1.SciChartDefaults.wasmBufferSizesKb);
    wasmContext.SCRTSetGlobalRenderLoopManager(chartInitObj);
    // @ts-ignore
    wasmContext.callMain();
};
exports.initDrawEngineSingleChart = initDrawEngineSingleChart;
