import { RicosTopic } from "./topics.js";
class EventInitializationError extends Error {
}
class DisposedEventAccessError extends Error {
}
const _RicosEvent = class _RicosEvent {
  constructor(topicDescriptor, logger) {
    this.subscribers = [];
    this.isActive = true;
    this.logger = logger;
    const topic = RicosTopic.fromString(topicDescriptor);
    if (topic.isWildcard()) {
      throw new EventInitializationError(
        `cannot create event with wildcard topic ${topicDescriptor}`
      );
    }
    this.topic = topic;
  }
  subscribe(handler, subscriberId) {
    const subscriber = new EventSubscriber(handler, subscriberId);
    if (this.isDuplicateSubscriber(subscriber)) {
    }
    this.subscribers.push(subscriber);
    this.logger.log(`[${this.topic}]: ${subscriberId} subscribed`);
    return {
      topic: this.topic.toString(),
      cancel: () => {
        this.logger.log(`[${this.topic}]: ${subscriberId} unsubscribed`);
        this.subscribers = this.subscribers.filter((s) => s !== subscriber);
      }
    };
  }
  isDuplicateSubscriber(subscriber) {
    return this.subscribers.some((s) => s.id === subscriber.id);
  }
  publishSync(data) {
    if (!this.isActive) {
      throw new DisposedEventAccessError(`[${this.topic}] cannot publish disposed event`);
    }
    const t1 = performance.now();
    const processings = this.subscribers.map((subscriber) => {
      const t3 = performance.now();
      subscriber.invoke(this.topic.toString(), data);
      const t4 = performance.now();
      return {
        subscriberId: subscriber.id,
        duration: t4 - t3
      };
    });
    const t2 = performance.now();
    const metadata = {
      topic: this.topic.toString(),
      eventId: ++_RicosEvent.eventId,
      data,
      duration: t2 - t1,
      timestamp: /* @__PURE__ */ new Date(),
      isAsync: false,
      processings
    };
    this.logger.log(metadata);
    return this.subscribers.length > 0;
  }
  publish(data) {
    if (!this.isActive) {
      throw new DisposedEventAccessError(`[${this.topic}] cannot publish disposed event`);
    }
    const t1 = performance.now();
    this.subscribers.forEach(
      (subscriber) => setTimeout(() => subscriber.invoke(this.topic.toString(), data), 0)
    );
    const t2 = performance.now();
    const metadata = {
      topic: this.topic.toString(),
      eventId: ++_RicosEvent.eventId,
      data,
      duration: t2 - t1,
      timestamp: /* @__PURE__ */ new Date(),
      isAsync: true
    };
    this.logger.log(metadata);
    return this.subscribers.length > 0;
  }
  publishOnce(data) {
    const published = this.publish(data);
    if (published) {
      this.dispose();
    }
    return published;
  }
  getTopic() {
    return this.topic;
  }
  dispose() {
    this.subscribers = [];
    this.isActive = false;
    this.logger.log(`[${this.topic}]: event disposed`);
  }
};
_RicosEvent.eventId = 0;
let RicosEvent = _RicosEvent;
class EventSubscriber {
  constructor(callback, id) {
    this.id = id;
    this.callback = callback;
  }
  invoke(topic, data) {
    this.callback(topic, data);
  }
}
export {
  EventInitializationError,
  EventSubscriber,
  RicosEvent
};
//# sourceMappingURL=ricos-event.js.map
