<script lang="ts" setup>
import type { Boundaries } from 'vue-advanced-cropper'
import { Cropper } from 'vue-advanced-cropper'
import 'vue-advanced-cropper/dist/style.css'

export interface Props {
  /** Images to be cropped */
  modelValue?: File
  /** Crop frame aspect ratio (width/height), default 1/1 */
  stencilAspectRatio?: number
  /** The ratio of the longest edge of the cut box to the length of the cut screen, default 0.9, not more than 1 */
  stencilSizePercentage?: number
}
const props = withDefaults(defineProps<Props>(), {
  stencilAspectRatio: 1 / 1,
  stencilSizePercentage: 0.9,
})

const emits = defineEmits<{
  (event: 'update:modelValue', value: File): void
}>()

const vmFile = useVModel(props, 'modelValue', emits, { passive: true })

const cropperDialog = ref(false)

const cropper = ref<InstanceType<typeof Cropper>>()

const cropperFlag = ref(false)

const cropperImage = reactive({
  src: '',
  type: 'image/jpg',
})

const stencilSize = ({ boundaries }: { boundaries: Boundaries }) => {
  return {
    width: boundaries.width * props.stencilSizePercentage,
    height: boundaries.height * props.stencilSizePercentage,
  }
}

watch(vmFile, (file, _, onCleanup) => {
  let expired = false
  onCleanup(() => expired = true)

  if (file && !cropperFlag.value) {
    cropperDialog.value = true
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = (e) => {
      if (expired)
        return
      cropperImage.src = e.target?.result as string
      cropperImage.type = file.type
    }
  }
  cropperFlag.value = false
})

const cropImage = () => {
  if (cropper.value && vmFile.value) {
    cropperFlag.value = true
    cropperDialog.value = false
    const { canvas } = cropper.value.getResult()
    canvas?.toBlob((blob) => {
      vmFile.value = new File([blob as any], `cropped${vmFile.value?.name}` as string, { type: blob?.type })
    }, cropperImage.type)
  }
}
</script>

<template>
  <ModalDialog v-model="cropperDialog" :use-v-if="false" max-w-500px flex>
    <div flex-1 w-0>
      <div text-lg text-center my2 px3>
        <h1>
          {{ $t('action.edit') }}
        </h1>
      </div>
      <div aspect-ratio-1>
        <Cropper
          ref="cropper"
          class="overflow-hidden w-full h-full"
          :src="cropperImage.src"
          :resize-image="{
            adjustStencil: false,
          }"
          :stencil-size="stencilSize"
          :stencil-props="{
            aspectRatio: props.stencilAspectRatio,
            movable: false,
            resizable: false,
            handlers: {},
          }"
          image-restriction="stencil"
        />
      </div>
      <div m-4>
        <button
          btn-solid w-full rounded text-sm
          @click="cropImage()"
        >
          {{ $t('action.confirm') }}
        </button>
      </div>
    </div>
  </ModalDialog>
</template>
