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

import Base from './Base'
import RNGizDeviceManagerModule, { RNGizDeviceManagerModule as RNGizDeviceManagerModuleClass} from './device'
import {
  DeviceDataCallback,
  DeviceDataRes,
  DeviceListCallback,
  DeviceBindCallback,
  DeviceStateCallback,
  DeviceBindRes,
  DeviceStateRes,
  GizCallback,
  GizConfigStruct,
  IDevice,
} from './types'
import * as Types from './types'
import RNGizUserManagerModule, { RNGizUserManagerModule as RNGizUserManagerModuleClass} from './user'

const eventEmitter = new NativeEventEmitter(NativeModules.RNGizSDKManagerModule)

class RNGizSDKManagerModuleClass extends Base {
  deviceDataCallbacks: DeviceDataCallback[] = []
  deviceListCallbacks: DeviceListCallback[] = []
  deviceStateCallbacks: DeviceStateCallback[] = []
  deviceBindCallbacks: DeviceBindCallback[] = []

  constructor() {
    super()
  }

  public registerListener = () => {
    eventEmitter.addListener('DeviceDataListener', this.deviceDataCallback)
    eventEmitter.addListener('DeviceListListener', this.deviceListCallback)
    eventEmitter.addListener('DeviceStateListener', this.deviceStateCallback)
    eventEmitter.addListener('DeviceBindStateListener', this.deviceBindCallback)
  }
  appendDeviceFunction = (device: IDevice) => {
    // 补充对应的设备方法
    device.bleCapability.connect = () => {
      return RNGizDeviceManagerModule.connect(device.id, 'BLE')
    }
    device.lanCapability.connect = () => {
      return RNGizDeviceManagerModule.connect(device.id, 'LAN')
    }
    device.mqttCapability.connect = () => {
      return RNGizDeviceManagerModule.connect(device.id, 'MQTT')
    }
    device.bleCapability.disConnect = () => {
      return RNGizDeviceManagerModule.disConnect(device.id, 'BLE')
    }
    device.lanCapability.disConnect = () => {
      return RNGizDeviceManagerModule.disConnect(device.id, 'LAN')
    }
    device.mqttCapability.disConnect = () => {
      return RNGizDeviceManagerModule.disConnect(device.id, 'MQTT')
    }

    device.bleCapability.sendDp = (data: Object) => {
      return RNGizDeviceManagerModule.sendDp(device.id, 'BLE', data)
    }
    device.lanCapability.sendDp = (data: Object) => {
      return RNGizDeviceManagerModule.sendDp(device.id, 'LAN', data)
    }
    device.mqttCapability.sendDp = (data: Object) => {
      return RNGizDeviceManagerModule.sendDp(device.id, 'MQTT', data)
    }

    device.bleCapability.getDp = (attrs?: string[]) => {
      return RNGizDeviceManagerModule.getDp(device.id, 'BLE', attrs)
    }
    device.lanCapability.getDp = (attrs?: string[]) => {
      return RNGizDeviceManagerModule.getDp(device.id, 'LAN', attrs)
    }
    device.mqttCapability.getDp = (attrs?: string[]) => {
      return RNGizDeviceManagerModule.getDp(device.id, 'MQTT', attrs)
    }

    device.bleCapability.getDeviceInfo = () => {
      return RNGizDeviceManagerModule.getDeviceInfo(device.id, 'BLE')
    }
    device.lanCapability.getDeviceInfo = () => {
      return RNGizDeviceManagerModule.getDeviceInfo(device.id, 'LAN')
    }
    device.mqttCapability.getDeviceInfo = () => {
      return RNGizDeviceManagerModule.getDeviceInfo(device.id, 'MQTT')
    }

    device.bleCapability.startUpgrade = (
      firmwareType: Types.GizOTAFirmwareType,
      callback: Types.GizOtaProgressCallback
    ) => {
      return RNGizDeviceManagerModule.startUpgrade(
        device.id,
        'BLE',
        firmwareType,
        callback
      )
    }
    device.lanCapability.startUpgrade = (
      firmwareType: Types.GizOTAFirmwareType,
      callback: Types.GizOtaProgressCallback
    ) => {
      return RNGizDeviceManagerModule.startUpgrade(
        device.id,
        'LAN',
        firmwareType,
        callback
      )
    }
    device.mqttCapability.startUpgrade = (
      firmwareType: Types.GizOTAFirmwareType,
      callback: Types.GizOtaProgressCallback
    ) => {
      return RNGizDeviceManagerModule.startUpgrade(
        device.id,
        'MQTT',
        firmwareType,
        callback
      )
    }

    /**
     * 配网相关
     */
    device.bleCapability.provideWiFiCredentials = (
      ssid: string,
      password: string,
      timeout: number,
      callback: Types.GizProvideWiFiCredentialsCallback
    ) => {
      return RNGizDeviceManagerModule.provideWiFiCredentials(
        device.id,
        'BLE',
        ssid,
        password,
        timeout,
        callback
      )
    }
    device.lanCapability.provideWiFiCredentials = (
      ssid: string,
      password: string,
      timeout: number,
      callback: Types.GizProvideWiFiCredentialsCallback
    ) => {
      return RNGizDeviceManagerModule.provideWiFiCredentials(
        device.id,
        'LAN',
        ssid,
        password,
        timeout,
        callback
      )
    }
    device.mqttCapability.provideWiFiCredentials = (
      ssid: string,
      password: string,
      timeout: number,
      callback: Types.GizProvideWiFiCredentialsCallback
    ) => {
      return RNGizDeviceManagerModule.provideWiFiCredentials(
        device.id,
        'MQTT',
        ssid,
        password,
        timeout,
        callback
      )
    }
    device.bleCapability.stopProvideWiFiCredentials = () => {
      return RNGizDeviceManagerModule.stopProvideWiFiCredentials(
        device.id,
        'BLE'
      )
    }
    device.lanCapability.stopProvideWiFiCredentials = () => {
      return RNGizDeviceManagerModule.stopProvideWiFiCredentials(
        device.id,
        'LAN'
      )
    }
    device.mqttCapability.stopProvideWiFiCredentials = () => {
      return RNGizDeviceManagerModule.stopProvideWiFiCredentials(
        device.id,
        'MQTT'
      )
    }

    /**
     * 配网相关
     */

    device.updateDeviceInfo = (alias?: string, remark?: string) => {
      return RNGizDeviceManagerModule.updateDeviceInfo(device.id, alias, remark)
    }
    device.bind = (alias?: string, remark?: string) => {
      return RNGizDeviceManagerModule.bind(device.id, alias, remark)
    }
    device.unBind = () => {
      return RNGizDeviceManagerModule.unBind(device.id)
    }
    device.register = () => {
      return RNGizDeviceManagerModule.register(device.id)
    }

    device.bleCapability.checkUpdate = (
      firmwareType: Types.GizOTAFirmwareType
    ) => {
      return RNGizDeviceManagerModule.checkUpdate(
        device.id,
        'BLE',
        firmwareType
      )
    }
    device.lanCapability.checkUpdate = (
      firmwareType: Types.GizOTAFirmwareType
    ) => {
      return RNGizDeviceManagerModule.checkUpdate(
        device.id,
        'LAN',
        firmwareType
      )
    }
    device.mqttCapability.checkUpdate = (
      firmwareType: Types.GizOTAFirmwareType
    ) => {
      return RNGizDeviceManagerModule.checkUpdate(
        device.id,
        'MQTT',
        firmwareType
      )
    }

    device.bleCapability.provideWiFiCredentials = (
      ssid: string,
      password: string,
      timeout: number,
      processHandler: Types.GizProvideWiFiCredentialsCallback
    ) => {
      return RNGizDeviceManagerModule.provideWiFiCredentials(
        device.id,
        'BLE',
        ssid,
        password,
        timeout,
        processHandler
      )
    }
    device.lanCapability.provideWiFiCredentials = (
      ssid: string,
      password: string,
      timeout: number,
      processHandler: Types.GizProvideWiFiCredentialsCallback
    ) => {
      return RNGizDeviceManagerModule.provideWiFiCredentials(
        device.id,
        'LAN',
        ssid,
        password,
        timeout,
        processHandler
      )
    }
    device.mqttCapability.provideWiFiCredentials = (
      ssid: string,
      password: string,
      timeout: number,
      processHandler: Types.GizProvideWiFiCredentialsCallback
    ) => {
      return RNGizDeviceManagerModule.provideWiFiCredentials(
        device.id,
        'MQTT',
        ssid,
        password,
        timeout,
        processHandler
      )
    }

    // 定时器相关
    device.bleCapability.queryTimer = () => {
      return RNGizDeviceManagerModule.queryTimer(device.id, 'BLE')
    }
    device.lanCapability.queryTimer = () => {
      return RNGizDeviceManagerModule.queryTimer(device.id, 'LAN')
    }
    device.mqttCapability.queryTimer = () => {
      return RNGizDeviceManagerModule.queryTimer(device.id, 'MQTT')
    }

    device.bleCapability.deleteTimer = (timerId: number) => {
      return RNGizDeviceManagerModule.deleteTimer(device.id, 'BLE', timerId)
    }
    device.lanCapability.deleteTimer = (timerId: number) => {
      return RNGizDeviceManagerModule.deleteTimer(device.id, 'LAN', timerId)
    }
    device.mqttCapability.deleteTimer = (timerId: number) => {
      return RNGizDeviceManagerModule.deleteTimer(device.id, 'MQTT', timerId)
    }

    device.bleCapability.editTimer = (data: Types.GizDeviceLocalTimerParams) => {
      return RNGizDeviceManagerModule.editTimer(device.id, 'BLE', data)
    }
    device.lanCapability.editTimer = (data: Types.GizDeviceLocalTimerParams) => {
      return RNGizDeviceManagerModule.editTimer(device.id, 'LAN', data)
    }
    device.mqttCapability.editTimer = (data: Types.GizDeviceLocalTimerParams) => {
      return RNGizDeviceManagerModule.editTimer(device.id, 'MQTT', data)
    }

    device.bleCapability.createTimer = (data: Types.GizDeviceLocalTimerParams) => {
      return RNGizDeviceManagerModule.createTimer(device.id, 'BLE', data)
    }
    device.lanCapability.createTimer = (data: Types.GizDeviceLocalTimerParams) => {
      return RNGizDeviceManagerModule.createTimer(device.id, 'LAN', data)
    }
    device.mqttCapability.createTimer = (data: Types.GizDeviceLocalTimerParams) => {
      return RNGizDeviceManagerModule.createTimer(device.id, 'MQTT', data)
    }
  }

