/*
 * AP配网页面
 * EZOpenSDK
 *
 * Created by junecheng on 2024/5/13.
 * Copyright (c) 2024年 Ezviz. All rights reserved.
 */

import pasteboard from '@ohos.pasteboard'
import wifiManager from '@ohos.wifiManager'
import { common, Want } from '@kit.AbilityKit'
import { connection } from '@kit.NetworkKit'
import { BusinessError } from '@kit.BasicServicesKit'
import { EZOpenSDK, EZWifiConfigStatus } from '@ohos/EZOpenSDK'

import OhosDeviceInfoUtil from '../../utils/OhosDeviceInfoUtil'
import EZToastUtil from '../../utils/EZToastUtil'
import EZLog from '../../utils/EZLog'
import GlobalKit from '../../global/GlobalKit'
import RouterManager from '../../global/RouterManager/RouterManager'

import { NavigationView } from '../../global/view/NavigationView'

export default class EZWiFiInfoRouterParam {
  ssid: string = ''
  password: string = ''
  isApConfig: boolean = true

  constructor(ssid: string, password: string, isApConfig: boolean) {
    this.ssid = ssid
    this.password = password
    this.isApConfig = isApConfig
  }
}

@Entry
@Component
struct EZAPWiFiConfigPage {
  private readonly TAG: string = `${EZAPWiFiConfigPage.name}:`
  routerParams: EZWiFiInfoRouterParam = RouterManager.getParams() as EZWiFiInfoRouterParam
  netConnectionWlan: connection.NetConnection | undefined = undefined
  // 设备热点名称
  @State devicWifiName: string = ''
  // 设备热点密码
  @State devicWifiPwd: string = ''
  // 是否显示'添加设备'按钮
  @State showAddBtn: boolean = false
  @State showLoadingProgress: boolean = false
  // 尝试过自动连接设备热点失败
  @State connect2DeviceHotspotAutoFailed: boolean = false
  // 网络判断定时器ID，判断设备连接的WiFi与用户输入的WiFi是否一致
  netMonitorTimerIntervalID: number = 0

  // ------------------------ 生命周期 ------------------------

  aboutToAppear() {
    this.devicWifiName = `${GlobalKit.getInstance().WiFiConfigPrefix}_${GlobalKit.getInstance().deviceSerialNo}`
    this.devicWifiPwd = `${GlobalKit.getInstance().WiFiConfigPrefix}_${GlobalKit.getInstance().deviceVerifyCode}`

    this.connect2DeviceHotspot()
  }

  aboutToDisappear() {
    if (this.netConnectionWlan) {
      this.netConnectionWlan.unregister((error: BusinessError) => {
        EZLog.info(this.TAG, `netConnectionWlan.unregister: ${JSON.stringify(error)}`)
      })
    }
  }

  onPageShow() {
    if (this.connect2DeviceHotspotAutoFailed) {
      clearInterval(this.netMonitorTimerIntervalID)

      this.startConfigWifi()
      this.netMonitorTimerIntervalID = setInterval(() => {
        this.startConfigWifi()
      }, 5000)
    }
  }

  onPageHide() {
    if (this.connect2DeviceHotspotAutoFailed) {
      clearInterval(this.netMonitorTimerIntervalID)
      this.stopConfigWifi()
    }
  }

  // ------------------------ Actions ------------------------

