import {
  NButton,
  NModal,
  NSpace,
  NSpin,
  NUpload,
  NUploadDragger,
  useMessage
} from 'naive-ui';
import {
  defineComponent,
  reactive,
  ref,
  nextTick,
  onMounted,
  watch,
  computed
} from 'vue';
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.css';
import styles from './index.module.less';
import iconUploadAdd from '../../../images/icon-upload2.png';
import { NaturalTypeEnum } from '@/enums/pageEnum';
import { getUploadSign, onOnlyFileUpload } from '/src/helpers/oss-file-upload';
import { formatUrlType } from '../upload-modal';

/**
 * 1. 图片上传可以进行裁剪
 */
export default defineComponent({
  name: 'upload-file',
  props: {
    img: {
      type: String,
      default: ''
    },
    accept: {
      // 支持类型
      type: String,
      default: '.jpg,.png,.jpeg,.gif'
    },
    bucketName: {
      type: String,
      default: 'gyt'
    },
    path: {
      type: String,
      default: ''
    },
    fileName: {
      type: String,
      default: ''
    },
    options: {
      type: Object,
      default: () => {
        return {
          viewMode: 0,
          autoCrop: true, //是否默认生成截图框
          enlarge: 1, //  图片放大倍数
          autoCropWidth: 640, //默认生成截图框宽度
          autoCropHeight: 360, //默认生成截图框高度
          fixedBox: false, //是否固定截图框大小 不允许改变
          previewsCircle: true, //预览图是否是原图形
          title: '上传图片'
        };
      }
    }
  },
  emits: ['close', 'confirm'],
  setup(props, { emit }) {
    const imgCropper = ref();
    const ossUploadUrl = `https://${props.bucketName}.ks3-cn-beijing.ksyuncs.com/`;
    const message = useMessage();
    const visiable = ref<boolean>(false);
    const btnLoading = ref<boolean>(false);
    const uploadRef = ref();
    const copperOptions = ref({
      img: '', //裁剪图片的地址
      autoCrop: true, //是否默认生成截图框
      autoCropWidth: 180, //默认生成截图框宽度
      autoCropHeight: 180, //默认生成截图框高度
      fixedBox: true, //是否固定截图框大小 不允许改变
      full: false,
      enlarge: 1, // 是否按照截图框比例输出 默认为1
      previewsCircle: true, //预览图是否是原圆形
      centerBox: true,
      outputType: 'png',
      title: '修改头像',
      name: null // 文件名称
    } as any);
    const state = reactive({
      myCropper: null as any,
      cropperReady: false
    }) as any;

    const onBeforeUpload = async (options: any) => {
      const file = options.file;
      // 文件大小
      let isLt2M = true;

      const type = file.type.includes('image')
        ? NaturalTypeEnum.IMG
        : file.type.includes('audio')
        ? NaturalTypeEnum.SONG
        : NaturalTypeEnum.VIDEO;
      if (type !== NaturalTypeEnum.IMG) {
        message.error('上传文件格式错误');
        return false;
      }
      const size = 10; //type === 'IMG' ? 10 : type === 'SONG' ? 20 : 500;
      if (size) {
        isLt2M = file.file.size / 1024 / 1024 < size;
        if (!isLt2M) {
          message.error(`图片大小不能超过${size}M`);
          return false;
        }
      }
      getBase64(file.file, (imageUrl: any) => {
        cropperBefore(imageUrl, file.file.name);
      });
      return false;
    };
    const getBase64 = async (img: any, callback: any) => {
      const reader = new FileReader();
      reader.addEventListener('load', () => callback(reader.result));
      reader.readAsDataURL(img);
    };

    const cropperBefore = (imageUrl: string, name?: string) => {
      const target = Object.assign({}, props.options, {
        img: imageUrl,
        name // 上传文件名
      });

      visiable.value = true;
      copperOptions.value = Object.assign({}, copperOptions.value, target);
      nextTick(() => {
        initImgCropper();
      });
    };

    const initImgCropper = () => {
      try {
        state.cropperReady = true;
        state.myCropper = new Cropper(imgCropper.value, {
          viewMode: 1, //定义裁剪器的视图模式。如果将viewMode设置为0，则裁剪框可以延伸到画布外部，而值为1、2或3将限制裁剪框的大小为画布的大小。viewMode为2或3会将画布限制为容器。请注意，如果画布和容器的比例相同，则2和3之间没有差别。
          dragMode: 'move', //定义的拖动模式裁剪器.canvas和容器一样，2和3没有区别。move:移动画布 crop:创建新的裁剪框（默认） none:什么也不做
          //定义裁剪框的固定纵横比。默认情况下，裁剪框为自由比率。
          aspectRatio:
            copperOptions.value.autoCropWidth /
            copperOptions.value.autoCropHeight,
          initialAspectRatio: 1,
          autoCropArea: 1, //定义0到1之间的fA编号。定义自动裁剪区域大小（百分比）。默认0.8
          cropBoxMovable: true, //允许通过拖动移动裁剪框。默认true
          cropBoxResizable: true, //以通过拖动来调整裁剪框的大小 默认true
          background: true, //显示容器的网格背景
          movable: false, //移动图像
          modal: true,
          preview: '.before',
          ready: () => {
            state.cropperReady = false;
          }
        });
      } catch {
        //
      }
    };

    // 裁切成功
    const onSubmit = () => {
      state.myCropper
        .getCroppedCanvas({
          imageSmoothingQuality: 'high'
        })
        .toBlob((blob: any) => {
          btnLoading.value = true;
          cropperOk(blob);
        });
    };
    const cropperOk = async (blob: any) => {
      try {
        const fileName = `${props.path}${
          props.fileName || new Date().getTime() + '.png'
        }`;
        const obj = {
          filename: fileName,
          bucketName: props.bucketName,
          postData: {
            filename: fileName,
            acl: 'public-read',
            key: fileName
          }
        };

        const { data } = await getUploadSign(obj);
        const formData = {
          policy: data.policy,
          signature: data.signature,
          acl: 'public-read',
          key: fileName,
          KSSAccessKeyId: data.kssAccessKeyId,
          name: fileName,
          file: blob
        };
        const res = await onOnlyFileUpload(ossUploadUrl, formData);
        emit('confirm', res);
        emit('close');
      } catch {
        //
      }
      btnLoading.value = false;
    };

    watch(
      () => props.img,
      () => {
        if (props.img && formatUrlType(props.img) === NaturalTypeEnum.IMG) {
          cropperBefore(props.img);
        }
      }
    );

    onMounted(() => {
      if (props.img && formatUrlType(props.img) === NaturalTypeEnum.IMG) {
        cropperBefore(props.img);
      }
    });
    return () => (
      <div class={styles.uploadFile}>
        <div class={styles.uploadHeader}>
          <div class={styles.headerItem}>上传封面</div>
        </div>

        {!visiable.value ? (
          <div class={styles.uploadContainer}>
            <NUpload
              ref={uploadRef}
              accept={props.accept}
              multiple={false}
              max={1}
              showFileList={false}
              showPreviewButton
              onBeforeUpload={(options: any) => onBeforeUpload(options)}
              // onFinish={(options: any) => {
              //   onFinish(options);
              // }}
              // onRemove={(options: any) => onRemove()}
            >
              <NUploadDragger>
                <div class={styles.uploadBtn}>
                  <img src={iconUploadAdd} class={styles.iconUploadAdd} />
                  <p>点击或将图片拖至此区域</p>
                  <span>（建议比例16:9）</span>
                </div>
              </NUploadDragger>
            </NUpload>
          </div>
        ) : (
          <div class={styles.uploadContainer}>
            <NSpin show={state.cropperReady}>
              <div class={styles.imgCropperSection}>
                {copperOptions.value?.img && (
                  <img
                    ref={imgCropper}
                    src={copperOptions.value?.img}
                    style={{
                      opacity: state.myCropper?.ready ? '1' : '0'
                    }}
                    alt=""
                  />
                )}
              </div>
            </NSpin>
          </div>
        )}

        <div class={styles.uploadBtnGroup}>
          {visiable.value ? (
            <NButton
              type="default"
              onClick={() => {
                copperOptions.value.img = '';
                visiable.value = false;
              }}>
              重新选择
            </NButton>
          ) : (
            <span></span>
          )}

          <NSpace>
            <NButton type="default" onClick={() => emit('close')}>
              取消
            </NButton>
            <NButton
              type="primary"
              onClick={() => onSubmit()}
              disabled={!visiable.value}
              loading={btnLoading.value}>
              保存封面
            </NButton>
          </NSpace>
        </div>
      </div>
    );
  }
});
