<script lang="ts" setup>
import userService from '@/api/service/userService'
import utils from '@/utils/utils'
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
import { nextTick, onMounted, reactive, ref, toRaw, watch, watchEffect } from 'vue'
import VueDragResize from 'vue-drag-resize'

const props = defineProps({
  visible: {
    type: Boolean,
    default: false
  },
  url: {
    type: String,
    default: ''
  },
  cropArea: {
    type: Array,
    default: () => []
  }
})

watch(
  () => [props.cropArea, props.visible],
  (newVal, oldVal) => {
    console.log('cropArea', newVal[0])
    if (!props.visible) {
      showCropBox.value = false
      // handleInitCropArea()
    }
  }
)
const emit = defineEmits(['update:visible', 'crop'])
const isVisible = ref(props.visible)
const loginFormRef = ref<FormInstance>()
const title = ref('裁剪视频')
const isMobile = ref(utils.checkIsMobile())
const cropBoxRef = ref<any>()
const backgroundVideoRef = ref<HTMLVideoElement>()
const croppedCanvasRef = ref<HTMLCanvasElement>()
const rectData = ref({
  left: 0,
  top: 0,
  height: 100,
  width: 100
})
const showCropBox = ref(false)
const cropPreviewBox = ref({
  width: 0,
  height: 0
})
onMounted(() => {
  console.log('mounted')
})
watch(
  () => props.visible,
  (val) => {
    console.log('visible', val)
    isVisible.value = val
  }
)
const onCancel = () => {
  console.log('cancel')
  handleClose()
}

const onConfirm = async () => {
  const video = backgroundVideoRef.value

  // 计算裁剪框在视频中的位置
  const scaleX = video!.videoWidth / video!.clientWidth
  const scaleY = video!.videoHeight / video!.clientHeight
  const cropData = {
    x: Math.round(rectData.value.left * scaleX),
    y: Math.round(rectData.value.top * scaleY),
    width: Math.round(rectData.value.width * scaleX),
    height: Math.round(rectData.value.height * scaleY)
  }
  if (cropData.width <= 0 || cropData.height <= 0) {
    ElMessage.error('裁剪框尺寸不正确')
    return
  }
  if (cropData.x < 0) {
    cropData.x = 0
  }
  if (cropData.y < 0) {
    cropData.y = 0
  }
  if (cropData.width > video!.videoWidth) {
    cropData.width = video!.videoWidth
  }
  if (cropData.x + cropData.width > video!.videoWidth) {
    cropData.width = video!.videoWidth - cropData.x
  }
  if (cropData.height > video!.videoHeight) {
    cropData.height = video!.videoHeight
  }
  if (cropData.y + cropData.height > video!.videoHeight) {
    cropData.height = video!.videoHeight - cropData.y
  }

  console.log(rectData.value, scaleX, scaleY)

  console.log('cropData', cropData)
  // 转换为 左上角坐标 右下角坐标 例如：[[100,200], [300,400]]
  const cropAreaData = [
    [cropData.x, cropData.y],
    [cropData.x + cropData.width, cropData.y + cropData.height]
  ]
  emit('crop', cropAreaData)
  handleClose()
}

const handleClose = () => {
  console.log('handleClose')
  emit('update:visible', false)
}

const cropVideoFrame = () => {
  try {
    const cropBox = cropBoxRef.value.$el.getBoundingClientRect()
    const video = backgroundVideoRef.value
    const canvas = croppedCanvasRef.value
    if (!video || !canvas) {
      return
    }
    const ctx = canvas!.getContext('2d')

    const scaleX = video!.videoWidth / video!.clientWidth
    const scaleY = video!.videoHeight / video!.clientHeight

    canvas!.width = cropBox.width
    canvas!.height = cropBox.height

    ctx!.drawImage(
      video!,
      (cropBox.left - video!.getBoundingClientRect().left) * scaleX,
      (cropBox.top - video!.getBoundingClientRect().top) * scaleY,
      cropBox.width * scaleX,
      cropBox.height * scaleY,
      0,
      0,
      cropBox.width,
      cropBox.height
    )

    // 递归调用，实现每一帧都更新
    requestAnimationFrame(cropVideoFrame)
  } catch (error) {
    console.log(error)
  }
}

const resize = (newRect: any) => {
  // console.log(newRect)
  rectData.value = newRect
}

