"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.beforeUploadFile = beforeUploadFile;
exports.isAcceptFile = isAcceptFile;
exports.uploadFile = uploadFile;

var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));

var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));

var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));

var _mobx = require("mobx");

var _AttachmentFileChunk = _interopRequireDefault(require("../data-set/AttachmentFileChunk"));

var _utils = require("../data-set/utils");

var _axios = _interopRequireDefault(require("../axios"));

var _promiseQueue = _interopRequireDefault(require("../promise-queue"));

var _localeContext = require("../locale-context");

var _formatter = require("../formatter");

var _UploadError = _interopRequireDefault(require("./UploadError"));

function getAxios(context) {
  return context.getConfig('axios') || _axios["default"];
}

function isAcceptFile(attachment, accept) {
  var acceptTypes = accept.map(function (type) {
    return new RegExp(type.replace(/\./g, '\\.').replace(/\*/g, '.*'));
  });
  var name = attachment.name,
      type = attachment.type;
  return acceptTypes.some(function (acceptType) {
    return acceptType.test(name) || acceptType.test(type);
  });
}

function getUploadAxiosConfig(props, attachment, chunk, attachmentUUID, context, _onUploadProgress) {
  var originFileObj = attachment.originFileObj;

  if (originFileObj) {
    var blob = chunk ? originFileObj.slice(chunk.start, chunk.end) : originFileObj;
    var globalConfig = context.getConfig('attachment');
    var action = props.action,
        data = props.data,
        headers = props.headers,
        _props$fileKey = props.fileKey,
        fileKey = _props$fileKey === void 0 ? globalConfig.defaultFileKey : _props$fileKey,
        withCredentials = props.withCredentials;
    var newHeaders = (0, _objectSpread2["default"])({
      'X-Requested-With': 'XMLHttpRequest'
    }, headers);
    var formData = new FormData();
    formData.append(fileKey, blob);

    if (data) {
      (0, _utils.appendFormData)(formData, data);
    }

    if (action && !chunk) {
      return {
        url: action,
        headers: newHeaders,
        data: formData,
        onUploadProgress: _onUploadProgress,
        method: 'POST',
        withCredentials: withCredentials
      };
    }

    var actionHook = globalConfig.action;

    if (actionHook) {
      var bucketName = props.bucketName,
          bucketDirectory = props.bucketDirectory,
          storageCode = props.storageCode,
          isPublic = props.isPublic;
      var newConfig = typeof actionHook === 'function' ? actionHook({
        attachment: attachment,
        chunk: chunk,
        bucketName: bucketName,
        bucketDirectory: bucketDirectory,
        storageCode: storageCode,
        attachmentUUID: attachmentUUID,
        isPublic: isPublic
      }) : actionHook;
      var customData = newConfig.data,
          customUploadProgress = newConfig.onUploadProgress;

      if (customData) {
        (0, _utils.appendFormData)(formData, customData);
      }

      return (0, _objectSpread2["default"])((0, _objectSpread2["default"])({
        withCredentials: withCredentials,
        method: 'POST'
      }, newConfig), {}, {
        headers: (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, newHeaders), newConfig.headers),
        data: formData,
        onUploadProgress: function onUploadProgress(e) {
          _onUploadProgress(e);

          if (customUploadProgress) {
            customUploadProgress(e);
          }
        }
      });
    }

    throw new Error("Please set configure.attachment.action .");
  }

  throw new Error('AttachmentFile can be uploaded only from input.files or DragEvent.dataTransfer.files');
}

function uploadChunk(_x, _x2, _x3, _x4, _x5) {
  return _uploadChunk.apply(this, arguments);
}

