/**
 * Hook system to modify simple things.
 *
 * @module util/hooks
 * @see Events for hook events
 * @example <caption>Accessing the hook system</caption>
 * window.rml.hooks.register("yourAction", function() {
 *  // Do something
 * });
 */
import $ from "jquery";

const registry = {};
const hooks = {
    /**
     * Registers a callback to a given event name.
     *
     * @param {string} names The event name, you can also pass multiple names when splitted with " "
     * @param {function} callback The callback function with the arguments
     * @returns {module:util/hooks}
     * @function register
     */
    register(names, callback) {
        names.split(" ").forEach((name) => {
            registry[name] = registry[name] || [];
            registry[name].push(callback);
        });
        return hooks;
    },

    /**
     * Deregister a callback to a given event name.
     *
     * @param {string} name The event name
     * @param {function} callback The callback function with the arguments
     * @returns {module:util/hooks}
     * @function register
     */
    deregister(name, callback) {
        let i;
        if (registry[name]) {
            registry[name].forEach((fns) => {
                i = fns.indexOf(callback);
                i > -1 && fns.splice(i, 1);
            });
        }
        return hooks;
    },

    /**
     * Call an event.
     *
     * @param {string} name The event name
     * @param {mixed[]} args Pass arguments to the callbacks
     * @param {object} context Pass context to the callbacks
     * @returns {module:util/hooks}
     * @function call
     */
    call(name, args, context) {
        if (registry[name]) {
            if (args) {
                if (Object.prototype.toString.call(args) === "[object Array]") {
                    args.push($);
                } else {
                    args = [args, $];
                }
            } else {
                args = [$];
            }

            // When explicit false then break the for
            registry[name].forEach((callback) => callback.apply(context, args) !== false);
        }
        return hooks;
    },

    /**
     * Checks if a event name is registered.
     *
     * @param {string} name The event name
     * @returns {boolean}
     * @function exists
     */
    exists(name) {
        return !!registry[name];
    },
};

export default hooks;