const onVideoLoaded = (val: any) => {
  console.log('onVideoLoaded', val)
  const video = backgroundVideoRef.value
  cropPreviewBox.value = {
    width: video?.clientWidth || 0,
    height: video?.clientHeight || 0
  }
  showCropBox.value = true
  const cropArea: any = toRaw(props.cropArea)

  if (cropArea.length > 0) {
    const scaleX = cropPreviewBox.value.width / video!.videoWidth
    const scaleY = cropPreviewBox.value.height / video!.videoHeight
    console.log('cropArea', cropArea, scaleX, scaleY)

    const left = Math.round(cropArea[0][0] * scaleX)
    const top = Math.round(cropArea[0][1] * scaleY)
    const width = Math.round((cropArea[1][0] - cropArea[0][0]) * scaleX)
    const height = Math.round((cropArea[1][1] - cropArea[0][1]) * scaleY)
    console.log('init cropArea', left, top, width, height)

    rectData.value = {
      left,
      top,
      width,
      height
    }
  } else {
    // 全部显示
    rectData.value = {
      left: 0,
      top: 0,
      width: video!.clientWidth,
      height: video!.clientHeight
    }
  }
  // nextTick(() => {
  //   cropVideoFrame()
  // })
}

const handleInitCropArea = () => {
  const video = backgroundVideoRef.value
  const cropArea: any = toRaw(props.cropArea)
  if (!video) {
    return
  }

  if (cropArea.length > 0) {
    const scaleX = cropPreviewBox.value.width / video!.videoWidth
    const scaleY = cropPreviewBox.value.height / video!.videoHeight
    console.log('cropArea', cropArea, scaleX, scaleY)

    const left = Math.round(cropArea[0][0] * scaleX)
    const top = Math.round(cropArea[0][1] * scaleY)
    const width = Math.round((cropArea[1][0] - cropArea[0][0]) * scaleX)
    const height = Math.round((cropArea[1][1] - cropArea[0][1]) * scaleY)
    console.log('init cropArea', left, top, width, height)

    rectData.value = {
      left,
      top,
      width,
      height
    }
  }
}
</script>
<template>
  <el-dialog
    v-model="isVisible"
    :close-on-click-modal="false"
    :show-close="false"
    :title="title"
    :width="isMobile ? '80%' : '400px'"
    align-center
    center
    lock-scroll
    class="wm-video-crop-dialog"
    :class="{ 'is-mobile': isMobile }"
  >
    <!-- 底部视频和裁剪框 -->
    <div class="video-crop-container">
      <video
        ref="backgroundVideoRef"
        :src="url"
        autoplay
        loop
        muted
        webkit-playsinline
        playsinline
        class="background-video"
        @loadeddata="onVideoLoaded"
        v-if="isVisible"
      ></video>
      <VueDragResize
        ref="cropBoxRef"
        :w="rectData.width"
        :h="rectData.height"
        :x="rectData.left"
        :y="rectData.top"
        :parent-limitation="true"
        :is-resizable="true"
        :is-draggable="true"
        class="crop-box"
        v-on:resizing="resize"
        v-on:dragging="resize"
        :isActive="true"
        v-if="showCropBox"
      ></VueDragResize>
    </div>
    <!-- 显示裁剪后的内容 -->
    <div class="cropped-image-container" v-if="false">
      <div class="title">裁剪后的视频显示效果</div>
      <div
        :style="{
          width: cropPreviewBox.width + 'px',
          height: cropPreviewBox.height + 'px'
        }"
      >
        <canvas ref="croppedCanvasRef"></canvas>
      </div>
    </div>
    <template #footer>
      <div class="dialog-footer">
        <el-button class="btn" @click="onCancel">取消</el-button>
        <el-button type="primary" class="btn confirm" @click="onConfirm"> 裁剪 </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style scoped lang="scss">
.wm-video-crop-dialog {
  .video-crop-container {
    position: relative;
    width: 100%;
    font-size: 0;
    .background-video {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }

    .crop-box {
      border-color: var(--el-color-primary-dark-2);
      position: absolute;
      cursor: move;
      .vdr-stick {
        background: var(--el-color-primary-dark-2);
        border: 1px solid var(--el-color-primary-dark-2);
        -webkit-box-shadow: 0 0 2px var(--el-color-primary-dark-2);
        box-shadow: 0 0 2px var(--el-color-primary-dark-2);
      }
    }
  }
  .cropped-image-container {
    margin-top: 10px;
    // text-align: center;
    .title {
      font-size: 16px;
      margin-bottom: 10px;
    }
  }

  .brn {
    &.confirm {
      margin-left: 10px;
    }
  }
  &.is-mobile {
    .wm-input {
      width: 100%;
    }
  }
}
</style>
<style lang="scss">
.wm-video-crop-dialog {
  .el-dialog__body {
    padding: 10px calc(var(--el-dialog-padding-primary) + 5px) 10px;
  }

  .video-crop-container {
    .crop-box {
      border-color: var(--el-color-primary);
      &::before {
        outline: 1px dashed var(--el-color-primary);
      }
      .vdr-stick {
        background: var(--el-color-primary);
        border: 1px solid var(--el-color-primary);
        -webkit-box-shadow: 0 0 2px var(--el-color-primary);
        box-shadow: 0 0 2px var(--el-color-primary);
      }
    }
  }
}
</style>
