import { BusEventType } from './BusEvent'

export interface Module {
  endpoint: string
  name: string
  ns: string
  version: string
  vendor: {
    name: string
    slug: string
    url: string
  }
}

export interface Modules {
  [prop: string]: Module
}

type ModuleCollectionOptions = {
  logInConsole: boolean
  onRegistered?: Function
}

export const EVENT_REGISTERED = 'modules-registered'

export default class ModuleCollection {
  private readonly modules: Modules = {}
  private readonly eBus?: BusEventType
  private readonly options: ModuleCollectionOptions = {
    logInConsole: true,
  }

  constructor(modules?: Modules, eBus?: BusEventType, options: Partial<ModuleCollectionOptions> = {}) {
    this.eBus = eBus
    this.options = {
      ...this.options,
      ...options,
    }

    if (options?.onRegistered) {
      this.onRegistered(options?.onRegistered)
    }

    this.initModules(modules)
  }

  initModules(modules: Modules = {}) {
    for (const moduleName of Object.keys(modules)) {
      this.registerModule(modules[moduleName])
    }

    this.eBus?.$emit(EVENT_REGISTERED, this.modules, this)
  }

  registerModule(module: Module): void {
    if (this.modules[module.ns]) {
      if (this.options.logInConsole) {
        console.warn(`модуль ${module.name} уже зарегистрирован`)
      }
    } else {
      this.modules[module.ns] = { ...module }
    }
  }

  get(moduleName: string): Module | undefined {
    if (!this.modules[moduleName]) {
      if (this.options.logInConsole) {
        console.error(`модуль ${moduleName} не зарегистрирован`)
      }
      return undefined
    }

    return this.modules[moduleName]
  }

  count(): number {
    return Object.keys(this.modules).length
  }

  isEmpty(): boolean {
    return this.count() === 0
  }

  onRegistered(callback: Function): void {
    this.eBus?.$on(EVENT_REGISTERED, callback)
  }
}
