import Utils from "../Utils/Utils";

let instance;
const instanceKey = 'evt_fuse_392994';

export class Event {
    constructor(key, callback, target = null) {
        this.key = key;
        this.callback = callback;
        this.target = target;
    }
}

class EventBus {
    _events = [];

    constructor(key) {
        if (key !== instanceKey) {
            throw new Error('Cannot instantiate like this');
        }
    }

    registerEvent(event, callback) {
        if (!(event instanceof Event)) {
            throw new Error('Only Event instances are accepted');
        }
        if (this._eventExists(event) !== -1) {
            console.warn('Cannot register Event. Already registered!');
            return;
        }
        this._events.push(event);
    }

    registerDynamicEvent(event, callback) {
        if (!event?.key) {
            console.error('Missing event key', event);
            return;
        }
        const eventToAdd = {
            key: event.key,
            callback: callback || event.callback,
            target: event.target || null
        };
        this._events.push(eventToAdd);
    }

    triggerEvent(key, payload) {
        for (const event of this._events) {
            if (event.key === key) {
                if (typeof event.callback === 'function') {
                    event.callback(payload);
                }
            }
        }
    }

    triggerDynamicEvent(key, payload) {
        for (const event of this._events) {
            if (event.key === key) {
                if (typeof event.callback === 'function') {
                    event.callback(key, payload);
                }
            }
        }
    }

    removeEvent(event) {
        if (!(event instanceof Event)) {
            throw new Error('Only Event instances are accepted');
        }
        const index = this._eventExists(event);
        if (index !== -1) {
            this._events.splice(index, 1);
        }
    }

    _eventExists(event) {
        let index = -1;
        for (let i = 0; i < this._events.length; i++) {
            if (this._eventsAreEqual(event, this._events[i])) {
                index = i;
                break;
            }
        }
        return index;
    }

    _eventsAreEqual(event1, event2) {
        return event1.key === event2.key &&
               event1.callback === event2.callback &&
               event1.target === event2.target;
    }

    static getInstance() {
        if (!instance) {
            instance = new EventBus(instanceKey);
        }
        return instance;
    }
}

export default EventBus;
