export class Observable {
    _eventListeners = [];
    _object = null;

    constructor(object) {
        this._object = object;
        /*
        , inject = ['on', 'off', 'dispatch']
        if (inject && (inject instanceof Array)) {
            for (let m of inject) {
                object[m] = this[m].bind(this);
            }
        }
        */
    }

    on(eventName, callback) {
        if (this.indexOf(eventName, callback) !== -1) {
            // eslint-disable-next-line no-console
            console.warn(`The following callback is already added to the event: ${eventName}`, callback);
            return;
        }
        this._eventListeners.push({
            eventName,
            callback,
        });
        return () => this.off(eventName, callback);
    }

    off(eventName, callback) {
        const idx = this.indexOf(eventName, callback);
        if (idx !== -1) {
            this._eventListeners.splice(idx, 1);
        }
    }

    indexOf(eventName, callback) {
        for (let o = 0; o < this._eventListeners.length; o++) {
            const el = this._eventListeners[o];
            if (el.eventName === eventName && el.callback === callback) {
                return o;
            }
        }
        return -1;
    }

    dispatch(eventName, params, direct = false) {
        const notify = this.createNotifyFunction(eventName, params);
        if (direct) {
            notify();
        } else {
            setTimeout(notify);
        }
    }

    createNotifyFunction(eventName, params) {
        return () => {
            for (let el of this._eventListeners) {
                if (el.eventName === eventName) {
                    el.callback.call(this._object, {
                        eventName,
                        time: new Date(),
                        data: params,
                    });
                }
            }
        };
    }

    dispose() {
        this._eventListeners = [];
        this._object = undefined;
    }
}

export default Observable;
