<template>
  <view>
    <view>
      <!-- #ifdef MP-WEIXIN -->
      <iot-p2p-player-with-mjpg
        v-if="deviceInfo"
        id="playerRef"
        :deviceInfo="deviceInfo"
        :xp2pInfo="xp2pInfo"
        :rotate="90"
        :muted="isMute"
        mode="RTC"
        :acceptPlayerEvents="true"
        soundMode="speaker"
        sceneType="live"
        :streamQuality="range[index].value"
        :minCache="0.2"
        :maxCache="0.8"
        :fill="true"
        orientation="horizontal"
        @playsuccess="handlePlaySuccess"
      >
      </iot-p2p-player-with-mjpg>
      <!-- #endif -->

      <!-- #ifdef APP-PLUS -->
      <video
        :key="videoKey"
        autoplay
        id="playerRef"
        v-if="url"
        :muted="isMute"
        :src="urlPrefix"
        :advanced="advancedOptions"
        object-fit="cover"
        class="w-[100vw] h-[100vh]"
        :is-live="true"
        :controls="false"
        :show-progress="false"
        :show-fullscreen-btn="false"
        :show-play-btn="false"
        :enable-progress-gesture="false"
        :vslide-gesture="true"
      />
      <!-- #endif -->
    </view>
    <image
      v-if="!isVideoLoaded"
      src="https://oss-lock.xhjcn.ltd/mp/background_monitor.png"
      class="w-full h-full absolute top-0 left-0"
    ></image>

    <cover-view
      v-if="(isApp || buttonInfo) && isVideoLoaded"
      :style="{
        top: isApp ? '60px' : buttonInfo.bottom + 15 + 'px'
      }"
      class="bg-[rgba(0,0,0,0.35)] rounded-full px-4 py-1.5 fixed right-32"
    >
      <cover-view class="text-white text-xs" @click="showQualitySelector">
        {{ range[index].name }}
      </cover-view>
    </cover-view>

    <!-- #ifdef MP-WEIXIN -->
    <iot-p2p-voice
      v-if="deviceInfo"
      id="voiceComponent"
      :deviceInfo="deviceInfo"
      :xp2pInfo="xp2pInfo"
      voiceType="Pusher"
    >
    </iot-p2p-voice>
    <!-- #endif -->

    <cover-view
      v-if="isVideoLoaded"
      class="fixed bottom-[calc(32rpx+env(safe-area-inset-bottom))] bg-[rgba(0,0,0,0.3)] rounded-xl p-4 shadow-lg left-1/2 -translate-x-1/2 w-622"
    >
      <cover-view class="flex items-center justify-around mx-15">
        <cover-view class="relative">
          <cover-image
            v-show="isMute"
            src="https://oss-lock.xhjcn.ltd/mp/icon_mute.png"
            :class="isApp ? 'size-48' : 'size-48 p-2'"
          ></cover-image>
          <cover-image
            v-show="!isMute"
            src="https://oss-lock.xhjcn.ltd/mp/icon_not_mute.png"
            :class="isApp ? 'size-48' : 'size-48 p-2'"
          ></cover-image>
          <cover-view
            @click="toggleMute"
            class="absolute top-0 left-0 w-full h-full size-48 p-2"
          ></cover-view>
        </cover-view>
        <cover-view class="relative">
          <cover-image
            src="https://oss-lock.xhjcn.ltd/mp/icon_screenshot.png"
            :class="isApp ? 'size-48' : 'size-48 p-2'"
          ></cover-image>
          <cover-view
            @click="handleScreenshot"
            class="absolute top-0 left-0 w-full h-full"
          ></cover-view>
        </cover-view>
      </cover-view>
      <cover-view class="flex items-center justify-between text-white mt-2 px-10">
        <cover-view class="flex flex-col items-center">
          <cover-view
            class="bg-white w-80 h-80 rounded-full flex items-center justify-center relative"
          >
            <cover-image
              :src="
                isVoice
                  ? 'https://oss-lock.xhjcn.ltd/mp/icon_microphone.png'
                  : 'https://oss-lock.xhjcn.ltd/mp/icon_no_microphone.png'
              "
              class="w-55 h-55"
            ></cover-image>
            <cover-view
              @click="toggleVoice"
              class="absolute top-0 left-0 w-full h-full"
            ></cover-view>
          </cover-view>
          <cover-view class="mt-2 text-center whitespace-nowrap text-xs">{{
            isVoice ? '点击停止' : '点击说话'
          }}</cover-view>
        </cover-view>
        <cover-view class="flex flex-col items-center">
          <cover-view
            class="bg-[#eb292b] w-80 h-80 rounded-full flex items-center justify-center relative"
          >
            <cover-image
              src="https://oss-lock.xhjcn.ltd/mp/icon_hang_up.png"
              class="w-60 h-60"
            ></cover-image>
            <cover-view
              @click="handleHangUp"
              class="absolute top-0 left-0 w-full h-full"
            ></cover-view>
          </cover-view>
          <cover-view class="mt-2 text-center whitespace-nowrap text-xs">挂断</cover-view>
        </cover-view>
        <cover-view class="flex flex-col items-center">
          <cover-view
            class="bg-[#63b8af] w-80 h-80 rounded-full flex items-center justify-center relative"
          >
            <cover-image
              src="https://oss-lock.xhjcn.ltd/mp/icon_lock_white.png"
              class="w-60 h-60"
            ></cover-image>
            <cover-view
              @click="handleLock"
              class="absolute top-0 left-0 w-full h-full"
            ></cover-view>
          </cover-view>
          <cover-view class="mt-2 text-center whitespace-nowrap text-xs">开锁</cover-view>
        </cover-view>
      </cover-view>
    </cover-view>
    <view
      v-if="!isVideoLoaded"
      class="fixed bottom-[calc(48rpx+env(safe-area-inset-bottom))] w-full flex justify-center"
    >
      <up-loading-icon
        size="70rpx"
        :vertical="true"
        textSize="28rpx"
        text="连接中"
        mode="circle"
      ></up-loading-icon>
    </view>
  </view>
