import { Airgram } from 'tdweb-airgram'
import Vue from 'vue'
import { TdEventContext, TdEventHandler } from './types'

export interface TdProviderConfig<AirgramContextT extends Airgram.Context> {
  airgram: Airgram<AirgramContextT>
}

class TdProvider<AirgramContextT extends Airgram.Context = Airgram.Context> {
  public static install: any

  public readonly airgram: Airgram.AirgramInstance<AirgramContextT>

  private readonly eventBus: Vue

  private isInitialized: boolean = false

  constructor ({ airgram }: TdProviderConfig<AirgramContextT>) {
    this.airgram = airgram
    this.eventBus = new Vue()
  }

  public off (eventName: string, handler: TdEventHandler): void {
    this.eventBus.$off(eventName, handler)
  }

  public on (eventName: string, handler: TdEventHandler): () => void {
    return this.listen('$on', eventName, handler)
  }

  public once (eventName: string, handler: TdEventHandler): () => void {
    return this.listen('$once', eventName, handler)
  }

  private initialize () {
    this.airgram.updates.use(({ airgram, update, getState, setState }) => {
      const context: TdEventContext = { airgram, getState, setState }
      this.eventBus.$emit(update, context)
    })
  }

  private listen (type: '$on' | '$once', eventName: string, handler: TdEventHandler): () => void {
    if (!this.isInitialized) {
      this.initialize()
    }
    this.isInitialized = true
    this.eventBus[type](eventName, handler)
    return () => this.off(eventName, handler)
  }
}

export {
  TdProvider
}
