"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: Object.getOwnPropertyDescriptor(all, name).get
    });
}
_export(exports, {
    get getRegisteredHotInstances () {
        return getRegisteredHotInstances;
    },
    get registerCustomFunctions () {
        return registerCustomFunctions;
    },
    get registerEngine () {
        return registerEngine;
    },
    get registerLanguage () {
        return registerLanguage;
    },
    get registerNamedExpressions () {
        return registerNamedExpressions;
    },
    get setupEngine () {
        return setupEngine;
    },
    get setupSheet () {
        return setupSheet;
    },
    get unregisterEngine () {
        return unregisterEngine;
    }
});
const _staticRegister = require("../../../utils/staticRegister");
const _mixed = require("../../../helpers/mixed");
const _templateLiteralTag = require("../../../helpers/templateLiteralTag");
const _console = require("../../../helpers/console");
const _object = require("../../../helpers/object");
const _formulas = require("../formulas");
const _settings = require("./settings");
/**
 * Prepares and returns the collection for the engine relationship with the HoT instances.
 *
 * @returns {Map}
 */ function getEngineRelationshipRegistry() {
    const registryKey = 'engine_relationship';
    const pluginStaticRegistry = (0, _staticRegister.staticRegister)(_formulas.PLUGIN_KEY);
    if (!pluginStaticRegistry.hasItem(registryKey)) {
        pluginStaticRegistry.register(registryKey, new Map());
    }
    return pluginStaticRegistry.getItem(registryKey);
}
/**
 * Prepares and returns the collection for the engine shared usage.
 *
 * @returns {Map}
 */ function getSharedEngineUsageRegistry() {
    const registryKey = 'shared_engine_usage';
    const pluginStaticRegistry = (0, _staticRegister.staticRegister)(_formulas.PLUGIN_KEY);
    if (!pluginStaticRegistry.hasItem(registryKey)) {
        pluginStaticRegistry.register(registryKey, new Map());
    }
    return pluginStaticRegistry.getItem(registryKey);
}
function setupEngine(hotInstance) {
    const hotSettings = hotInstance.getSettings();
    const pluginSettings = hotSettings[_formulas.PLUGIN_KEY];
    const engineConfigItem = pluginSettings?.engine;
    if (pluginSettings === true) {
        return null;
    }
    if ((0, _mixed.isUndefined)(engineConfigItem)) {
        return null;
    }
    // `engine.hyperformula` or `engine` is the engine class
    if (typeof engineConfigItem.hyperformula === 'function' || typeof engineConfigItem === 'function') {
        return registerEngine(engineConfigItem.hyperformula ?? engineConfigItem, hotSettings, hotInstance);
    // `engine` is the engine instance
    } else if (typeof engineConfigItem === 'object' && (0, _mixed.isUndefined)(engineConfigItem.hyperformula)) {
        const engineRelationship = getEngineRelationshipRegistry();
        const sharedEngineUsage = getSharedEngineUsageRegistry().get(engineConfigItem);
        if (!engineRelationship.has(engineConfigItem)) {
            engineRelationship.set(engineConfigItem, []);
        }
        engineRelationship.get(engineConfigItem).push(hotInstance);
        if (sharedEngineUsage) {
            sharedEngineUsage.push(hotInstance.guid);
        }
        if (!engineConfigItem.getConfig().licenseKey) {
            engineConfigItem.updateConfig({
                licenseKey: _settings.DEFAULT_LICENSE_KEY
            });
        }
        if (engineConfigItem.getConfig().leapYear1900 !== _settings.DEFAULT_SETTINGS.leapYear1900 || (0, _object.isObjectEqual)(engineConfigItem.getConfig().nullDate, _settings.DEFAULT_SETTINGS.nullDate) === false) {
            (0, _console.warn)((0, _templateLiteralTag.toSingleLine)`If you use HyperFormula with Handsontable, keep the default \`leapYear1900\` and \`nullDate\` 
      settings. Otherwise, HyperFormula's dates may not sync correctly with Handsontable's dates.`);
        }
        return engineConfigItem;
    }
    return null;
}
function registerEngine(engineClass, hotSettings, hotInstance) {
    const pluginSettings = hotSettings[_formulas.PLUGIN_KEY];
    const engineSettings = (0, _settings.getEngineSettingsWithDefaultsAndOverrides)(hotSettings);
    const engineRegistry = getEngineRelationshipRegistry();
    const sharedEngineRegistry = getSharedEngineUsageRegistry();
    registerCustomFunctions(engineClass, pluginSettings.functions);
    registerLanguage(engineClass, pluginSettings.language);
    // Create instance
    const engineInstance = engineClass.buildEmpty(engineSettings);
    // Add it to global registry
    engineRegistry.set(engineInstance, [
        hotInstance
    ]);
    sharedEngineRegistry.set(engineInstance, [
        hotInstance.guid
    ]);
    registerNamedExpressions(engineInstance, pluginSettings.namedExpressions);
    // Add hooks needed for cross-referencing sheets
    engineInstance.on('sheetAdded', ()=>{
        engineInstance.rebuildAndRecalculate();
    });
    engineInstance.on('sheetRemoved', ()=>{
        engineInstance.rebuildAndRecalculate();
    });
    return engineInstance;
}
function getRegisteredHotInstances(engine) {
    const engineRegistry = getEngineRelationshipRegistry();
    const hotInstances = engineRegistry.size === 0 ? [] : Array.from(engineRegistry.get(engine) ?? []);
    return new Map(hotInstances.map((hot)=>[
            hot.getPlugin('formulas').sheetId,
            hot
        ]));
}
function unregisterEngine(engine, hotInstance) {
    if (engine) {
        const engineRegistry = getEngineRelationshipRegistry();
        const engineHotRelationship = engineRegistry.get(engine);
        const sharedEngineRegistry = getSharedEngineUsageRegistry();
        const sharedEngineUsage = sharedEngineRegistry.get(engine);
        if (engineHotRelationship && engineHotRelationship.includes(hotInstance)) {
            engineHotRelationship.splice(engineHotRelationship.indexOf(hotInstance), 1);
            if (engineHotRelationship.length === 0) {
                engineRegistry.delete(engine);
            }
        }
        if (sharedEngineUsage && sharedEngineUsage.includes(hotInstance.guid)) {
            sharedEngineUsage.splice(sharedEngineUsage.indexOf(hotInstance.guid), 1);
            if (sharedEngineUsage.length === 0) {
                sharedEngineRegistry.delete(engine);
                engine.destroy();
            }
        }
    }
}
function registerCustomFunctions(engineClass, customFunctions) {
    if (customFunctions) {
        customFunctions.forEach((func)=>{
            const { name, plugin, translations } = func;
            try {
                engineClass.registerFunction(name, plugin, translations);
            } catch (e) {
                (0, _console.warn)(e.message);
            }
        });
    }
}
function registerLanguage(engineClass, languageSetting) {
    if (languageSetting) {
        const { langCode } = languageSetting;
        try {
            engineClass.registerLanguage(langCode, languageSetting);
        } catch (e) {
            (0, _console.warn)(e.message);
        }
    }
}
function registerNamedExpressions(engineInstance, namedExpressions) {
    if (namedExpressions) {
        engineInstance.suspendEvaluation();
        namedExpressions.forEach((namedExp)=>{
            const { name, expression, scope, options } = namedExp;
            try {
                engineInstance.addNamedExpression(name, expression, scope, options);
            } catch (e) {
                (0, _console.warn)(e.message);
            }
        });
        engineInstance.resumeEvaluation();
    }
}
function setupSheet(engineInstance, sheetName) {
    if ((0, _mixed.isUndefined)(sheetName) || !engineInstance.doesSheetExist(sheetName)) {
        sheetName = engineInstance.addSheet(sheetName);
    }
    return sheetName;
}
