"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.EventBus = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _rxjs = require("rxjs");
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

/** Key used to represent all content types */
const ALL_TYPES_KEY = '*';

/**
 * Content event listener
 */

/**
 * Event bus for all content generated events
 */
class EventBus {
  /** The events Rxjs Subject */

  /** Map of listener for each content type */

  /** Subscription to the _events$ Observable */

  /**
   * @param contentTypeValidator Handler to validate if a content type is valid or not
   */
  constructor(contentTypeValidator) {
    (0, _defineProperty2.default)(this, "_events$", void 0);
    (0, _defineProperty2.default)(this, "eventListeners", new Map());
    (0, _defineProperty2.default)(this, "eventsSubscription", void 0);
    this.contentTypeValidator = contentTypeValidator;
    this._events$ = new _rxjs.Subject();
    this.eventsSubscription = this._events$.subscribe(event => {
      const eventListeners = this.eventListeners.get(event.type);
      if (eventListeners) {
        var _eventListeners$event, _eventListeners$ALL_T;
        const listeners = [...((_eventListeners$event = eventListeners[event.contentTypeId]) !== null && _eventListeners$event !== void 0 ? _eventListeners$event : []), ...((_eventListeners$ALL_T = eventListeners[ALL_TYPES_KEY]) !== null && _eventListeners$ALL_T !== void 0 ? _eventListeners$ALL_T : [])];
        listeners.forEach(cb => {
          cb(event);
        });
      }
    });
  }

  /**
   *
   *
   * @param type The event type e.g. "getItemSuccess")
   * @param cb Callback to execute
   *
   * @example
   *
   * ```ts
   * // Register an event for all content types
   * eventBus.on('getItemSuccess', (event) => {})
   *
   * // Register an event for the "dashboard" content type
   * * eventBus.on('getItemSuccess', 'dashboard', (event) => {})
   * ```
   */

  /**
   * Register an event listener for specific events on specific content types
   *
   * @param eventType The event type to listen to
   * @param contentType The content type to listen to (if not specified all content types will send the event type)
   * @param cb Handler to call when the event occurs
   *
   * @returns Handler to unsubscribe
   */
  on(eventType, _contentType, _cb) {
    const contentType = typeof _contentType === 'function' ? ALL_TYPES_KEY : _contentType;
    const cb = typeof _contentType === 'function' ? _contentType : _cb;
    if (contentType !== ALL_TYPES_KEY) {
      var _this$contentTypeVali, _this$contentTypeVali2;
      const isContentTypeValid = (_this$contentTypeVali = (_this$contentTypeVali2 = this.contentTypeValidator) === null || _this$contentTypeVali2 === void 0 ? void 0 : _this$contentTypeVali2.call(this, contentType)) !== null && _this$contentTypeVali !== void 0 ? _this$contentTypeVali : true;
      if (!isContentTypeValid) {
        throw new Error(`Invalid content type [${contentType}].`);
      }
    }
    if (!this.eventListeners.has(eventType)) {
      this.eventListeners.set(eventType, {});
    }
    const eventTypeListeners = this.eventListeners.get(eventType);
    if (eventTypeListeners[contentType] === undefined) {
      eventTypeListeners[contentType] = new Set();
    }
    eventTypeListeners[contentType].add(cb);
    return () => {
      eventTypeListeners[contentType].delete(cb);
    };
  }

  /**
   * Send an event to the CM event bus
   * @param event The event to send
   */
  emit(event) {
    this._events$.next(event);
  }

  /** Content management events Observable */
  get events$() {
    return this._events$.asObservable();
  }
  stop() {
    this.eventsSubscription.unsubscribe();
  }
}
exports.EventBus = EventBus;