/**
 * Utility to register plugins and common namespace for keeping the reference to all plugins classes.
 */ "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 getPlugin () {
        return getPlugin;
    },
    get getPluginsNames () {
        return getPluginsNames;
    },
    get hasPlugin () {
        return hasPlugin;
    },
    get registerPlugin () {
        return registerPlugin;
    }
});
const _string = require("../helpers/string");
const _errors = require("../helpers/errors");
const _priorityMap = require("../utils/dataStructures/priorityMap");
const _uniqueMap = require("../utils/dataStructures/uniqueMap");
const _uniqueSet = require("../utils/dataStructures/uniqueSet");
const ERROR_PLUGIN_REGISTERED = (pluginName)=>`There is already registered "${pluginName}" plugin.`;
const ERROR_PRIORITY_REGISTERED = (priority)=>`There is already registered plugin on priority "${priority}".`;
const ERROR_PRIORITY_NAN = (priority)=>`The priority "${priority}" is not a number.`;
/**
 * Stores plugins' names' queue with their priorities.
 */ const priorityPluginsQueue = (0, _priorityMap.createPriorityMap)({
    errorPriorityExists: ERROR_PRIORITY_REGISTERED,
    errorPriorityNaN: ERROR_PRIORITY_NAN
});
/**
 * Stores plugins names' queue by registration order.
 */ const uniquePluginsQueue = (0, _uniqueSet.createUniqueSet)({
    errorItemExists: ERROR_PLUGIN_REGISTERED
});
/**
 * Stores plugins references between their name and class.
 */ const uniquePluginsList = (0, _uniqueMap.createUniqueMap)({
    errorIdExists: ERROR_PLUGIN_REGISTERED
});
function getPluginsNames() {
    return [
        ...priorityPluginsQueue.getItems(),
        ...uniquePluginsQueue.getItems()
    ];
}
function getPlugin(pluginName) {
    const unifiedPluginName = (0, _string.toUpperCaseFirst)(pluginName);
    return uniquePluginsList.getItem(unifiedPluginName);
}
function hasPlugin(pluginName) {
    /* eslint-disable no-unneeded-ternary */ return getPlugin(pluginName) ? true : false;
}
function registerPlugin(pluginName, pluginClass, priority) {
    [pluginName, pluginClass, priority] = unifyPluginArguments(pluginName, pluginClass, priority);
    if (getPlugin(pluginName) === undefined) {
        _registerPlugin(pluginName, pluginClass, priority);
    }
}
/**
 * Registers plugin under the given name.
 *
 * @param {string|Function} pluginName The plugin name or plugin class.
 * @param {Function} [pluginClass] The plugin class.
 * @param {number} [priority] The plugin priority.
 */ function _registerPlugin(pluginName, pluginClass, priority) {
    const unifiedPluginName = (0, _string.toUpperCaseFirst)(pluginName);
    if (uniquePluginsList.hasItem(unifiedPluginName)) {
        (0, _errors.throwWithCause)(ERROR_PLUGIN_REGISTERED(unifiedPluginName));
    }
    if (priority === undefined) {
        uniquePluginsQueue.addItem(unifiedPluginName);
    } else {
        priorityPluginsQueue.addItem(priority, unifiedPluginName);
    }
    uniquePluginsList.addItem(unifiedPluginName, pluginClass);
}
/**
 * Unifies arguments to register the plugin.
 *
 * @param {string|Function} pluginName The plugin name or plugin class.
 * @param {Function} [pluginClass] The plugin class.
 * @param {number} [priority] The plugin priority.
 * @returns {Array}
 */ function unifyPluginArguments(pluginName, pluginClass, priority) {
    if (typeof pluginName === 'function') {
        pluginClass = pluginName;
        pluginName = pluginClass.PLUGIN_KEY;
        priority = pluginClass.PLUGIN_PRIORITY;
    }
    return [
        pluginName,
        pluginClass,
        priority
    ];
}
