/*
 * 设备二维码扫描页面
 * EZOpenSDK
 *
 * Created by junecheng on 2024/3/14.
 * Copyright (c) 2024年 Ezviz. All rights reserved.
 */
import { scanCore, scanBarcode, customScan } from '@kit.ScanKit'
import { vibrator } from '@kit.SensorServiceKit'
import { router, display } from '@kit.ArkUI'
import { BusinessError } from '@kit.BasicServicesKit'

import EZLog from '../../utils/EZLog'
import PermissionUtil from '../../utils/PermissionUtil'
import GlobalKit from '../../global/GlobalKit'
import RouterManager from '../../global/RouterManager/RouterManager'

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


@Entry
@Component
struct EZAddByQRCodePage {
  private readonly TAG: string = `${EZAddByQRCodePage.name}:`
  // 设置预览流高度，默认单位：vp
  @State cameraHeight: number = 200
  // 设置预览流宽度，默认单位：vp
  @State cameraWidth: number = 200
  @State isLightOn: boolean = false
  private mXComponentController: XComponentController = new XComponentController()
  @State userGrant: boolean = false // 是否已申请相机权限
  @State surfaceId: string = '' // xComponent组件生成id
  @State isFlashLightEnable: boolean = false // 是否开启了闪光灯
  @State isSensorLight: boolean = false // 记录当前环境亮暗状态
  @State cameraOffsetX: number = 0 // 设置预览流x轴方向偏移量，默认单位：vp
  @State cameraOffsetY: number = 0 // 设置预览流y轴方向偏移量，默认单位：vp
  @State zoomValue: number = 1 // 预览流缩放比例
  @State setZoomValue: number = 1 // 已设置的预览流缩放比例
  @State scaleValue: number = 1 // 屏幕缩放比
  @State pinchValue: number = 1 // 双指缩放比例
  @State displayHeight: number = 0 // 屏幕高度，单位vp
  @State displayWidth: number = 0 // 屏幕宽度，单位vp

  aboutToAppear() {

  }

  async onPageShow() {
    EZLog.info(this.TAG, 'onPageShow')
    await this.requestCameraPermission()
    let options: scanBarcode.ScanOptions = {
      scanTypes: [scanCore.ScanType.ALL],
      enableMultiMode: true,
      enableAlbum: true
    }
    this.setDisplay()
    customScan.init(options)
  }

  async onPageHide() {
    EZLog.info(this.TAG, 'onPageHide')
    // 页面消失或隐藏时，停止并释放相机流
    this.userGrant = false
    this.isFlashLightEnable = false
    this.isSensorLight = false
    try {
      //customScan.off('lightingFlash')
    } catch (error) {
      EZLog.info(this.TAG, `Failed to off lightingFlash. Code: ${error.code}, message: ${error.message}`)
    }
    await customScan.stop()
    // 自定义相机流释放接口
    customScan.release().then(() => {
      EZLog.info(this.TAG, 'Succeeded in releasing customScan by promise.')
    }).catch((error: BusinessError) => {
      EZLog.info(this.TAG,
        `Failed to release customScan by promise. Code: ${error.code}, message: ${error.message}`)
    })
  }

  // 用户申请相机权限
  async requestCameraPermission() {
    let p = await PermissionUtil.checkAndRequestPermission(getContext(), ['ohos.permission.CAMERA'])
    if (p.valueOf()) {
      // 用户授权，可以继续访问目标操作
      EZLog.info(this.TAG, 'Succeeded in getting permissions.')
      this.userGrant = true
    } else {
      console.error(`${this.TAG}:获取麦克风权限失败`)
      PermissionUtil.showGuideToSettingsDialog(getContext(), "打开设置",
        '由于二维码扫描需要使用到相机,请在设置页打开相机权限后进行使用')
    }
  }

  // 竖屏时获取屏幕尺寸，设置预览流全屏
  setDisplay() {
    // 默认竖屏
    let displayClass = display.getDefaultDisplaySync()
    this.displayHeight = px2vp(displayClass.height)
    this.displayWidth = px2vp(displayClass.width)
    let maxLen: number = Math.max(this.displayWidth, this.displayHeight)
    let minLen: number = Math.min(this.displayWidth, this.displayHeight)
    const RATIO: number = 16 / 9
    this.cameraHeight = maxLen
    this.cameraWidth = maxLen / RATIO
    this.cameraOffsetX = (minLen - this.cameraWidth) / 2
  }

  /**
   * 处理扫码结果
   * @param result
   */
  private async handleScanResult(result: Array<scanBarcode.ScanResult>) {
    if (result.length > 0) {
      console.debug(this.TAG, `showScanResult: ${JSON.stringify(result)}}`)
      this.drawScanQRCodeRect(result[0].scanCodeRect?.left, result[0].scanCodeRect?.top, result[0].scanCodeRect?.right,
        result[0].scanCodeRect?.bottom,)
      await this.onScanQRCodeSuccess(result[0].originalValue)
    }
  }

