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());
    });
};
import { WorldSystem, RendererAPI } from 'dacha';
import * as Events from 'dacha/events';
import { schemaRegistry } from '../../../decorators/schema-registry';
import { classRegistry } from '../../../decorators/class-registry';
import { widgetRegistry } from '../../../hocs/widget-registry';
import { EventType } from '../../../events';
const DEFAULT_AUTO_SAVE_INTERVAL = 10000;
export class ProjectLoader extends WorldSystem {
    constructor(options) {
        var _a;
        super();
        this.handleNeedsUpdate = () => __awaiter(this, void 0, void 0, function* () {
            var _a, _b, _c;
            (_a = this.extensionScript) === null || _a === void 0 ? void 0 : _a.remove();
            this.extensionScript = undefined;
            widgetRegistry.clear();
            schemaRegistry.clear();
            classRegistry.clear();
            yield this.loadScript('./extension.js');
            this.setUpData({
                events: (_b = window.extension) === null || _b === void 0 ? void 0 : _b.default.events,
                locales: (_c = window.extension) === null || _c === void 0 ? void 0 : _c.default.locales,
            });
            this.world.dispatchEvent(EventType.ExtensionUpdated);
        });
        this.world = options.world;
        this.editorConfig = window.electron.getEditorConfig();
        this.world.data.configStore = options.resources.store;
        this.world.data.editorConfig = this.editorConfig;
        this.autoSaveInterval =
            (_a = this.editorConfig.autoSaveInterval) !== null && _a !== void 0 ? _a : DEFAULT_AUTO_SAVE_INTERVAL;
        window.electron.onSave(() => {
            this.saveProjectConfig();
        });
        window.electron.onNeedsUpdate(() => {
            void this.handleNeedsUpdate();
        });
    }
    onWorldLoad() {
        return __awaiter(this, void 0, void 0, function* () {
            var _a, _b;
            if (process.env.NODE_ENV === 'production') {
                yield this.loadScript('./extension.js');
            }
            this.setUpData({
                events: (_a = window.extension) === null || _a === void 0 ? void 0 : _a.default.events,
                locales: (_b = window.extension) === null || _b === void 0 ? void 0 : _b.default.locales,
            });
        });
    }
    loadScript(src) {
        return __awaiter(this, void 0, void 0, function* () {
            return new Promise((resolve) => {
                const script = document.createElement('script');
                script.src = src;
                script.onload = () => resolve();
                script.onerror = () => {
                    console.warn(`Error while loading bundle: ${src}`);
                    resolve();
                };
                document.body.appendChild(script);
                this.extensionScript = script;
            });
        });
    }
    setUpData(extension) {
        var _a;
        const { events = [], locales = {} } = extension;
        this.world.data.extension = {
            events: [...events, ...Object.values(Events)],
            locales,
        };
        const rendererApi = this.world.systemApi.get(RendererAPI);
        rendererApi.reloadShaders((_a = classRegistry.getGroup('behavior.shader')) !== null && _a !== void 0 ? _a : []);
    }
    saveProjectConfig() {
        const projectConfig = this.world.data.configStore.get([]);
        window.electron.saveProjectConfig(projectConfig);
        this.world.dispatchEvent(EventType.SaveProject);
    }
    update(options) {
        var _a;
        if (!this.editorConfig.autoSave) {
            return;
        }
        const { deltaTime } = options;
        this.autoSaveInterval -= deltaTime;
        if (this.autoSaveInterval <= 0) {
            this.saveProjectConfig();
            this.autoSaveInterval =
                (_a = this.editorConfig.autoSaveInterval) !== null && _a !== void 0 ? _a : DEFAULT_AUTO_SAVE_INTERVAL;
        }
    }
}
ProjectLoader.systemName = 'ProjectLoader';
