import { ref, computed, unref, nextTick, watch } from 'vue';
import { throttle } from 'lodash-unified';
import '../../../utils/index.mjs';
import { isBoolean } from '../../../utils/types.mjs';
import { buildProps, definePropType } from '../../../utils/vue/props/runtime.mjs';

const croppersEmits = {
  "update:modelValue": (value) => isBoolean(value),
  cropUploadSuccess: (value) => isBoolean(value)
};
const uploadCropperProps = buildProps({
  maxFileSize: {
    type: Number,
    default: 3e6
  },
  width: {
    type: Number,
    default: 400
  },
  height: {
    type: Number,
    default: 400
  },
  size: {
    type: Number,
    default: 3
  }
});
const cropperProps = buildProps({
  ...uploadCropperProps,
  modelValue: {
    type: Boolean,
    required: true
  },
  file: {
    type: definePropType(String),
    required: true
  }
});
const useCropper = (cropperProps2) => {
  const isShowDialog = ref(false);
  const sourImgUrl = ref("");
  const sourceImg = ref(null);
  const createImgUrl = ref("");
  const scalingRatio = ref(0);
  const sourceZoomRadius = ref(0);
  const nRatio = ref(cropperProps2.width / cropperProps2.height);
  const mouseDown = ref(false);
  const sourceImgContainer = ref({
    w: 300,
    h: 240,
    r: 1.25
  });
  const shadeInfo = ref({
    w: 0,
    h: 0,
    x: 0,
    y: 0
  });
  const sourceImgInfo = ref({
    x: 0,
    y: 0,
    width: 0,
    height: 0,
    top: 0,
    left: 0,
    screenX: 0,
    screenY: 0,
    initWidth: 0,
    initHeight: 0,
    naturalWidth: 0,
    naturalHeight: 0
  });
  const canvasRef = ref(null);
  const previewImgStyle = computed(() => {
    const ratio = nRatio.value;
    return {
      width: "150px",
      height: `${150 / ratio}px`
    };
  });
  const updateShadeStyle = () => {
    let { w, h } = shadeInfo.value;
    const Ratio = nRatio.value;
    const { r: sourceR, w: sourceW, h: sourceH } = sourceImgContainer.value;
    if (Ratio < sourceR) {
      h = sourceH;
      shadeInfo.value.w = w = (sourceW - h * Ratio) / 2;
    } else {
      w = sourceW;
      shadeInfo.value.h = h = (sourceH - w / Ratio) / 2;
    }
    shadeInfo.value.x = w;
    shadeInfo.value.y = h;
    return {
      w,
      h
    };
  };
  const sourImgStyle = computed(() => {
    const { width, height, top, left } = sourceImgInfo.value;
    return {
      width: `${width}px`,
      height: `${height}px`,
      top: `${top}px`,
      left: `${left}px`
    };
  });
  const getImgFile = (img) => {
    const image = new Image();
    image.crossOrigin = "Anonymous";
    image.src = img;
    image.onload = () => {
      const canvas = document.createElement("canvas");
      canvas.width = image.width;
      canvas.height = image.height;
      const context = canvas.getContext("2d");
      context.drawImage(image, 0, 0, image.width, image.height);
      const dataURL = canvas.toDataURL();
      const file = dataURLtoFile(dataURL);
      readAsDataURLFun(file);
    };
  };
  const dataURLtoFile = (dataurl, filename = "") => {
    const arr = dataurl.split(",");
    const mime = arr[0].match(/:(.*?);/)[1];
    const bstr = atob(arr[1]);
    let n = bstr.length;
    const u8arr = new Uint8Array(n);
    while (n--) {
      u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], filename, { type: mime });
  };
  const setSourceImg = () => {
    if (!cropperProps2.file) {
      return;
    }
    if (typeof cropperProps2.file === "string") {
      getImgFile(cropperProps2.file);
    } else {
      readAsDataURLFun(cropperProps2.file);
    }
  };
  const readAsDataURLFun = (file) => {
    const fr = new FileReader();
    fr.onload = () => {
      sourImgUrl.value = fr.result;
      startCrop();
    };
    fr.readAsDataURL(file);
  };
  const startCrop = () => {
    const img = new Image();
    img.src = sourImgUrl.value;
    img.onload = () => {
      const sourceRadius = img.naturalWidth / img.naturalHeight;
      const { w: sourceW, h: sourceH } = unref(sourceImgContainer);
      const { w: shadeW, h: shadeH } = unref(shadeInfo);
      if (sourceRadius < nRatio.value) {
        sourceImgInfo.value.width = sourceW - shadeW * 2;
        sourceImgInfo.value.height = sourceImgInfo.value.width / sourceRadius;
        sourceZoomRadius.value = sourceImgInfo.value.width / img.naturalWidth;
      } else {
        sourceImgInfo.value.height = sourceH - shadeH * 2;
        sourceImgInfo.value.width = sourceImgInfo.value.height * sourceRadius;
        sourceZoomRadius.value = sourceImgInfo.value.height / img.naturalHeight;
      }
      sourceImgInfo.value.left = (sourceW - sourceImgInfo.value.width) / 2;
      sourceImgInfo.value.top = (sourceH - sourceImgInfo.value.height) / 2;
      sourceImgInfo.value.x = sourceImgInfo.value.left;
      sourceImgInfo.value.y = sourceImgInfo.value.top;
      sourceImgInfo.value.initWidth = sourceImgInfo.value.width;
      sourceImgInfo.value.initHeight = sourceImgInfo.value.height;
      sourceImgInfo.value.naturalWidth = img.naturalWidth;
      sourceImgInfo.value.naturalHeight = img.naturalHeight;
      if (cropperProps2.modelValue) {
        nextTick(() => {
          createImg();
        });
      }
    };
    sourceImg.value = img;
  };
  const createImg = () => {
    const { top, left, naturalWidth, naturalHeight } = unref(sourceImgInfo);
    mouseDown.value = false;
    const canvas = canvasRef.value;
    const ctx = canvas.getContext("2d");
    if (!canvas || !ctx) {
      console.error("\u4E0D\u652F\u6301\u7684\u753B\u5E03");
      return;
    }
    const ratio = (Number(scalingRatio.value) + 100) / 100;
    const { w: sourceW, h: sourceH } = unref(sourceImgContainer);
    const { w: shadeW, h: shadowh } = unref(shadeInfo);
    const createImgWidth = {
      w: (sourceW - 2 * shadeW) / ratio / sourceZoomRadius.value,
      h: (sourceH - 2 * shadowh) / ratio / sourceZoomRadius.value,
      x: (shadeW - left) / ratio / sourceZoomRadius.value,
      y: (shadowh - top) / ratio / sourceZoomRadius.value
    };
    let canvasWidth;
    let canvasHeight;
    const sourceRadius = naturalWidth / naturalHeight;
    if (sourceRadius < nRatio.value) {
      canvasWidth = naturalWidth;
      canvasHeight = naturalWidth / nRatio.value;
    } else {
      canvasWidth = naturalHeight * nRatio.value;
      canvasHeight = naturalHeight;
    }
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(sourceImg.value, createImgWidth.x, createImgWidth.y, createImgWidth.w, createImgWidth.h, 0, 0, canvas.width, canvas.height);
    const size = data2blob(canvas.toDataURL("image/png")).size;
    if (size <= cropperProps2.size * 1024 * 1024) {
      createImgUrl.value = canvas.toDataURL("image/png");
    } else {
      const quality = cropperProps2.size / size * 1024 * 1024 * 0.64;
      createImgUrl.value = canvas.toDataURL("image/jpeg", quality);
    }
  };
  const data2blob = (data) => {
    data = data.split(",")[1];
    data = window.atob(data);
    const ia = new Uint8Array(data.length);
    for (let i = 0; i < data.length; i++) {
      ia[i] = data.charCodeAt(i);
    }
    return new Blob([ia], {
      type: "image/png"
    });
  };
  const clearData = () => {
    sourImgUrl.value = "";
    createImgUrl.value = "";
    sourceZoomRadius.value = 0;
    scalingRatio.value = 0;
  };
  const startMoveImg = (e) => {
    sourceImgInfo.value.screenX = e.screenX;
    sourceImgInfo.value.screenY = e.screenY;
    mouseDown.value = true;
  };
  const moveImg = throttle((e) => {
    e.preventDefault();
    if (!mouseDown.value) {
      return;
    }
    const dX = (e.screenX - sourceImgInfo.value.screenX) * 0.1;
    const dY = (e.screenY - sourceImgInfo.value.screenY) * 0.1;
    let rX = sourceImgInfo.value.left + dX;
    let rY = sourceImgInfo.value.top + dY;
    const { w: sourceW, h: sourceH } = unref(sourceImgContainer);
    const { w: shadeW, h: shadowh } = unref(shadeInfo);
    if (dX > 0) {
      rX = rX > shadeW ? shadeW : rX;
    } else {
      const maxX = shadeW + 2 * (sourceImgInfo.value.width - sourceW) / 2;
      rX = Math.abs(rX) > maxX ? -maxX : rX;
    }
    if (dY > 0) {
      rY = rY > shadowh ? shadowh : rY;
    } else {
      const maxY = shadowh + 2 * (sourceImgInfo.value.height - sourceH) / 2;
      rY = Math.abs(rY) > maxY ? -maxY : rY;
    }
    sourceImgInfo.value.top = rY;
    sourceImgInfo.value.left = rX;
  }, 16);
  const zoomImg = (type) => {
    if (type === -1 && Number(scalingRatio.value) > 0) {
      scalingRatio.value = Number(scalingRatio.value) - 1;
    }
    if (type === -2 && Number(scalingRatio.value) < 100) {
      scalingRatio.value = Number(scalingRatio.value) + 1;
    }
  };
  const shadeStyle = computed(() => {
    const { w, h } = updateShadeStyle();
    return {
      width: `${w}px`,
      height: `${h}px`
    };
  });
  watch(() => cropperProps2.modelValue, (value) => {
    isShowDialog.value = value;
    if (value) {
      setSourceImg();
    } else {
      clearData();
    }
  });
  watch(scalingRatio, (n) => {
    sourceImgInfo.value.width = sourceImgInfo.value.initWidth * (Number(n) + 100) / 100;
    sourceImgInfo.value.height = sourceImgInfo.value.initHeight * (Number(n) + 100) / 100;
    const { top, left, width, height } = sourceImgInfo.value;
    const nTop = -height + sourceImgContainer.value.h - shadeInfo.value.h;
    sourceImgInfo.value.top = top < nTop ? nTop : top;
    const nLeft = -width + sourceImgContainer.value.w - shadeInfo.value.w;
    sourceImgInfo.value.left = left < nLeft ? nLeft : left;
    nextTick(() => {
      if (isShowDialog.value) {
        createImg();
      }
    });
  });
  return {
    zoomImg,
    scalingRatio,
    canvasRef,
    createImg,
    data2blob,
    createImgUrl,
    sourImgUrl,
    clearData,
    previewImgStyle,
    shadeStyle,
    sourImgStyle,
    isShowDialog,
    startMoveImg,
    moveImg,
    shadeInfo,
    sourceImgInfo
  };
};

export { cropperProps, croppersEmits, uploadCropperProps, useCropper };
//# sourceMappingURL=upload-cropper.mjs.map
