"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CustomCallback = void 0;
const sort_1 = require("../../functions/sort");
const Feature_1 = require("./Feature");
/**
 * The base class for a custom callback. Individual custom callbacks (and validation callbacks) will
 * extend from this class.
 */
class CustomCallback extends Feature_1.Feature {
    subscriptions = [];
    addSubscriber(priority, callbackFunc, ...optionalArgs) {
        const subscription = {
            priority,
            callbackFunc,
            optionalArgs,
        };
        this.subscriptions.push(subscription);
        // Sort the subscriptions by priority so that the callbacks with the lowest priority are first.
        // By default, the `Array.sort` method is transpiled to using Lua's sort, which is not stable.
        // We need to do a stable sort so that we preserve the subscription order.
        this.subscriptions = (0, sort_1.stableSort)(this.subscriptions, (0, sort_1.sortObjectArrayByKey)("priority"));
    }
    /**
     * If the submitted function does not match any of the existing subscriptions, this method will do
     * nothing.
     */
    removeSubscriber(callback) {
        const subscriptionIndexMatchingCallback = this.subscriptions.findIndex((subscription) => {
            const subscriptionCallback = subscription.callbackFunc;
            return callback === subscriptionCallback;
        });
        if (subscriptionIndexMatchingCallback !== -1) {
            this.subscriptions.splice(subscriptionIndexMatchingCallback, 1);
        }
    }
    fire = (...fireArgs) => {
        for (const subscription of this.subscriptions) {
            const { callbackFunc, optionalArgs } = subscription;
            if (this.shouldFire(fireArgs, optionalArgs)) {
                // - TypeScript is not smart enough to know that the arguments match the function, so we
                //   must cast it to `AnyFunction`.
                // - We cannot use `...fireArgs` here because it would fail to pass any arguments that exist
                //   beyond `nil` elements.
                const value = callbackFunc(fireArgs[0], fireArgs[1], fireArgs[2], fireArgs[3], fireArgs[4], fireArgs[5], fireArgs[6]);
                if (value !== undefined) {
                    return value;
                }
            }
        }
        return undefined;
    };
    /**
     * This method needs to be overwritten for any callback that has optional filtration arguments.
     * See "shouldFire.ts" for methods tailored to specific kinds of callbacks.
     */
    shouldFire = () => true;
}
exports.CustomCallback = CustomCallback;
