<script setup lang="ts">
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.css'
import { nextTick, ref, shallowRef, useTemplateRef } from 'vue'

const imageRef = useTemplateRef('imageRef')
// const rectanglePreview = useTemplateRef('rectanglePreview')
const roundPreview = useTemplateRef('roundPreview')

const isShowImageCropperModal = ref(false)
const cropperIns = shallowRef<Cropper | null>(null)
const isInitCropper = ref(false)
const confirmBtnLoading = ref(false)
const currentEditImageUrl = ref('')

let cropImageResolve: (value: any) => void = () => {}
let cropImageReject: (value: any) => void = () => {}

function initCropper() {
  return new Promise((resolve) => {
    nextTick(() => {
      if (imageRef.value) {
        cropperIns.value = new Cropper(imageRef.value, {
          viewMode: 3,
          dragMode: 'move',
          aspectRatio: 1,
          // cropBoxMovable: false, // 可通过拖动移动裁剪框
          // cropBoxResizable: false, // 可通过拖动调整裁剪框的大小
          minCropBoxWidth: 50, // 裁剪框的最小宽度
          minCropBoxHeight: 50, // 裁剪框的最小高度
          // autoCropArea: 1,
          // preview: previewRef.value! || [],
          preview: [roundPreview.value!],
          // rotatable: false, // 旋转
          // scalable: false, // 可伸缩
          // zoomable: false, // 可缩放
          // zoomOnTouch: false, // 缩放触摸

          ready: () => {
            if (!isInitCropper.value) {
              isInitCropper.value = true
              resolve('加载成功')
            }
          },
        })
      }
    })
  })
}

function handleCropConfirm() {
  if (cropperIns.value) {
    confirmBtnLoading.value = true

    cropperIns.value.getCroppedCanvas().toBlob((blob) => {
      if (blob) {
        const fd = new FormData()
        const file = new File([blob], `image.${blob.type.split('/')[1]}`, { type: blob.type })

        fd.append('file', file)

        cropImageResolve(file)

        confirmBtnLoading.value = false
        isShowImageCropperModal.value = false
      }
    })
  }
}

function handleCropCancel() {
  isShowImageCropperModal.value = false

  cropImageReject(new Error('Cancel'))
}

function cropImage(url: string): Promise<File> {
  currentEditImageUrl.value = url

  isShowImageCropperModal.value = true

  return initCropper().then(() => {
    return new Promise((resolve, reject) => {
      cropImageResolve = resolve
      cropImageReject = reject
    })
  })
}

function onModalAfterLeave() {
  if (cropperIns.value) {
    cropperIns.value.destroy()

    cropperIns.value = null
    isInitCropper.value = false
  }
}

defineExpose({
  cropImage,
})
</script>

<template>
  <n-modal v-model:show="isShowImageCropperModal" :on-after-leave="onModalAfterLeave">
    <n-card class="!w-[800px]" title="图片裁切" :bordered="false" size="huge" role="dialog" aria-modal="true">
      <div class="relative flex">
        <div class="absolute inset-0">
          <n-skeleton height="400px" width="400px" />
        </div>

        <div
          class="h-[400px] w-[400px] transition-[opacity] duration-300 ease-in-out"
          :class="{ 'opacity-0': !isInitCropper }"
        >
          <img ref="imageRef" class="block h-full w-full" alt="Picture" :src="currentEditImageUrl" />
        </div>

        <div class="ml-[40px]">
          <div class="mb-[10px] text-[16px]">图片预览：</div>

          <!-- <div ref="rectanglePreview" class="h-[180px] w-[180px] overflow-hidden rounded-[6px] bg-[#f3f3f3]"></div> -->
          <div ref="roundPreview" class="mt-[20px] h-[180px] w-[180px] overflow-hidden rounded-full bg-[#f3f3f3]"></div>
        </div>
      </div>

      <template #footer>
        <div class="text-end">
          <n-button class="!mr-[20px]" @click="handleCropCancel">取消</n-button>
          <n-button type="primary" :loading="confirmBtnLoading" @click="handleCropConfirm">确定</n-button>
        </div>
      </template>
    </n-card>
  </n-modal>
</template>

<style lang="scss" scoped>
// :global(.cropper-view-box) {
//   .cropper-view-box,
//   .cropper-face {
//     border-radius: 50%;
//   }

//   .cropper-view-box {
//     outline: 0;
//     box-shadow: 0 0 0 1px #39f;
//   }
// }

// :global(.cropper-container .cropper-crop-box) {
//   outline: 1px solid #000dff;

//   .cropper-line {
//     background-color: #000dff !important;
//   }

//   .cropper-point {
//     background-color: #000dff !important;
//   }
// }

// .cropper-container .cropper-crop-box {
//   outline: 1px solid #000dff;

//   .cropper-line {
//     background-color: #000dff !important;
//   }

//   .cropper-point {
//     background-color: #000dff !important;
//   }
// }
</style>