  @State scanQRCodeRectLeft: number | undefined = undefined
  @State scanQRCodeRectTop: number | undefined = undefined
  @State scanQRCodeRectRight: number | undefined = undefined
  @State scanQRCodeRectBottom: number | undefined = undefined

  private drawScanQRCodeRect(left: number | undefined, top: number | undefined, right: number | undefined,
    bottom: number | undefined) {
    console.debug(this.TAG, `drawScanQRCodeRect: ${left},${top},${right},${bottom}`)
    this.scanQRCodeRectLeft = left
    this.scanQRCodeRectRight = right
    this.scanQRCodeRectTop = top
    this.scanQRCodeRectBottom = bottom
  }

  /**
   * 扫码成功.处理二维码信息
   * @param resultString
   */
  private async onScanQRCodeSuccess(resultString: string) {
    if (!resultString) {
      console.error(this.TAG, "scan resultString is null")
      return
    }
    console.info(this.TAG, "scan resultString = " + resultString)

    try {
      // 触发马达振动
      vibrator.startVibration({
        type: 'time',
        duration: 200,
      }, {
        id: 0,
        usage: 'alarm'
      }, (error: BusinessError) => {
        if (error) {
          console.error(`Failed to start vibration. Code: ${error.code}, message: ${error.message}`)
          return
        }
        console.info('Succeed in starting vibration')
      })
    } catch (err) {
      let e: BusinessError = err as BusinessError
      console.error(`An unexpected error occurred. Code: ${e.code}, message: ${e.message}`)
    }

    // 初始化数据
    let mSerialNoStr = ""
    let mSerialVeryCodeStr = ""
    let deviceType = ""

    // 字符集合
    const newlineCharacterSet = ["\n\r", "\r\n", "\r", "\n"]
    let stringOrigin = resultString

    // 寻找第一次出现的位置
    let a = -1
    let firstLength = 1
    for (let string of newlineCharacterSet) {
      if (a === -1) {
        a = resultString.indexOf(string)
        if (a > stringOrigin.length - 3) {
          a = -1
        }
        if (a !== -1) {
          firstLength = string.length
        }
      }
    }

    // 扣去第一次出现回车的字符串后，剩余的是第二行以及以后的
    if (a !== -1) {
      resultString = resultString.substring(a + firstLength)
    }

    // 寻找最后一次出现的位置
    let b = -1
    for (let string of newlineCharacterSet) {
      if (b === -1) {
        b = resultString.indexOf(string)
        if (b !== -1) {
          mSerialNoStr = resultString.substring(0, b)
          firstLength = string.length
        }
      }
    }

    // 寻找遗失的验证码阶段
    if (mSerialNoStr && b !== -1 && (b + firstLength) <= resultString.length) {
      resultString = resultString.substring(b + firstLength)
    }

    // 再次寻找回车键最后一次出现的位置
    let c = -1
    for (let string of newlineCharacterSet) {
      if (c === -1) {
        c = resultString.indexOf(string)
        if (c !== -1) {
          mSerialVeryCodeStr = resultString.substring(0, c)
        }
      }
    }

    // 寻找CS-C2-21WPFR 判断是否支持wifi
    if (mSerialNoStr && c !== -1 && (c + firstLength) <= resultString.length) {
      resultString = resultString.substring(c + firstLength)
    }
    if (resultString && resultString.length > 0) {
      deviceType = resultString
    }

    if (b === -1) {
      mSerialNoStr = resultString
    }

    if (!mSerialNoStr) {
      mSerialNoStr = stringOrigin
    }
    console.info(this.TAG,
      `mSerialNoStr = ${mSerialNoStr}, mSerialVeryCodeStr = ${mSerialVeryCodeStr}, deviceType = ${deviceType}`)

    // 判断是不是9位
    this.isValidate(mSerialNoStr, mSerialVeryCodeStr, deviceType)
  }

  /**
   * 验证是否是萤石二维码,不是则重新扫码
   * @param mSerialNoStr
   * @param mSerialVeryCodeStr
   * @param deviceType
   */
  private isValidate(mSerialNoStr: string, mSerialVeryCodeStr: string, deviceType: string) {
    if (mSerialNoStr && mSerialNoStr.length == 9) {
      GlobalKit.getInstance().deviceSerialNo = mSerialNoStr
      GlobalKit.getInstance().deviceVerifyCode = mSerialVeryCodeStr
      GlobalKit.getInstance().deviceModel = ''
      RouterManager.pushUrl(RouterManager.deviceResultPage)
      // 获取到扫描结果后暂停相机流
      customScan.stop().then(() => {
        EZLog.info(this.TAG, 'Succeeded in stopping customScan by promise!')
      }).catch((error: BusinessError) => {
        EZLog.info(this.TAG,
          `Failed to stop customScan by promise. Code: ${error.code}, message: ${error.message}`)
      })

    } else {
      // 扫描的不是萤石二维码
      customScan.stop().then(() => {
        EZLog.info(this.TAG, 'Succeeded in stopping customScan by promise!')
        this.showQRCodeErrorDialog()

      }).catch((error: BusinessError) => {
        EZLog.info(this.TAG,
          `Failed to stop customScan by promise. Code: ${error.code}, message: ${error.message}`)
      })
      console.debug(this.TAG, "customScan restart")
    }
  }

