export type Observer<T> = (value: T) => void

export interface Observable<T> {
  subscribe: (observer: Observer<T>) => { unsubscribe: () => void }
}

export class Subject<T> {
  protected observers = new Set<Observer<T>>()

  next(value: T): void {
    this.observers.forEach((observer) => observer(value))
  }

  asObservable(): Observable<T> {
    return {
      subscribe: (observer: Observer<T>) => {
        this.observers.add(observer)
        return {
          unsubscribe: () => this.observers.delete(observer),
        }
      },
    }
  }
}

export class BehaviorSubject<T> extends Subject<T> {
  private currentValue: T

  constructor(currentValue: T) {
    super()
    this.currentValue = currentValue
  }

  override next(value: T): void {
    this.currentValue = value
    super.next(value)
  }

  get value(): T {
    return this.currentValue
  }

  override asObservable(): Observable<T> {
    return {
      subscribe: (observer: Observer<T>) => {
        observer(this.currentValue)
        return super.asObservable().subscribe(observer)
      },
    }
  }
}
