import ISubscriber, {LEvent} from "./Subscriber"; class PublisherSubscription implements ISubscription { private subscriber: ISubscriber; private readonly eventTypes: EventType[]; private unbindCallback?: () => void; constructor(subscriber: ISubscriber, eventTypes: EventType[]) { this.subscriber = subscriber; this.eventTypes = eventTypes; } setUnbind(unbind: () => void): void { this.unbindCallback = unbind; } unbind(): void { this.unbindCallback?.(); } getEventTypes(): EventType[] { return this.eventTypes; } getSubscriber(): ISubscriber { return this.subscriber; } } interface EventSubscriberRecord { get(key: K): ISubscriber[]; set(key: K, subscribers: ISubscriber[]): EventSubscriberRecord; } export class Publisher implements IPublisher { private subscribers: EventSubscriberRecord; private parent: PublisherType; constructor(parent: PublisherType) { this.parent = parent; this.subscribers = new Map(); } addSubscriber(subscriber: ISubscriber, subscribeTo: EventType | Readonly): ISubscription { let eventTypes: EventType[] = []; if (typeof subscribeTo === "string") { eventTypes.push(subscribeTo); } else { eventTypes = subscribeTo.slice(); } for (const key of eventTypes) { this.getSubscribers(key).push(subscriber); } const sub = new PublisherSubscription(subscriber, eventTypes); sub.setUnbind(() => this.unbind(sub)); return sub; } private unbind(subscription: PublisherSubscription): void { for (const key of subscription.getEventTypes()) { const subs = this.getSubscribers(key); subs.splice(subs.indexOf(subscription.getSubscriber()), 1); } } private getSubscribers(key: K): ISubscriber[] { const subscribersList = this.subscribers.get(key); if (subscribersList === undefined) { const newList: ISubscriber[] = []; this.subscribers.set(key, newList); return newList; } else { return subscribersList; } } notifySubs(eventType: K): void { for (const sub of this.getSubscribers(eventType)) { sub.notify(this.parent, eventType); } } } export interface IPublisher { addSubscriber(subscriber: ISubscriber, subscribeTo: T | T[]): { unbind: () => void }; } export interface ISubscription { unbind(): void; }