import { NativeEventEmitter, EmitterSubscription } from 'react-native'

import {
  RfidBleNative,
  IRfidBleNative,
  RfidReader,
  EpcReply,
} from './NativeModule'

export * from './NativeModule'

export interface EventType<_T = undefined> {}

const EVENT_PREFIX = 'RFID_BLE'
const eventWithPrefix = <T>(eventName: string) =>
  `${EVENT_PREFIX}:${eventName}` as EventType<T>

export const RfidBleEvent = {
  DEBUG: eventWithPrefix('DEBUG'),

  START_SCANNING: eventWithPrefix('START_SCANNING'),
  STOP_SCANNING: eventWithPrefix('STOP_SCANNING'),

  READER_RECEIVED: eventWithPrefix<RfidReader>('READER_RECEIVED'),
  READER_CONNECTED: eventWithPrefix<RfidReader>('READER_CONNECTED'),
  READER_DISCONNECTED: eventWithPrefix<RfidReader>('READER_DISCONNECTED'),

  EPC_REPLIES_READ: eventWithPrefix<EpcReply[]>('EPC_REPLIES_READ'),
}

export const AUTO_SCAN_DEFAULT_DURATION = 6000 // in ms

class RfidBle extends NativeEventEmitter implements IRfidBleNative {
  private __autoScanTimeoutID: any = null

  constructor(private __nativeModule: IRfidBleNative) {
    super()
  }

  requestEnabled() {
    return this.__nativeModule.requestEnabled()
  }

  autoScan(duration = AUTO_SCAN_DEFAULT_DURATION) {
    this.__autoScanTimeoutID = setTimeout(this.stopScan.bind(this), duration)

    return this.startScan()
  }

  startScan() {
    return this.__nativeModule.startScan()
  }

  stopScan() {
    clearTimeout(this.__autoScanTimeoutID)
    return this.__nativeModule.stopScan()
  }

  connectToReader(readerAddress: string) {
    return this.__nativeModule.connectToReader(readerAddress)
  }

  disconnect() {
    return this.__nativeModule.disconnect()
  }

  on<E extends EventType>(
    eventType: E,
    listener: (arg: E extends EventType<infer T> ? T : never) => any
  ): EmitterSubscription {
    return super.addListener(eventType as any, listener)
  }
}

export default new RfidBle(RfidBleNative)
