"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("../utils");
class SubmitHookService {
    constructor(onSubmitHooksChange) {
        this.submitHooks = [];
        this.onSubmitHooksChange = onSubmitHooksChange;
    }
    send(submitHooks, callback) {
        this.submitHooks = submitHooks;
        this.onSubmitHooksChange(submitHooks, callback);
    }
    internalAdd(_lajiFormId, relativePointer, hook, description) {
        const lajiFormId = `${_lajiFormId}`;
        let promise;
        const _hook = () => {
            return new Promise((resolve) => {
                let isRetry = false;
                const hooks = (this.submitHooks || []).map(hookItem => {
                    if (hookItem.hook === _hook) {
                        isRetry = true;
                        return Object.assign(Object.assign({}, hookItem), { running: true, promise });
                    }
                    return hookItem;
                });
                if (isRetry) {
                    this.send(hooks);
                }
                resolve(hook());
            }).then(() => {
                this.remove(lajiFormId, _hook);
            }).catch(e => {
                var _a;
                this.send((_a = this.submitHooks) === null || _a === void 0 ? void 0 : _a.map(hookItem => hookItem.hook === _hook ? Object.assign(Object.assign({}, hookItem), { e, running: false, failed: true }) : hookItem));
            });
        };
        promise = _hook();
        this.send([
            ...this.submitHooks,
            { hook: _hook, promise, lajiFormId, description, relativePointer, running: true }
        ]);
        return _hook;
    }
    /**
     * Add a submit hook for a Field component.
     */
    add(props, hook) {
        const id = (0, utils_1.getFieldUUID)(props);
        const idSchemaId = "id" in props ? props.id : props.idSchema.$id;
        const relativePointer = props.formContext.services.ids.getRelativePointer(idSchemaId, id);
        return this.internalAdd(id, relativePointer, hook);
    }
    /** Remove a hook either by id or hook instance */
    remove(lajiFormId, hook) {
        return new Promise(resolve => {
            lajiFormId = `${lajiFormId}`;
            const newHooks = this.submitHooks.filter(({ hook: _hook, lajiFormId: _lajiFormId }) => (hook ? _hook !== hook : lajiFormId !== _lajiFormId));
            newHooks.length !== this.submitHooks.length ? this.send(newHooks, resolve) : resolve();
        });
    }
    removeAll() {
        this.send([]);
    }
    checkHooks() {
        this.send(this.submitHooks.map(hookItem => (Object.assign(Object.assign({}, hookItem), { running: true }))));
        return Promise.all(this.submitHooks.map(({ promise, hook }) => {
            const setNotRunning = () => {
                this.send(this.submitHooks.map(hookItem => (Object.assign(Object.assign({}, hookItem), { running: hookItem.hook === hook ? false : hookItem.running }))));
            };
            return promise.then(setNotRunning).catch(setNotRunning);
        }));
    }
}
exports.default = SubmitHookService;
