<!-- eslint-disable @typescript-eslint/no-non-null-assertion -->
<script lang="ts" setup>
import 'vue-cropper/dist/index.css'
import { VueCropper } from 'vue-cropper'
import type { UploadFile } from 'element-plus'
import { ElMessage } from 'element-plus'
import type { UploadInstance } from 'element-plus'

const uploadRef = ref<UploadInstance>()
interface Options {
  img: string | ArrayBuffer | null // 裁剪图片的地址
  info: true // 裁剪框的大小信息
  outputSize: number // 裁剪生成图片的质量 [1至0.1]
  outputType: string // 裁剪生成图片的格式
  canScale: boolean // 图片是否允许滚轮缩放
  autoCrop: boolean // 是否默认生成截图框
  autoCropWidth: number // 默认生成截图框宽度
  autoCropHeight: number // 默认生成截图框高度
  fixedBox: boolean // 固定截图框大小 不允许改变
  fixed: boolean // 是否开启截图框宽高固定比例
  fixedNumber: Array<number> // 截图框的宽高比例  需要配合centerBox一起使用才能生效
  full: boolean // 是否输出原图比例的截图
  canMoveBox: boolean // 截图框能否拖动
  original: boolean // 上传图片按照原始比例渲染
  centerBox: boolean // 截图框是否被限制在图片里面
  infoTrue: boolean // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
  accept: string // 上传允许的格式
  mode: string
}
// 父组件传参props
const props = defineProps<{
  modelValue: boolean
  circleUrl: string
}>()
const emits = defineEmits(['closeAvatarDialog', 'update:modelValue'])

const dialogVisible = computed({
  get: () => props.modelValue,
  set: value => emits('update:modelValue', value)
})
// 裁剪组件需要使用到的参数
const options = reactive<Options>({
  img: props.circleUrl, // 需要剪裁的图片
  autoCrop: true, // 是否默认生成截图框
  autoCropWidth: 200, // 默认生成截图框的宽度
  autoCropHeight: 200, // 默认生成截图框的长度
  fixedBox: true, // 是否固定截图框的大小 不允许改变
  info: true, // 裁剪框的大小信息
  outputSize: 1, // 裁剪生成图片的质量 [1至0.1]
  outputType: 'png', // 裁剪生成图片的格式
  canScale: true, // 图片是否允许滚轮缩放
  fixed: true, // 是否开启截图框宽高固定比例
  fixedNumber: [1, 1], // 截图框的宽高比例 需要配合centerBox一起使用才能生效 1比1
  full: false, // 是否输出原图比例的截图
  canMoveBox: false, // 截图框能否拖动
  original: true, // 上传图片按照原始比例渲染
  centerBox: true, // 截图框是否被限制在图片里面
  infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
  accept: 'image/jpeg,image/jpg,image/png,image/gif,image/x-icon',
  mode: 'contain'
})

const beforeUpload = (file: UploadFile) => {
  const { size } = file
  const fileType = file.raw?.type
  const type = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/x-icon']
  if (type.indexOf(fileType!) === -1) {
    ElMessage.warning('仅支持jpeg,jpg,png,gif,icon格式上传')
    uploadRef.value?.clearFiles()
  } else if (Number(size) / 1024 / 1024 > 2) {
    ElMessage.error('图片大小不能超过2MB!')
    uploadRef.value?.clearFiles()
  } else {
    const reader = new FileReader()
    // 转化为base64
    reader.readAsDataURL(file.raw!)
    reader.onload = () => {
      // 获取到需要剪裁的图片 展示到剪裁框中
      options.img = reader.result
    }
  }
}

const previews: any = ref({})
const showBoxStyle: any = ref({})

const cropperRef: any = ref({})
const previewHandle = (data: any) => {
  previews.value = data // 预览img图片
  showBoxStyle.value = {
    width: data.w + 'px',
    height: data.h + 'px',
    overflow: 'hidden',
    margin: '0',
    zoom: 200 / data.h
  }
}

const goSave = () => {
  cropperRef.value.getCropData((data: any) => {
    emits('closeAvatarDialog', data)
  })
  // cropperRef.value.getCropBlob((data: any) => {
  //   // console.log(data)
  // })
}

const changeScale = (num: number) => {
  const scale = num || 1
  cropperRef.value.changeScale(scale)
}
const rotateLeft = () => {
  cropperRef.value.rotateLeft()
}
const rotateRight = () => {
  cropperRef.value.rotateRight()
}
</script>

<template>
  <el-dialog
    title="上传头像"
    v-model="dialogVisible"
    :show-close="false"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    destroy-on-close
    width="900px"
  >
    <div class="croWrap">
      <div style="width: 600px; height: 400px">
        <vue-cropper
          ref="cropperRef"
          :img="options.img"
          :info="true"
          :autoCropWidth="options.autoCropWidth"
          :autoCropHeight="options.autoCropHeight"
          :info-true="options.infoTrue"
          :auto-crop="options.autoCrop"
          :fixed-box="options.fixedBox"
          :can-move="options.canMoveBox"
          :can-scale="options.canScale"
          :fixed-number="options.fixedNumber"
          :fixed="options.fixed"
          :full="options.full"
          :center-box="options.centerBox"
          :mode="options.mode"
          @real-time="previewHandle"
        />
      </div>
      <div class="previewBox">
        <div :style="showBoxStyle">
          <img :src="previews.url" :style="previews.img" />
        </div>
      </div>
    </div>
    <div class="btnWrap">
      <el-upload
        ref="uploadRef"
        class="upload-demo"
        action="#"
        :auto-upload="false"
        :on-change="beforeUpload"
        :show-file-list="false"
      >
        <template #trigger>
          <el-button type="primary">选择图片</el-button>
        </template>
      </el-upload>
      <el-button @click="changeScale(1)">放大</el-button>
      <el-button @click="changeScale(-1)">缩小</el-button>
      <el-button @click="rotateLeft">向左</el-button>
      <el-button @click="rotateRight">向右</el-button>
    </div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="goSave">确定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<style lang="scss" scoped>
.btnWrap {
  display: flex;
  align-items: center;
  margin-top: 12px;
  .upload-demo {
    margin-right: 12px;
  }
}
.croWrap {
  display: flex;
  justify-content: space-between;
  .previewBox {
    width: 200px;
    height: 200px;
    border: 1px solid #ccc;
    overflow: hidden;
    border-radius: 50%;
  }
}
</style>