  /**
   * 启动二维码扫描
   */
  private startScan() {
    this.drawScanQRCodeRect(undefined, undefined, undefined, undefined)
    // 获取XComponent组件的surfaceId
    this.surfaceId = this.mXComponentController.getXComponentSurfaceId()
    EZLog.info(this.TAG, `Succeeded in getting surfaceId: ${this.surfaceId}`)
    let viewControl: customScan.ViewControl = {
      width: this.cameraWidth,
      height: this.cameraHeight,
      surfaceId: this.surfaceId
    }
    customScan.start(viewControl)
      .then(async (result: Array<scanBarcode.ScanResult>) => {
        // 处理扫码结果
        this.handleScanResult(result)
      })
  }

  /**
   * 显示错误二维码提醒
   */
  private showQRCodeErrorDialog() {
    AlertDialog.show(
      {
        title: '警告',
        message: '请扫描萤石设备机身或说明书上的二维码',
        autoCancel: true,
        alignment: DialogAlignment.Center,
        offset: { dx: 0, dy: -20 },
        gridCount: 3,
        confirm: {
          value: '确定',
          action: () => {
            this.startScan()
          }
        },
        cancel: () => {
          this.startScan()
        }
      }
    )
  }

  /**
   * 设置闪光灯
   */
  private setFlashLight() {
    try {
      this.isLightOn = customScan.getFlashLightStatus()
      // 根据当前闪光灯状态，选择打开或关闭闪关灯
      if (this.isLightOn) {
        customScan.closeFlashLight()
      } else {
        customScan.openFlashLight()
      }
    } catch (e) {
      console.error(this.TAG, `setFlashLight error:${e}`)
    }
  }

  // 自定义扫码界面的顶部返回按钮和扫码提示
  @Builder
  TopTool() {
    Column() {
      Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
        Text('返回')
          .onClick(async () => {
            router.back()
          })
      }.padding({ left: 24, right: 24, top: 40 })

      Column() {
        Text('扫描二维码/条形码')
        Text('对准二维码/条形码，即可自动扫描')
      }.margin({ left: 24, right: 24, top: 24 })
    }
    .height(146)
    .width('100%')
  }

  //用来配置CanvasRenderingContext2D对象的参数，包括是否开启抗锯齿，true表明开启抗锯齿。
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  //用来创建CanvasRenderingContext2D对象，通过在canvas中调用CanvasRenderingContext2D对象来绘制。
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Stack({ alignContent: Alignment.Top }) {
      if (this.userGrant) {
        Column() {
          XComponent({
            id: 'componentId',
            type: 'surface',
            controller: this.mXComponentController
          })
            .onLoad(async () => {
              EZLog.info(this.TAG, 'Succeeded in loading, onLoad is called.')
              this.startScan()
            })// XComponent宽、高，默认单位vp，支持px、lpx、vp
            .width(this.cameraWidth)
            .height(this.cameraHeight)
            .position({ x: this.cameraOffsetX, y: this.cameraOffsetY })
        }
        .height('100%')
        .width('100%')

        if (this.scanQRCodeRectLeft && this.scanQRCodeRectTop && this.scanQRCodeRectRight &&
        this.scanQRCodeRectBottom) {
          Row() {
          }
          .width(20)
          .height(20)
          .markAnchor({ x: 50, y: 15 })
          .backgroundColor(Color.Orange)
          .borderRadius(10)
          .position({
            x: (this.scanQRCodeRectLeft + this.scanQRCodeRectRight) / 2,
            y: (this.scanQRCodeRectTop + this.scanQRCodeRectBottom) / 2
          })
        }

      }
      this.ScanerBorder()

      NavigationView({
        showRightBtn: true,
        title: $r('app.string.ad_scan_qr_title'),
        rightNavTitle: $r('app.string.ad_input_manual'),
        rightNavClick: () => {
          RouterManager.pushUrl(RouterManager.inputSerialPage)
        }
      })

    }
    // 建议相机流设置为全屏
    .width('100%')
    .height('100%')

  }

  @Builder
  ScanerBorder() {
    Column() {
      Column() {

      }
      .width(200)
      .height(200)
      .align(Alignment.Center)
      .borderWidth(1)
      .borderColor(Color.White)

      Text($r('app.string.ad_scan_qr_hint'))
        .fontColor(Color.White)
        .fontSize(14)
        .align(Alignment.Center)
        .margin({ top: 20 })

      Image(this.isLightOn ? $r('app.media.turn_on') : $r('app.media.turn_off'))
        .width(50).height(50)
        .margin({ top: 40 })
        .onClick(() => {
          this.setFlashLight()
        })
    }.width('100%').height('100%')
    //.backgroundColor(Color.Gray)
    .justifyContent(FlexAlign.Center)
  }
}