text: "use strict";
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
      var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
      if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
      else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
      return c > 3 && r && Object.defineProperty(target, key, r), r;
  };
  var __metadata = (this && this.__metadata) || function (k, v) {
      if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
  };
  Object.defineProperty(exports, "__esModule", { value: true });
  const common_1 = require("@nestjs/common");
  const core_1 = require("@nestjs/core");
  const rxjs_1 = require("rxjs");
  const operators_1 = require("rxjs/operators");
  const util_1 = require("util");
  const command_bus_1 = require("./command-bus");
  const constants_1 = require("./decorators/constants");
  const invalid_saga_exception_1 = require("./exceptions/invalid-saga.exception");
  const default_pubsub_1 = require("./helpers/default-pubsub");
  const observable_bus_1 = require("./utils/observable-bus");
  let EventBus = class EventBus extends observable_bus_1.ObservableBus {
      constructor(commandBus, moduleRef) {
          super();
          this.commandBus = commandBus;
          this.moduleRef = moduleRef;
          this.subscriptions = [];
          this.useDefaultPublisher();
      }
      get publisher() {
          return this._publisher;
      }
      set publisher(_publisher) {
          this._publisher = _publisher;
      }
      onModuleDestroy() {
          this.subscriptions.forEach(subscription => subscription.unsubscribe());
      }
      publish(event) {
          this._publisher.publish(event);
      }
      publishAll(events) {
          (events || []).forEach(event => this._publisher.publish(event));
      }
      bind(handler, name) {
          const stream$ = name ? this.ofEventName(name) : this.subject$;
          const subscription = stream$.subscribe(event => handler.handle(event));
          this.subscriptions.push(subscription);
      }
      registerSagas(types = []) {
          const sagas = types
              .map(target => {
              const metadata = Reflect.getMetadata(constants_1.SAGA_METADATA, target) || [];
              const instance = this.moduleRef.get(target, { strict: false });
              if (!instance) {
                  throw new invalid_saga_exception_1.InvalidSagaException();
              }
              return metadata.map((key) => instance[key]);
          })
              .reduce((a, b) => a.concat(b), []);
          sagas.forEach(saga => this.registerSaga(saga));
      }
      register(handlers = []) {
          handlers.forEach(handler => this.registerHandler(handler));
      }
      registerHandler(handler) {
          const instance = this.moduleRef.get(handler, { strict: false });
          if (!instance) {
              return;
          }
          const eventsNames = this.reflectEventsNames(handler);
          eventsNames.map(event => this.bind(instance, event.name));
      }
      ofEventName(name) {
          return this.subject$.pipe(operators_1.filter(event => this.getEventName(event) === name));
      }
      getEventName(event) {
          const { constructor } = Object.getPrototypeOf(event);
          return constructor.name;
      }
      registerSaga(saga) {
          if (!util_1.isFunction(saga)) {
              throw new invalid_saga_exception_1.InvalidSagaException();
          }
          const stream$ = saga(this);
          if (!(stream$ instanceof rxjs_1.Observable)) {
              throw new invalid_saga_exception_1.InvalidSagaException();
          }
          const subscription = stream$
              .pipe(operators_1.filter(e => !!e))
              .subscribe(command => this.commandBus.execute(command));
          this.subscriptions.push(subscription);
      }
      reflectEventsNames(handler) {
          return Reflect.getMetadata(constants_1.EVENTS_HANDLER_METADATA, handler);
      }
      useDefaultPublisher() {
          const pubSub = new default_pubsub_1.DefaultPubSub();
          pubSub.bridgeEventsTo(this.subject$);
          this._publisher = pubSub;
      }
  };
  EventBus = __decorate([
      common_1.Injectable(),
      __metadata("design:paramtypes", [command_bus_1.CommandBus,
          core_1.ModuleRef])
  ], EventBus);
  exports.EventBus = EventBus;
  