function _uploadChunk() {
  _uploadChunk = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(props, attachment, chunk, attachmentUUID, context) {
    var _context$getConfig, onBeforeUploadChunk, config, resp;

    return _regenerator["default"].wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.prev = 0;
            _context$getConfig = context.getConfig('attachment'), onBeforeUploadChunk = _context$getConfig.onBeforeUploadChunk;
            _context.t0 = !onBeforeUploadChunk;

            if (_context.t0) {
              _context.next = 8;
              break;
            }

            _context.next = 6;
            return onBeforeUploadChunk({
              chunk: chunk,
              attachment: attachment,
              bucketName: props.bucketName,
              bucketDirectory: props.bucketDirectory,
              storageCode: props.storageCode,
              isPublic: props.isPublic,
              attachmentUUID: attachmentUUID
            });

          case 6:
            _context.t1 = _context.sent;
            _context.t0 = _context.t1 !== false;

          case 8:
            if (!_context.t0) {
              _context.next = 15;
              break;
            }

            config = getUploadAxiosConfig(props, attachment, chunk, attachmentUUID, context, (0, _mobx.action)(function (e) {
              chunk.percent = e.total > 0 ? e.loaded / e.total * 100 : 0;
            }));
            _context.next = 12;
            return getAxios(context)(config);

          case 12:
            resp = _context.sent;
            chunk.status = 'success';
            return _context.abrupt("return", resp);

          case 15:
            _context.next = 21;
            break;

          case 17:
            _context.prev = 17;
            _context.t2 = _context["catch"](0);
            chunk.status = 'error';
            throw new _UploadError["default"](_context.t2);

          case 21:
          case "end":
            return _context.stop();
        }
      }
    }, _callee, null, [[0, 17]]);
  }));
  return _uploadChunk.apply(this, arguments);
}

function uploadChunks(props, attachment, chunks, attachmentUUID, context, threads) {
  var length = chunks.length;

  if (length) {
    (0, _mobx.runInAction)(function () {
      attachment.status = 'uploading';
    });
    var queue = new _promiseQueue["default"](threads);
    chunks.forEach(function (chunk) {
      if (chunk.status !== 'success') {
        queue.add(function () {
          return uploadChunk(props, attachment, chunk, attachmentUUID, context);
        });
      }
    });
    return queue.ready();
  }

  return Promise.resolve();
}

function uploadNormalFile(_x6, _x7, _x8, _x9) {
  return _uploadNormalFile.apply(this, arguments);
}

function _uploadNormalFile() {
  _uploadNormalFile = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(props, attachment, attachmentUUID, context) {
    var config, resp;
    return _regenerator["default"].wrap(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            _context2.prev = 0;
            (0, _mobx.runInAction)(function () {
              attachment.status = 'uploading';
            });
            config = getUploadAxiosConfig(props, attachment, undefined, attachmentUUID, context, (0, _mobx.action)(function (e) {
              var percent = e.total > 0 ? e.loaded / e.total * 100 : 0;
              attachment.percent = percent;
              var handleProgress = props.onUploadProgress;

              if (handleProgress) {
                handleProgress(percent, attachment);
              }
            }));
            _context2.next = 5;
            return getAxios(context)(config);

          case 5:
            resp = _context2.sent;
            attachment.percent = 100;
            return _context2.abrupt("return", new Promise(function (resolve) {
              setTimeout(function () {
                return resolve(resp);
              }, 0);
            }));

          case 10:
            _context2.prev = 10;
            _context2.t0 = _context2["catch"](0);
            throw new _UploadError["default"](_context2.t0);

          case 13:
          case "end":
            return _context2.stop();
        }
      }
    }, _callee2, null, [[0, 10]]);
  }));
  return _uploadNormalFile.apply(this, arguments);
}

function cuteFile(attachment, chunkSize) {
  var size = attachment.size,
      chunks = attachment.chunks;

  if (!chunks) {
    var count = chunkSize ? Math.ceil(size / chunkSize) : 1;
    var start = 0;
    var index = 0;
    var len;
    var newChunks = [];

    while (index < count) {
      len = Math.min(chunkSize, size - start);
      newChunks.push(new _AttachmentFileChunk["default"]({
        file: attachment,
        total: size,
        start: start,
        end: chunkSize ? start + len : size,
        index: index
      }));
      index += 1;
      start += len;
    }

    if (newChunks.length > 1) {
      attachment.chunks = newChunks;
    }

    return newChunks;
  }

  return chunks;
}

function beforeUploadFile(_x10, _x11, _x12) {
  return _beforeUploadFile.apply(this, arguments);
}

