import DeferredError from '../../Shared/ErrorTypes/DeferredError';

export { DeferredError };

/**
 * @private
 * @type {{}}
 */
const promises = {};

export class Deferred {
    constructor(name = false) {
        if (promises[name]) {
            throw new DeferredError('Instance already exists with the name: ' + name);
        }
        this.name = name;
        this.promise = new Promise((resolve, reject) => {
            this._resolve = resolve;
            this._reject = reject;
        });
        if (name) {
            promises[name] = this;
        }
    }

    remove() {
        delete promises[this.name];
    }

    resolve = (...args) => {
        this.remove();
        this._resolve.apply(0, args);
    };

    reject = (...args) => {
        this.remove();
        this._reject.apply(0, args);
    };

    then(fn) {
        this.promise.then(fn);
    }

    static get(name) {
        if (!promises[name]) {
            throw new DeferredError('Instance does not exist with the name: ' + name);
        }
        return promises[name];
    }
}

export default Deferred;

export class DeferredGroup {
    deferredList = [];

    constructor() {
        if (arguments.length > 0) {
            this.deferredList = this.deferredList.concat(arguments);
        }
    }

    create(name = false) {
        const deferred = new Deferred(name);
        this.add(deferred);
        return deferred;
    }

    createResolver(name = false) {
        return this.create(name).resolve;
    }

    add(deferred) {
        this.deferredList.push(deferred);
    }

    then(fn) {
        return Promise.all(this.deferredList.map(d => d.promise)).then(fn);
    }
}
