
class Scheduler {
    constructor() {
        this.middlewares = [];
    }

    use(fn) {
        if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
        this.middlewares.push(fn);
        return this;
    }

    compose() {
        return (context, next) => {
            let index = -1;
            const dispatch = (i) => {
                if (i <= index) return Promise.reject(new Error('next() called multiple times'));
                index = i;
                let fn = this.middlewares[i];
                if (index === this.middlewares.length) fn = next;
                if (!fn) return Promise.resolve();
                try {
                    return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
                } catch (e) {
                    return Promise.reject(e);
                }
            };
            return dispatch(0);
        };
    }
}

export default new Scheduler();
