import { defineComponent, ref, watch, inject, computed, createElementBlock, openBlock, normalizeClass, createVNode, createCommentVNode, createElementVNode, createSlots, renderList, unref, withCtx, renderSlot, normalizeProps, guardReactiveProps, Fragment, createBlock, mergeProps, createTextVNode, toDisplayString } from "vue";
import { uploadProps } from "./types.mjs";
import { isArray, isFunction } from "../_utils/is.mjs";
import { filterSlots } from "../_utils/vue-utils.mjs";
import _sfc_main$3 from "./UploadItem.vue.mjs";
import slot from "./slot.mjs";
import { doUploadFileList, isPictureType, generateImageDataUrl, doUploadFile } from "./util.mjs";
import _sfc_main$2 from "./UploadSelect.vue.mjs";
import { IconAdd } from "../_utils/icons.mjs";
import _sfc_main$1 from "./InputSelect.vue.mjs";
import { formItemInjectKey } from "../form/provide.mjs";
import { useI18n } from "../locale/index.mjs";
const _hoisted_1 = {
  key: 0,
  class: "o-upload-select-wrap"
};
const _hoisted_2 = {
  key: 0,
  class: "o-upload-select-extra"
};
const _hoisted_3 = { class: "o-upload-card-label" };
const _sfc_main = /* @__PURE__ */ defineComponent({
  __name: "OUpload",
  props: uploadProps,
  emits: ["progress", "success", "error", "change", "select", "update:modelValue"],
  setup(__props, { expose: __expose, emit: __emit }) {
    const props = __props;
    const emits = __emit;
    const emitUpdateValue = (value) => {
      emits("update:modelValue", value);
    };
    const { t } = useI18n();
    const fileList = ref(props.modelValue ?? props.defaultFileList ?? []);
    watch(
      () => props.modelValue,
      (v) => {
        if (fileList.value === v) {
          return;
        }
        if (isArray(v)) {
          fileList.value = [...v];
        } else {
          fileList.value = [];
        }
      }
    );
    const formItemInjection = inject(formItemInjectKey, null);
    let fileId = 1;
    const uploadOption = computed(() => {
      return {
        uploadRequest: props.uploadRequest,
        onBeforeUpload: props.onBeforeUpload,
        onProgress: (file) => {
          emits("progress", file);
        },
        onSuccess: (file) => {
          emits("success", file);
          emitUpdateValue(fileList.value);
          emits("change", fileList.value);
        },
        onError: (file) => {
          emits("error", file);
          emitUpdateValue(fileList.value);
          emits("change", fileList.value);
        }
      };
    });
    const selectRef = ref(null);
    let replaceId = "";
    const uploadAll = () => {
      return doUploadFileList(fileList.value, uploadOption.value);
    };
    const afterSelected = (files) => {
      var _a, _b, _c, _d, _e, _f, _g;
      if (replaceId) {
        const idx = fileList.value.findIndex((item) => item.id === replaceId);
        if (idx > -1) {
          const f = fileList.value[idx];
          (_a = f.request) == null ? void 0 : _a.abort();
          fileList.value[idx] = files[0];
          replaceId = "";
          emitUpdateValue(fileList.value);
          emits("select", fileList.value);
          (_c = formItemInjection == null ? void 0 : (_b = formItemInjection.fieldHandlers).onChange) == null ? void 0 : _c.call(_b);
          if (!props.lazyUpload) {
            doUploadFile(fileList.value[idx], uploadOption.value);
          }
        }
      } else {
        let s = fileList.value.length;
        let l = files.length;
        if (props.multiple) {
          fileList.value = fileList.value.concat(files);
        } else {
          (_e = (_d = fileList.value[0]) == null ? void 0 : _d.request) == null ? void 0 : _e.abort();
          fileList.value = files;
          s = 0;
          l = 1;
        }
        emitUpdateValue(fileList.value);
        emits("select", fileList.value);
        (_g = formItemInjection == null ? void 0 : (_f = formItemInjection.fieldHandlers).onChange) == null ? void 0 : _g.call(_f);
        if (!props.lazyUpload) {
          doUploadFileList(fileList.value.slice(s, s + l), uploadOption.value);
        }
      }
    };
    const onFileSelected = async (files) => {
      let list = [];
      const isPicture = isPictureType(props.listType);
      if (isFunction(props.onAfterSelect)) {
        list = await props.onAfterSelect(files);
        if (isPicture) {
          list.forEach((item) => {
            if (!item.imgUrl && item.file) {
              item.imgUrl = generateImageDataUrl(item.file);
            }
          });
        }
      } else {
        list = Array.from(files).map((item) => {
          return {
            id: `${fileId++}`,
            name: item.name,
            file: item,
            imgUrl: isPicture ? generateImageDataUrl(item) : ""
          };
        });
      }
      afterSelected(list);
    };
    const removeFile = async (file) => {
      var _a, _b, _c;
      if (isFunction(props.onBeforeRemove)) {
        const sure = await props.onBeforeRemove(file);
        if (sure === false) {
          return false;
        }
      }
      (_a = file.request) == null ? void 0 : _a.abort();
      fileList.value = fileList.value.filter((f) => f.id !== file.id);
      (_c = formItemInjection == null ? void 0 : (_b = formItemInjection.fieldHandlers).onChange) == null ? void 0 : _c.call(_b);
      emitUpdateValue(fileList.value);
      return true;
    };
    const removeFileByIndex = (index) => {
      if (index > -1 && index < fileList.value.length) {
        return removeFile(fileList.value[index]);
      }
    };
    const removeAllFiles = () => {
      return new Promise((resolve) => {
        Promise.allSettled(fileList.value.map((f) => removeFile(f))).then((res) => {
          resolve(res);
        });
        fileList.value = [];
        emitUpdateValue(fileList.value);
      });
    };
    const onFileUploadRetry = (file) => {
      if (!file.retry || !file.file) {
        return;
      }
      doUploadFile(file, uploadOption.value);
    };
    const onFileReplace = (file) => {
      var _a;
      (_a = selectRef.value) == null ? void 0 : _a.select(false);
      replaceId = file.id;
    };
    const doSelect = async () => {
      var _a;
      if (isFunction(props.beforeSelect)) {
        const goon = await props.beforeSelect(fileList.value);
        if (goon === false) {
          return;
        }
      }
      (_a = selectRef.value) == null ? void 0 : _a.select(props.multiple);
    };
    __expose({
      upload: uploadAll,
      select: doSelect,
      retry: onFileUploadRetry,
      replace: onFileReplace,
      removeByIndex: removeFileByIndex,
      removeAll: removeAllFiles
    });
    return (_ctx, _cache) => {
      return openBlock(), createElementBlock(
        "div",
        {
          class: normalizeClass(["o-upload", { "o-upload-draggable": _ctx.draggable }])
        },
        [
          createVNode(_sfc_main$1, {
            ref_key: "selectRef",
            ref: selectRef,
            accept: props.accept,
            disabled: props.disabled,
            onSelected: onFileSelected
          }, null, 8, ["accept", "disabled"]),
          ["text", "picture"].includes(props.listType) ? (openBlock(), createElementBlock("div", _hoisted_1, [
            createVNode(_sfc_main$2, {
              disabled: props.disabled,
              draggable: props.draggable,
              "btn-label": props.btnLabel,
              "drag-label": props.dragLabel,
              "drag-hover-label": props.dragHoverLabel,
              onToSelect: doSelect,
              onSelected: onFileSelected
            }, createSlots({
              _: 2
              /* DYNAMIC */
            }, [
              renderList(unref(filterSlots)(_ctx.$slots, unref(slot).names), (name) => {
                return {
                  name,
                  fn: withCtx((slotData) => [
                    renderSlot(_ctx.$slots, name, normalizeProps(guardReactiveProps(slotData)))
                  ])
                };
              })
            ]), 1032, ["disabled", "draggable", "btn-label", "drag-label", "drag-hover-label"]),
            _ctx.$slots["select-extra"] ? (openBlock(), createElementBlock("div", _hoisted_2, [
              renderSlot(_ctx.$slots, "select-extra")
            ])) : createCommentVNode("v-if", true)
          ])) : createCommentVNode("v-if", true),
          createElementVNode(
            "div",
            {
              class: normalizeClass(["o-upload-list", {
                "o-upload-card-list": props.listType === "picture-card"
              }])
            },
            [
              (openBlock(true), createElementBlock(
                Fragment,
                null,
                renderList(fileList.value, (item) => {
                  return openBlock(), createBlock(_sfc_main$3, {
                    key: item.id,
                    file: item,
                    "list-type": props.listType,
                    onRemove: removeFile,
                    onRetry: onFileUploadRetry,
                    onReplace: onFileReplace
                  }, createSlots({
                    _: 2
                    /* DYNAMIC */
                  }, [
                    renderList(unref(filterSlots)(_ctx.$slots, unref(slot).names), (name) => {
                      return {
                        name,
                        fn: withCtx((slotData) => [
                          renderSlot(_ctx.$slots, name, mergeProps({ ref_for: true }, slotData))
                        ])
                      };
                    })
                  ]), 1032, ["file", "list-type"]);
                }),
                128
                /* KEYED_FRAGMENT */
              )),
              props.listType === "picture-card" ? (openBlock(), createElementBlock(
                "div",
                {
                  key: 0,
                  class: normalizeClass(["o-upload-card-add", {
                    "is-disabled": props.disabled
                  }]),
                  onClick: doSelect
                },
                [
                  createElementVNode("div", null, [
                    renderSlot(_ctx.$slots, "select-add", {}, () => [
                      createVNode(unref(IconAdd), { class: "o-upload-card-add-icon" }),
                      createElementVNode("div", _hoisted_3, [
                        renderSlot(_ctx.$slots, "select-add-label", {}, () => [
                          createTextVNode(
                            toDisplayString(props.btnLabel ?? unref(t)("upload.buttonLabel")),
                            1
                            /* TEXT */
                          )
                        ])
                      ])
                    ])
                  ])
                ],
                2
                /* CLASS */
              )) : createCommentVNode("v-if", true)
            ],
            2
            /* CLASS */
          )
        ],
        2
        /* CLASS */
      );
    };
  }
});
export {
  _sfc_main as default
};
