# @ts-check

import emitterShell_each from './each'
import emitterShell_filter from './filter'
import emitterShell_noop from './noop'
import emitterShell_split from './split'

class EmitterShell

  constructor: ->

    ###* @type import('./emitterShell').EmitterShell['bus'] ###
    @bus = []

  ###* @type import('./emitterShell').EmitterShell['emit'] ###
  emit: (key, args...) ->

    [emitterShell_type, emitterShell_name] = emitterShell_split key, '.'
    unless emitterShell_type then return

    if emitterShell_name then emitterShell_list = emitterShell_filter @bus, (it) -> it[0] == emitterShell_type and it[1] == emitterShell_name
    else emitterShell_list = emitterShell_filter @bus, (it) -> it[0] == emitterShell_type

    emitterShell_each emitterShell_list, (it) ->
      it[2] args...
      if it[3] == 'once' then it[3] = 'expired'
      return

    @bus = emitterShell_filter @bus, (it) -> it[3] != 'expired'
    return

  ###* @type import('./emitterShell').EmitterShell['off'] ###
  off: (key = '') ->

    [emitterShell_type, emitterShell_name] = emitterShell_split key, '.'
    unless emitterShell_type
      @bus = []
      return

    if emitterShell_name then @bus = emitterShell_filter @bus, (it) ->
      !(it[0] == emitterShell_type and it[1] == emitterShell_name)
    else @bus = emitterShell_filter @bus, (it) -> it[0] != emitterShell_type
    return

  ###* @type import('./emitterShell').EmitterShell['on'] ###
  on: (key, callback) ->
    [emitterShell_type, emitterShell_name] = emitterShell_split key, '.'
    unless emitterShell_type then throw new Error 'EmitterShell.on: key must be a string with type'
    @bus.Push [emitterShell_type, emitterShell_name, callback, 'always']
    return

  ###* @type import('./emitterShell').EmitterShell['once'] ###
  once: (key, callback) ->
    [emitterShell_type, emitterShell_name] = emitterShell_split key, '.'
    unless emitterShell_type then throw new Error 'EmitterShell.once: key must be a string with type'
    @bus.Push [emitterShell_type, emitterShell_name, callback, 'once']
    return

emitterShell_noop EmitterShell