function _beforeUploadFile() {
  _beforeUploadFile = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(props, context, attachment) {
    var attachments,
        useChunk,
        globalConfig,
        accept,
        _props$fileSize,
        fileSize,
        fetchFileSize,
        onBeforeUpload,
        beforeUpload,
        _args3 = arguments;

    return _regenerator["default"].wrap(function _callee3$(_context3) {
      while (1) {
        switch (_context3.prev = _context3.next) {
          case 0:
            attachments = _args3.length > 3 && _args3[3] !== undefined ? _args3[3] : [];
            useChunk = _args3.length > 4 ? _args3[4] : undefined;
            globalConfig = context.getConfig('attachment');
            accept = props.accept;

            if (!(accept && !isAcceptFile(attachment, accept))) {
              _context3.next = 7;
              break;
            }

            (0, _mobx.runInAction)(function () {
              attachment.status = 'error';
              attachment.invalid = true;
              attachment.errorMessage = (0, _localeContext.$l)('Attachment', 'file_type_mismatch', undefined, {
                types: accept.join(',')
              });
            });
            return _context3.abrupt("return");

          case 7:
            _props$fileSize = props.fileSize, fileSize = _props$fileSize === void 0 ? globalConfig.defaultFileSize : _props$fileSize;
            fetchFileSize = globalConfig.fetchFileSize;

            if (!fetchFileSize) {
              _context3.next = 13;
              break;
            }

            _context3.next = 12;
            return fetchFileSize({
              bucketName: props.bucketName,
              bucketDirectory: props.bucketDirectory,
              storageCode: props.storageCode,
              isPublic: props.isPublic
            });

          case 12:
            fileSize = _context3.sent;

          case 13:
            if (!(fileSize && fileSize > 0 && attachment.size > fileSize)) {
              _context3.next = 16;
              break;
            }

            (0, _mobx.runInAction)(function () {
              attachment.status = 'error';
              attachment.invalid = true;
              attachment.errorMessage = (0, _localeContext.$l)('Attachment', 'file_max_size', undefined, {
                size: (0, _formatter.formatFileSize)(fileSize)
              });
            });
            return _context3.abrupt("return");

          case 16:
            onBeforeUpload = globalConfig.onBeforeUpload;
            _context3.t0 = onBeforeUpload;

            if (!_context3.t0) {
              _context3.next = 23;
              break;
            }

            _context3.next = 21;
            return onBeforeUpload(attachment, attachments, {
              useChunk: useChunk,
              bucketName: props.bucketName,
              bucketDirectory: props.bucketDirectory,
              storageCode: props.storageCode,
              isPublic: props.isPublic
            });

          case 21:
            _context3.t1 = _context3.sent;
            _context3.t0 = _context3.t1 === false;

          case 23:
            if (!_context3.t0) {
              _context3.next = 25;
              break;
            }

            return _context3.abrupt("return", false);

          case 25:
            beforeUpload = props.beforeUpload;
            _context3.t2 = beforeUpload;

            if (!_context3.t2) {
              _context3.next = 32;
              break;
            }

            _context3.next = 30;
            return beforeUpload(attachment, attachments);

          case 30:
            _context3.t3 = _context3.sent;
            _context3.t2 = _context3.t3 === false;

          case 32:
            return _context3.abrupt("return", !_context3.t2);

          case 33:
          case "end":
            return _context3.stop();
        }
      }
    }, _callee3);
  }));
  return _beforeUploadFile.apply(this, arguments);
}

function uploadFile(_x13, _x14, _x15, _x16, _x17, _x18) {
  return _uploadFile.apply(this, arguments);
}

function _uploadFile() {
  _uploadFile = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(props, attachment, attachmentUUID, context, chunkSize, useChunk) {
    var chunks, globalConfig, _props$chunkThreads, chunkThreads;

    return _regenerator["default"].wrap(function _callee4$(_context4) {
      while (1) {
        switch (_context4.prev = _context4.next) {
          case 0:
            if (!useChunk) {
              _context4.next = 5;
              break;
            }

            chunks = cuteFile(attachment, chunkSize);
            globalConfig = context.getConfig('attachment');
            _props$chunkThreads = props.chunkThreads, chunkThreads = _props$chunkThreads === void 0 ? globalConfig.defaultChunkThreads : _props$chunkThreads;
            return _context4.abrupt("return", uploadChunks(props, attachment, chunks.slice(), attachmentUUID, context, Math.min(chunks.length, chunkThreads)));

          case 5:
            return _context4.abrupt("return", uploadNormalFile(props, attachment, attachmentUUID, context));

          case 6:
          case "end":
            return _context4.stop();
        }
      }
    }, _callee4);
  }));
  return _uploadFile.apply(this, arguments);
}
//# sourceMappingURL=utils.js.map
