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

import Base from './Base'
import {
  GizCallback,
  GizCapability,
  GizDeviceData,
  GizDeviceInfoProfile,
  GizOTAFirmwareType,
  GizOtaProgressCallback,
  GizOtaProgressEventCallback,
  GizProvideWiFiCredentialsCallback,
  GizResult,
  GizDeviceLocalTimerParams,
} from './types'
const eventEmitter = new NativeEventEmitter(
  NativeModules.RNGizDeviceManagerModule
)

class RNGizDeviceManagerModule extends Base {
  otaEventCallbacks: GizOtaProgressEventCallback[] = []
  provideWiFiCredentialsCallbacks: GizProvideWiFiCredentialsCallback[] = []
  constructor() {
    super()
    eventEmitter.addListener('GizOTAProgressEvent', this.otaEventCallback)
    eventEmitter.addListener(
      'GizProvideWiFiCredentialsEvent',
      this.provideWiFiCredentialsCallback
    )
  }

  otaEventCallback: GizOtaProgressEventCallback = (data) => {
    this.otaEventCallbacks.map((item) => {
      item(data)
    })
  }
  provideWiFiCredentialsCallback: GizProvideWiFiCredentialsCallback = (
    data
  ) => {
    this.provideWiFiCredentialsCallbacks.map((item) => {
      item(data)
    })
  }

  sendDp(
    id: string,
    type: GizCapability,
    data: Object
  ): Promise<GizResult<GizDeviceData, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      const dataString = JSON.stringify(data)
      NativeModules.RNGizDeviceManagerModule.sendDp(
        {
          id,
          type,
          data: dataString,
        },
        callback
      )
    })
  }
  getDp(
    id: string,
    type: GizCapability,
    attrs?: string[]
  ): Promise<GizResult<GizDeviceData, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.getDp(
        {
          id,
          type,
          attrs,
        },
        callback
      )
    })
  }

  getDeviceInfo(
    id: string,
    type: GizCapability
  ): Promise<GizResult<GizDeviceInfoProfile, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.getDeviceInfo(
        {
          id,
          type,
        },
        callback
      )
    })
  }

  connect(id: string, type: GizCapability): Promise<GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.connect(
        {
          id,
          type,
        },
        callback
      )
    })
  }
  disConnect(id: string, type: GizCapability): Promise<GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.disConnect(
        {
          id,
          type,
        },
        callback
      )
    })
  }


  updateDeviceInfo(
    id: string,
    alias?: string,
    remark?: string
  ): Promise<GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.updateDeviceInfo(
        {
          id,
          alias,
          remark,
        },
        callback
      )
    })
  }

  bind(
    id: string,
    alias?: string,
    remark?: string
  ): Promise<GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.bind(
        {
          id,
          alias,
          remark,
        },
        callback
      )
    })
  }
  unBind(id: string): Promise<GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.unBind(
        {
          id,
        },
        callback
      )
    })
  }
  register(id: string): Promise<GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.register(
        {
          id,
        },
        callback
      )
    })
  }
  checkUpdate(
    id: string,
    type: GizCapability,
    firmwareType: GizOTAFirmwareType
  ): Promise<GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.checkUpdate(
        {
          id,
          type,
          firmwareType,
        },
        callback
      )
    })
  }

  async startUpgrade(
    id: string,
    type: GizCapability,
    firmwareType: GizOTAFirmwareType,
    callback: GizOtaProgressCallback
  ): Promise<GizResult<any, any>> {
    // 注册监听
    const wapperCallback: GizOtaProgressEventCallback = ({ data }) => {
      callback(data)
    }
    this.otaEventCallbacks.push(wapperCallback)
    const data = await this.callbackWapper(
      (callback: GizCallback<any, any>) => {
        NativeModules.RNGizDeviceManagerModule.startUpgrade(
          {
            id,
            type,
            firmwareType,
          },
          callback
        )
      }
    )
    // OTA结束，销毁监听
    this.deleteCallBack(this.otaEventCallbacks, wapperCallback)
    return data
  }

  async provideWiFiCredentials(
    id: string,
    type: GizCapability,
    ssid: string,
    password: string,
    timeout: number,
    processHandler: GizProvideWiFiCredentialsCallback
  ): Promise<GizResult<any, any>> {
    const wapperCallback: GizProvideWiFiCredentialsCallback = (data) => {
      processHandler(data)
    }
    this.provideWiFiCredentialsCallbacks.push(wapperCallback)
    const data = await this.callbackWapper(
      (callback: GizCallback<any, any>) => {
        NativeModules.RNGizDeviceManagerModule.provideWiFiCredentials(
          {
            id,
            type,
            ssid,
            password,
            timeout,
          },
          callback
        )
      }
    )
    this.deleteCallBack(this.provideWiFiCredentialsCallbacks, wapperCallback)
    return data
  }

  async stopProvideWiFiCredentials(
    id: string,
    type: GizCapability
  ): Promise<GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.stopProvideWiFiCredentials(
        {
          id,
          type,
        },
        callback
      )
    })
  }

  async queryTimer(id: string, type: GizCapability): Promise<GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.queryTimer(
        {
          id,
          type,
        },
        callback
      )
    })
  }

  async deleteTimer(id: string, type: GizCapability, timerId: number): Promise<GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.deleteTimer(
        {
          id,
          type,
          timerId,
        },
        callback
      )
    })
  }

  async createTimer(id: string, type: GizCapability, data: GizDeviceLocalTimerParams): Promise<GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.createTimer(
        {
          id,
          type,
          data,
        },
        callback
      )
    })
  }

  async editTimer(id: string, type: GizCapability, data: GizDeviceLocalTimerParams): Promise<GizResult<any, any>> {
    return this.callbackWapper((callback: GizCallback<any, any>) => {
      NativeModules.RNGizDeviceManagerModule.editTimer(
        {
          id,
          type,
          data,
        },
        callback
      )
    })
  }
}

export default new RNGizDeviceManagerModule()

export { RNGizDeviceManagerModule }