"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _vue = require("vue");
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _request = _interopRequireDefault(require("./request"));
var _uid2 = _interopRequireDefault(require("./uid"));
var _attrAccept = _interopRequireDefault(require("./attr-accept"));
var _traverseFileTree = _interopRequireDefault(require("./traverseFileTree"));
var _interface = require("./interface");
var _pickAttrs = _interopRequireDefault(require("../_util/pickAttrs"));
var _partition = _interopRequireDefault(require("lodash/partition"));
var _excluded = ["componentTag", "prefixCls", "disabled", "id", "multiple", "accept", "capture", "directory", "openFileDialogOnClick", "onMouseenter", "onMouseleave"];
var _default2 = (0, _vue.defineComponent)({
  name: 'AjaxUploader',
  inheritAttrs: false,
  props: (0, _interface.uploadProps)(),
  setup: function setup(props, _ref) {
    var slots = _ref.slots,
      attrs = _ref.attrs,
      expose = _ref.expose;
    var uid = (0, _vue.ref)((0, _uid2.default)());
    var reqs = {};
    var fileInput = (0, _vue.ref)();
    var isMounted = false;
    /**
     * Process file before upload. When all the file is ready, we start upload.
     */
    var processFile = /*#__PURE__*/function () {
      var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(file, fileList) {
        var beforeUpload, transformedFile, action, mergedAction, data, mergedData, parsedData, parsedFile, mergedParsedFile;
        return _regenerator.default.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                beforeUpload = props.beforeUpload;
                transformedFile = file;
                if (!beforeUpload) {
                  _context.next = 14;
                  break;
                }
                _context.prev = 3;
                _context.next = 6;
                return beforeUpload(file, fileList);
              case 6:
                transformedFile = _context.sent;
                _context.next = 12;
                break;
              case 9:
                _context.prev = 9;
                _context.t0 = _context["catch"](3);
                // Rejection will also trade as false
                transformedFile = false;
              case 12:
                if (!(transformedFile === false)) {
                  _context.next = 14;
                  break;
                }
                return _context.abrupt("return", {
                  origin: file,
                  parsedFile: null,
                  action: null,
                  data: null
                });
              case 14:
                // Get latest action
                action = props.action;
                if (!(typeof action === 'function')) {
                  _context.next = 21;
                  break;
                }
                _context.next = 18;
                return action(file);
              case 18:
                mergedAction = _context.sent;
                _context.next = 22;
                break;
              case 21:
                mergedAction = action;
              case 22:
                // Get latest data
                data = props.data;
                if (!(typeof data === 'function')) {
                  _context.next = 29;
                  break;
                }
                _context.next = 26;
                return data(file);
              case 26:
                mergedData = _context.sent;
                _context.next = 30;
                break;
              case 29:
                mergedData = data;
              case 30:
                parsedData =
                // string type is from legacy `transformFile`.
                // Not sure if this will work since no related test case works with it
                ((0, _typeof2.default)(transformedFile) === 'object' || typeof transformedFile === 'string') && transformedFile ? transformedFile : file;
                if (parsedData instanceof File) {
                  parsedFile = parsedData;
                } else {
                  parsedFile = new File([parsedData], file.name, {
                    type: file.type
                  });
                }
                mergedParsedFile = parsedFile;
                mergedParsedFile.uid = file.uid;
                return _context.abrupt("return", {
                  origin: file,
                  data: mergedData,
                  parsedFile: mergedParsedFile,
                  action: mergedAction
                });
              case 35:
              case "end":
                return _context.stop();
            }
          }
        }, _callee, null, [[3, 9]]);
      }));
      return function processFile(_x, _x2) {
        return _ref2.apply(this, arguments);
      };
    }();
    var post = function post(_ref3) {
      var data = _ref3.data,
        origin = _ref3.origin,
        action = _ref3.action,
        parsedFile = _ref3.parsedFile;
      if (!isMounted) {
        return;
      }
      var onStart = props.onStart,
        customRequest = props.customRequest,
        name = props.name,
        headers = props.headers,
        withCredentials = props.withCredentials,
        method = props.method;
      var uid = origin.uid;
      var request = customRequest || _request.default;
      var requestOption = {
        action: action,
        filename: name,
        data: data,
        file: parsedFile,
        headers: headers,
        withCredentials: withCredentials,
        method: method || 'post',
        onProgress: function onProgress(e) {
          var onProgress = props.onProgress;
          onProgress === null || onProgress === void 0 ? void 0 : onProgress(e, parsedFile);
        },
        onSuccess: function onSuccess(ret, xhr) {
          var onSuccess = props.onSuccess;
          onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(ret, parsedFile, xhr);
          delete reqs[uid];
        },
        onError: function onError(err, ret) {
          var onError = props.onError;
          onError === null || onError === void 0 ? void 0 : onError(err, ret, parsedFile);
          delete reqs[uid];
        }
      };
      onStart(origin);
      reqs[uid] = request(requestOption);
    };
    var reset = function reset() {
      uid.value = (0, _uid2.default)();
    };
    var abort = function abort(file) {
      if (file) {
        var _uid = file.uid ? file.uid : file;
        if (reqs[_uid] && reqs[_uid].abort) {
          reqs[_uid].abort();
        }
        delete reqs[_uid];
      } else {
        Object.keys(reqs).forEach(function (uid) {
          if (reqs[uid] && reqs[uid].abort) {
            reqs[uid].abort();
          }
          delete reqs[uid];
        });
      }
    };
    (0, _vue.onMounted)(function () {
      isMounted = true;
    });
    (0, _vue.onBeforeUnmount)(function () {
      isMounted = false;
      abort();
    });
    var uploadFiles = function uploadFiles(files) {
      var originFiles = (0, _toConsumableArray2.default)(files);
      var postFiles = originFiles.map(function (file) {
        // eslint-disable-next-line no-param-reassign
        file.uid = (0, _uid2.default)();
        return processFile(file, originFiles);
      });
      // Batch upload files
      Promise.all(postFiles).then(function (fileList) {
        var onBatchStart = props.onBatchStart;
        onBatchStart === null || onBatchStart === void 0 ? void 0 : onBatchStart(fileList.map(function (_ref4) {
          var origin = _ref4.origin,
            parsedFile = _ref4.parsedFile;
          return {
            file: origin,
            parsedFile: parsedFile
          };
        }));
        fileList.filter(function (file) {
          return file.parsedFile !== null;
        }).forEach(function (file) {
          post(file);
        });
      });
    };
    var onChange = function onChange(e) {
      var accept = props.accept,
        directory = props.directory;
      var files = e.target.files;
      var acceptedFiles = (0, _toConsumableArray2.default)(files).filter(function (file) {
        return !directory || (0, _attrAccept.default)(file, accept);
      });
      uploadFiles(acceptedFiles);
      reset();
    };
    var onClick = function onClick(e) {
      var el = fileInput.value;
      if (!el) {
        return;
      }
      var onClick = props.onClick;
      // TODO
      // if (children && (children as any).type === 'button') {
      //   const parent = el.parentNode as HTMLInputElement;
      //   parent.focus();
      //   parent.querySelector('button').blur();
      // }
      el.click();
      if (onClick) {
        onClick(e);
      }
    };
    var onKeyDown = function onKeyDown(e) {
      if (e.key === 'Enter') {
        onClick(e);
      }
    };
    var onFileDrop = function onFileDrop(e) {
      var multiple = props.multiple;
      e.preventDefault();
      if (e.type === 'dragover') {
        return;
      }
      if (props.directory) {
        (0, _traverseFileTree.default)(Array.prototype.slice.call(e.dataTransfer.items), uploadFiles, function (_file) {
          return (0, _attrAccept.default)(_file, props.accept);
        });
      } else {
        var files = (0, _partition.default)(Array.prototype.slice.call(e.dataTransfer.files), function (file) {
          return (0, _attrAccept.default)(file, props.accept);
        });
        var successFiles = files[0];
        var errorFiles = files[1];
        if (multiple === false) {
          successFiles = successFiles.slice(0, 1);
        }
        uploadFiles(successFiles);
        if (errorFiles.length && props.onReject) props.onReject(errorFiles);
      }
    };
    expose({
      abort: abort
    });
    return function () {
      var _cls, _slots$default;
      var Tag = props.componentTag,
        prefixCls = props.prefixCls,
        disabled = props.disabled,
        id = props.id,
        multiple = props.multiple,
        accept = props.accept,
        capture = props.capture,
        directory = props.directory,
        openFileDialogOnClick = props.openFileDialogOnClick,
        onMouseenter = props.onMouseenter,
        onMouseleave = props.onMouseleave,
        otherProps = (0, _objectWithoutProperties2.default)(props, _excluded);
      var cls = (_cls = {}, (0, _defineProperty2.default)(_cls, prefixCls, true), (0, _defineProperty2.default)(_cls, "".concat(prefixCls, "-disabled"), disabled), (0, _defineProperty2.default)(_cls, attrs.class, !!attrs.class), _cls);
      // because input don't have directory/webkitdirectory type declaration
      var dirProps = directory ? {
        directory: 'directory',
        webkitdirectory: 'webkitdirectory'
      } : {};
      var events = disabled ? {} : {
        onClick: openFileDialogOnClick ? onClick : function () {},
        onKeydown: openFileDialogOnClick ? onKeyDown : function () {},
        onMouseenter: onMouseenter,
        onMouseleave: onMouseleave,
        onDrop: onFileDrop,
        onDragover: onFileDrop,
        tabindex: '0'
      };
      return (0, _vue.createVNode)(Tag, (0, _objectSpread2.default)((0, _objectSpread2.default)({}, events), {}, {
        "class": cls,
        "role": "button",
        "style": attrs.style
      }), {
        default: function _default() {
          return [(0, _vue.createVNode)("input", (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, (0, _pickAttrs.default)(otherProps, {
            aria: true,
            data: true
          })), {}, {
            "id": id,
            "type": "file",
            "ref": fileInput,
            "onClick": function onClick(e) {
              return e.stopPropagation();
            },
            "key": uid.value,
            "style": {
              display: 'none'
            },
            "accept": accept
          }, dirProps), {}, {
            "multiple": multiple,
            "onChange": onChange
          }, capture != null ? {
            capture: capture
          } : {}), null), (_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots)];
        }
      });
    };
  }
});
exports.default = _default2;