  deviceDataCallback = (data: DeviceDataRes) => {
    this.deviceDataCallbacks.map((item) => {
      item(data)
    })
  }
  deviceListCallback = (data: IDevice[]) => {
    this.deviceListCallbacks.map((item) => {
      data.map((d) => {
        this.appendDeviceFunction(d)
      })
      item(data)
    })
  }
  deviceStateCallback = (data: DeviceStateRes) => {
    this.deviceStateCallbacks.map((item) => {
      item(data)
    })
  }
  deviceBindCallback = (data: DeviceBindRes) => {
    this.deviceBindCallbacks.map((item) => {
      item(data)
    })
  }

  async initSDK(config: GizConfigStruct): Promise<Types.GizResult<any, any>> {
    this.registerListener()
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizSDKManagerModule.initSDK(config, callback)
    })
  }
  async getProductDataPointConfig(
    productKey: String
  ): Promise<Types.GizResult<string, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizSDKManagerModule.getProductDataPointConfig(
        { productKey },
        callback
      )
    })
  }

  async startBleScan(): Promise<Types.GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizSDKManagerModule.startBleScan({}, callback)
    })
  }
  async stopBleScan(): Promise<Types.GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizSDKManagerModule.stopBleScan({}, callback)
    })
  }

  async feedback(
    uploadLog: boolean,
    contact: string,
    content: string
  ): Promise<Types.GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizSDKManagerModule.feedback(
        { uploadLog, contact, content },
        callback
      )
    })
  }

  async cleanCache(): Promise<Types.GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizSDKManagerModule.cleanCache({}, callback)
    })
  }
  /**
   * 查询设备列表
   */
  async getDevices(): Promise<Types.GizResult<[IDevice], any>> {
    const data = await this.callbackWapper(
      (callback: GizCallback<IDevice[], any>) => {
        NativeModules.RNGizSDKManagerModule.getDevices({}, callback)
      }
    )
    if (data.success) {
      data.data?.map((item: IDevice) => {
        // 补充一些方法
        this.appendDeviceFunction(item)
      })
    }
    return data
  }

  // 添加监听
  addDeviceDataListener(callback: DeviceDataCallback) {
    this.deviceDataCallbacks.push(callback)
  }
  addDeviceListListener(callback: DeviceListCallback) {
    this.deviceListCallbacks.push(callback)
  }
  addDeviceStateListener(callback: DeviceStateCallback) {
    this.deviceStateCallbacks.push(callback)
  }
  addDeviceBindStateListener(callback: DeviceBindCallback) {
    this.deviceBindCallbacks.push(callback)
  }

  // 解除
  removeDeviceDataListener(callback: DeviceDataCallback) {
    this.deleteCallBack(this.deviceDataCallbacks, callback)
  }
  removeDeviceListListener(callback: DeviceListCallback) {
    this.deleteCallBack(this.deviceListCallbacks, callback)
  }
  removeDeviceStateListener(callback: DeviceStateCallback) {
    this.deleteCallBack(this.deviceStateCallbacks, callback)
  }
  removeDeviceBindStateListener(callback: DeviceBindCallback) {
    this.deleteCallBack(this.deviceBindCallbacks, callback)
  }
}

const RNGizSDKManagerModule = new RNGizSDKManagerModuleClass();
export default RNGizSDKManagerModule

export { RNGizDeviceManagerModule, RNGizUserManagerModule, RNGizSDKManagerModule, Types, RNGizSDKManagerModuleClass, RNGizDeviceManagerModuleClass, RNGizUserManagerModuleClass }