</template>

<script setup>
  import { onMounted, ref, computed } from 'vue'
  import { onUnload } from '@dcloudio/uni-app'
  import { useBluetoothStore } from '@/stores/bluetooth'
  import { useBasicStore } from '@/stores/basic'
  import { useUserStore } from '@/stores/user'
  import { passthrough } from '@/api/sdk'
  import { getLockNetTokenRequest } from '@/api/lock'
  // #ifdef MP-WEIXIN
  import * as A from './exportForXp2pPlugin'
  import * as B from './exportForPlayerPlugin'
  // #endif

  // #ifdef APP-PLUS
  import {
    startServiceFunction,
    stopServiceFunction,
    runSendServiceFunction,
    stopSendServiceFunction,
    dataSendFunction
  } from '@/uni_modules/xhj-tencent-xp2p'
  import { initAudio, onStartRecord, stopRecord, releaseRecord } from '@/uni_modules/xhj-record'
  // #endif

  const $bluetooth = useBluetoothStore()
  const $basic = useBasicStore()
  const $user = useUserStore()
  const buttonInfo = ref(null)

  const isApp = ref(false)

  const onlineToken = ref('0')
  const lockId = ref()
  const time = ref(0)
  const pending = ref(false)

  const index = ref(1)
  const range = ref([
    { name: '标清', value: 'standard' },
    { name: '高清', value: 'high' },
    { name: '超清', value: 'super' }
  ])

  const deviceInfo = ref()
  const xp2pInfo = ref()
  const url = ref()
  const isVoice = ref(false)
  const isMute = ref(false)
  const isVideoLoaded = ref(false)
  const videoKey = ref(Date.now())
  const cleanupCalled = ref(false)

  const advancedOptions = ref([
    {
      key: 'videotoolbox',
      value: 0,
      type: 'player'
    },
    {
      key: 'framedrop',
      value: 5,
      type: 'player'
    },
    {
      key: 'skip_loop_filter',
      value: 48,
      type: 'player'
    }
  ])

  const urlPrefix = computed(() => {
    const data =
      url.value + `ipc.flv?action=live&channel=0&quality=${range.value[index.value].value}`
    return data
  })

  const cleanupResources = () => {
    if (cleanupCalled.value) return
    cleanupCalled.value = true

    // #ifdef APP-PLUS
    // 停止录音
    url.value = null
    isVideoLoaded.value = false
    if (isVoice.value) {
      stopRecord()
    }
    releaseRecord()
    if (deviceInfo.value) {
      stopSendServiceFunction(`${deviceInfo.value.productId}/${deviceInfo.value.deviceName}`)
      stopServiceFunction(`${deviceInfo.value.productId}/${deviceInfo.value.deviceName}`)
    }
    // #endif
    // #ifdef MP-WEIXIN
    const page = getCurrentPages().pop()
    if (page) {
      const player = page.selectComponent('#playerRef')
      if (player && player.stopAll) {
        player.stopAll()
      }
    }
    // #endif
  }

  onMounted(async () => {
    // #ifdef APP-PLUS
    initAudio()
    isApp.value = true
    // #endif

    // #ifdef MP-WEIXIN
    console.log(A, B)
    // #endif
    buttonInfo.value = await $basic.getButtonInfo()

    const { code, data, message } = await passthrough({
      request_method: 'GET',
      request_uri: '/api/v1/tencentYun/getDeviceDetailData',
      post_args: {
        lockId: $bluetooth.currentLockInfo.lockId
      }
    })

    // #ifdef MP-WEIXIN
    if (code === 0) {
      deviceInfo.value = {
        deviceId: `${data.productId}/${data.deviceName}`,
        productId: data.productId,
        deviceName: data.deviceName
      }
      xp2pInfo.value = data.xp2pInfo
    } else {
      $basic.backAndToast(message)
    }
    await getServeTime()
    // #endif
    // #ifdef APP-PLUS
    if (code === 0) {
      deviceInfo.value = data
      const params = {
        appKey: 'aanuJXFtISXFYVVsd',
        appSecret: 'SsnOMHJUcazCvpULSVWY',
        productId: deviceInfo.value.productId,
        deviceName: deviceInfo.value.deviceName,
        xp2pInfo: deviceInfo.value.xp2pInfo
      }

      const result = await startServiceFunction(
        params.appKey,
        params.appSecret,
        params.productId,
        params.deviceName,
        params.xp2pInfo
      )
      console.log('初始化SDK结果：', result)
      if (result?.code === 0) {
        handlePlaySuccess()
        setTimeout(() => {
          url.value = result.data.url
          runSendServiceFunction(
            `${deviceInfo.value.productId}/${deviceInfo.value.deviceName}`,
            'channel=0',
            false
          )
        }, 0)
      } else {
        $basic.backAndToast(message)
      }
    } else {
      $basic.backAndToast(message)
    }
    // #endif
  })

  onUnload(() => {
    cleanupResources()
  })

  const showQualitySelector = () => {
    uni.showActionSheet({
      itemList: range.value.map(item => item.name),
      success: res => {
        const value = res.tapIndex
        if (index.value === value) {
          return
        }
        index.value = value
        videoKey.value = Date.now()
      }
    })
  }

  const handleScreenshot = () => {
    // #ifdef MP-WEIXIN
    const page = getCurrentPages().pop()
    const player = page.selectComponent('#playerRef')

    player.snapshot().then(res => {
      uni.saveImageToPhotosAlbum({
        filePath: res.tempImagePath,
        success: () => {
          uni.showToast({
            title: '截图已保存到相册',
            icon: 'none'
          })
        },
        fail: () => {
          uni.showToast({
            title: '保存失败',
            icon: 'none'
          })
        }
      })
    })
    // #endif
    // #ifdef APP-PLUS
    uni.showModal({
      title: '提示',
      content:
        '由于技术限制，APP端无法直接截取视频画面。请使用手机系统截图功能：\n\niOS：同时按下电源键+音量上键\nAndroid：同时按下电源键+音量下键',
      confirmText: '我知道了',
      showCancel: false
    })
    // #endif
  }

  const handleHangUp = () => {
    cleanupResources()
    uni.navigateBack()
  }

  const handleLock = () => {
    uni.showModal({
      title: '提示',
      content: '是否确认开锁？',
      success: res => {
        if (res.confirm) {
          openDoorOperate()
        }
      }
    })
  }

  const getServeTime = async () => {
    const { code, data } = await $bluetooth.updateServerTimestamp()
    if (code === 0) {
      time.value = parseInt((data.date - new Date().getTime()) / 1000, 10)
    }
  }

  const openDoorOperate = async () => {
    const timestamp = new Date().getTime()
    if (pending.value) {
      return
    }

    const netWork = await $basic.getNetworkType()
    if (!netWork) {
      return
    }

    if ($bluetooth.currentLockInfo.appUnlockOnline) {
      const result = await getNetToken()
      if (!result) {
        pending.value = false
        return
      }
    }

    uni.showLoading({
      title: '开锁中'
    })
    uni.vibrateLong()
    pending.value = true
    const openMode = $bluetooth.currentLockInfo.appUnlockOnline ? 1 : 0

    const { code } = await $bluetooth.openDoor({
      name: $bluetooth.currentLockInfo.lockName,
      uid: $user.userInfo.uid.toString(),
      openMode,
      openTime: parseInt(new Date().getTime() / 1000, 10) + time.value,
      onlineToken: onlineToken.value
    })

    $bluetooth
      .syncRecord({
        keyId: $bluetooth.keyId.toString(),
        uid: $user.userInfo.uid.toString()
      })
      .then(() => {
        $bluetooth.closeBluetoothConnection()
      })

    // #ifdef MP-WEIXIN
    uni.reportEvent('open_door', {
      result: code,
      duration: new Date().getTime() - timestamp
    })
    // #endif

    if (code === 0) {
      uni.showToast({
        title: `开门成功`,
        icon: 'none'
      })
    } else if (code === 7) {
      uni.showToast({
        title: `钥匙过期`,
        icon: 'none'
      })
    } else if (code === 13) {
      uni.showToast({
        title: `钥匙当前不可用`,
        icon: 'none'
      })
    } else if (code === -1) {
      uni.showToast({
        title: `开锁失败`,
        icon: 'none'
      })
    }
    uni.hideLoading()
    pending.value = false
  }

  const getNetToken = async () => {
    const { code, data, message } = await getLockNetTokenRequest({
      lockId: lockId.value
    })
    if (code === 0) {
      onlineToken.value = data.token
      return true
    }
    uni.showToast({
      title: message,
      icon: 'none'
    })
    return false
  }

  const toggleVoice = () => {
    // #ifdef MP-WEIXIN
    if (isVoice.value) {
      isVoice.value = false
      const page = getCurrentPages().pop()
      const voice = page.selectComponent('#voiceComponent')
      if (voice) {
        voice.stopVoice()
      }
    } else {
      uni.vibrateLong()
      isVoice.value = true
      const page = getCurrentPages().pop()
      const voice = page.selectComponent('#voiceComponent')
      if (voice) {
        voice.startVoice()
      }
    }
    // #endif
    // #ifdef APP-PLUS
    if (isVoice.value) {
      isVoice.value = false
      stopRecord()
    } else {
      uni.vibrateLong()
      isVoice.value = true
      onStartRecord(callback)
    }
    // #endif
  }

  const callback = audioData => {
    dataSendFunction(`${deviceInfo.value.productId}/${deviceInfo.value.deviceName}`, audioData)
  }

  const handlePlaySuccess = () => {
    isVideoLoaded.value = true
  }

  const toggleMute = () => {
    isMute.value = !isMute.value
  }
</script>

<style lang="scss" scoped>
  :deep(.mjpg-player--iot-player) {
    height: 100vh !important;
  }
</style>