  /** 复制密码Action */
  copyPwdAction = () => {
    let pasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, this.devicWifiPwd)
    const systemPasteboard = pasteboard.getSystemPasteboard()
    systemPasteboard.setData(pasteData) // 将数据放入剪切板
    EZToastUtil.showToast('done')
  }
  /** 跳转系统设置Action */
  toSystemSettingAction = () => {
    let context = getContext(this) as common.UIAbilityContext
    OhosDeviceInfoUtil.toSystemWiFiSettingPage(context)
  }
  /** 添加设备Action */
  addDeviceAction = () => {
    RouterManager.pushUrl(RouterManager.apConfigResultPage)
  }

  // ------------------------ 网络请求 ------------------------

  // ------------------------ 自定义方法 ------------------------

  /** 连接设备热点 */
  async connect2DeviceHotspot() {
    this.showLoadingProgress = true
    try {
      let config: wifiManager.WifiDeviceConfig = {
        ssid: this.devicWifiName,
        preSharedKey: this.devicWifiPwd,
        securityType: wifiManager.WifiSecurityType.WIFI_SEC_TYPE_PSK
      }
      // 通过wifiManager.addCandidateConfig获取注册WLAN的networkId
      let networkId: number = await wifiManager.addCandidateConfig(config)
      EZLog.info(this.TAG, "networkId: " + JSON.stringify(networkId))
      this.netConnectionWlan = connection.createNetConnection({
        netCapabilities: {
          bearerTypes: [connection.NetBearType.BEARER_WIFI]
        },
        bearerPrivateIdentifier: `${networkId}`
      }, 10*1000)
      this.netConnectionWlan.register((error: BusinessError) => {
        EZLog.info(this.TAG, `netConnectionWlan.register: ${JSON.stringify(error)}`)
      })
      this.netConnectionWlan.on('netAvailable', (error) => {
        this.showLoadingProgress = false
        EZLog.info(this.TAG, `netConnectionWlan.on netAvailable: ${JSON.stringify(error)}`)
        EZToastUtil.showToast('ap连接完成：' + this.devicWifiName + JSON.stringify(error))
        this.startConfigWifi()
      })

    } catch (error) {
      EZLog.error(this.TAG, `failed: ${JSON.stringify(error)}`)
      this.showLoadingProgress = false
      this.connect2DeviceHotspotAutoFailed = true
      EZToastUtil.showToast('连接失败，需手动去设置页面连接设备热点！')
    }

    // 当前鸿蒙不支持通过代码方式连接指定wifi，只能自己手动去设置页面连接设备热点！
    // setTimeout(() => {
    //   EZToastUtil.showToast('当前鸿蒙不支持通过代码方式连接指定wifi，需手动去设置页面连接设备热点！')
    //   this.connect2DeviceHotspotAutoFailed = true
    // }, 1000)
  }

  async startConfigWifi() {
    // 网络不一致，拦截。必须连接上设备热点后才能发起配网！
    let wifiInfo = await wifiManager.getLinkedInfo()
    if (!wifiInfo || wifiInfo.ssid != this.devicWifiName) {
      return
    }

    clearInterval(this.netMonitorTimerIntervalID)
    this.showLoadingProgress = true
    this.showAddBtn = false
    if (this.routerParams.isApConfig) {
      EZOpenSDK.startAPConfigWifi(this.routerParams.ssid, this.routerParams.password, GlobalKit.getInstance()
        .deviceSerialNo, GlobalKit.getInstance().deviceVerifyCode, (status, deviceSerial) => {
        switch (status) {
          case EZWifiConfigStatus.DEVICE_WIFI_SENT_SUCCESS: // 向设备发送WiFi信息成功
            // 等待设备配网
            EZLog.info(this.TAG, '向设备发送WiFi信息成功')
            EZToastUtil.showToast('向设备发送WiFi信息成功')
            break
          case EZWifiConfigStatus.DEVICE_WIFI_SENT_FAILED: // 向设备发送WiFi信息失败
            // 配网失败，可以重试
            EZLog.info(this.TAG, '配网失败，请稍后重试')
            EZToastUtil.showToast('配网失败，请稍后重试')
            this.showLoadingProgress = false
            break
          case EZWifiConfigStatus.DEVICE_PLATFORM_REGISTED: // 设备注册平台成功
            // TODO 将设备添加到自己账号下
            EZLog.info(this.TAG, '设备注册平台成功')
            EZToastUtil.showToast('设备注册平台成功')
            this.showLoadingProgress = false
            this.showAddBtn = true
            break
          case EZWifiConfigStatus.DEVICE_PLATFORM_REGIST_FAILED: // 设备注册平台失败
            // TODO 可以自行开启新一轮轮询
            EZLog.info(this.TAG, '设备注册平台失败')
            EZToastUtil.showToast('设备注册平台失败')
            this.showLoadingProgress = false
            break
        }
      })
    }
  }

  stopConfigWifi() {
    if (this.routerParams.isApConfig) {
      EZOpenSDK.stopAPConfigWifi()
    }
  }

  // ------------------------ UI ------------------------

  build() {
    Column() {
      NavigationView({
        title: $r('app.string.wifi_mode_wifi_connect')
      })
      Stack({ alignContent: Alignment.Center }) {
        Image($r('app.media.wifi_bg'))
        Column() {
          Column() {
            Text($r('app.string.wifi_mode_wifi_connect_tip')).fontSize(14)
            // Step 1
            Row() {
              Text('1').fontSize(30)
              Column() {
                Text($r('app.string.wifi_step_one_msg')).fontSize(14)
                Row() {
                  Text($r('app.string.wifi_step_one_name')).fontSize(14)
                  Text(this.devicWifiName).fontSize(15).fontColor(Color.Orange)
                }.margin({ top: 8 })

                Row() {
                  Text($r('app.string.wifi_step_one_pwd')).fontSize(14)
                  Text(this.devicWifiPwd).fontSize(15).fontColor(Color.Orange)
                }.margin({ top: 4 })
              }.layoutWeight(1).alignItems(HorizontalAlign.Start).margin({ left: 20, top: 1 })
            }.margin({ top: 10 }).alignItems(VerticalAlign.Top)

            Button($r('app.string.wifi_step_one_copy'))
              .backgroundColor(Color.Orange)
              .width(130)
              .height(30)
              .margin({ top: 10, bottom: 15 })
              .fontSize(14)
              .onClick(this.copyPwdAction)
            Divider()
            // Step 2
            Row() {
              Text('2').fontSize(30)
              Column() {
                Text($r('app.string.wifi_step_two_msg', `${this.devicWifiName}`)).fontSize(14)
              }.layoutWeight(1).alignItems(HorizontalAlign.Start).margin({ left: 20, top: 1 })
            }.margin({ top: 10 }).alignItems(VerticalAlign.Top)

            Button($r('app.string.wifi_step_two_setting'))
              .backgroundColor(Color.Orange)
              .width(130)
              .height(30)
              .margin({ top: 10, bottom: 15 })
              .fontSize(14)
              .onClick(this.toSystemSettingAction)
            Divider()
            // Step 3
            Row() {
              Text('3').fontSize(30)
              Column() {
                Text($r('app.string.wifi_step_three_msg')).fontSize(14)
              }.layoutWeight(1).alignItems(HorizontalAlign.Start).margin({ left: 20, top: 1 })
            }.margin({ top: 10 }).alignItems(VerticalAlign.Top)

            // note
            Text($r('app.string.wifi_mode_wifi_connect_note'))
              .fontSize(14)
              .fontColor(Color.Red)
              .layoutWeight(1)
              .baselineOffset(500)
              .margin({ top: 35 })
          }
          .layoutWeight(1)
          .margin({
            left: 16,
            right: 16,
            top: 20,
            bottom: 20
          })
          .visibility(this.connect2DeviceHotspotAutoFailed ? Visibility.Visible : Visibility.Hidden)

          // 添加设备
          Column() {
            Button($r('app.string.wifi_ap_add_device_title'))
              .backgroundColor(Color.Orange)
              .width(130)
              .height(30)
              .fontSize(14)
              .onClick(this.addDeviceAction)
            // add tips
            Text($r('app.string.wifi_mode_wifi_connect_add_tip')).fontSize(14).fontColor(Color.Red).margin({ top: 10 })
          }.visibility(this.showAddBtn ? Visibility.Visible : Visibility.Hidden)
        }

        LoadingProgress().width(40).height(40)
          .visibility(this.showLoadingProgress ? Visibility.Visible : Visibility.Hidden)
      }.layoutWeight(1)
    }
  }
}