'use strict';

exports.__esModule = true;

var _find2 = require('lodash/find');

var _find3 = _interopRequireDefault(_find2);

var _isUndefined2 = require('lodash/isUndefined');

var _isUndefined3 = _interopRequireDefault(_isUndefined2);

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

var _react = require('react');

var React = _interopRequireWildcard(_react);

var _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _compose = require('recompose/compose');

var _compose2 = _interopRequireDefault(_compose);

var _rsuiteIntl = require('rsuite-intl');

var _withLocale = require('./IntlProvider/withLocale');

var _withLocale2 = _interopRequireDefault(_withLocale);

var _UploadFileItem = require('./UploadFileItem');

var _UploadFileItem2 = _interopRequireDefault(_UploadFileItem);

var _UploadTrigger = require('./UploadTrigger');

var _UploadTrigger2 = _interopRequireDefault(_UploadTrigger);

var _utils = require('./utils');

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : _defaults(subClass, superClass); }

var guid = function guid() {
  var num = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 8;
  return (Math.random() * 1e18).toString(36).slice(0, num).toUpperCase();
};

var getFiles = function getFiles(event) {
  if (event.dataTransfer && _typeof(event.dataTransfer) === 'object') {
    return event.dataTransfer.files;
  }
  if (event.target) {
    return event.target.files;
  }
  return [];
};

var Uploader = function (_React$Component) {
  _inherits(Uploader, _React$Component);

  function Uploader(props) {
    _classCallCheck(this, Uploader);

    var _this = _possibleConstructorReturn(this, _React$Component.call(this, props));

    _initialiseProps.call(_this);

    var _props$defaultFileLis = props.defaultFileList,
        defaultFileList = _props$defaultFileLis === undefined ? [] : _props$defaultFileLis;

    var fileList = defaultFileList.map(_this.createFile);

    _this.state = {
      fileList: fileList
    };
    return _this;
  }

  Uploader.prototype.getFileList = function getFileList() {
    var fileList = this.props.fileList;

    if ((0, _isUndefined3.default)(fileList)) {
      return this.state.fileList;
    }

    return fileList || [];
  };

  Uploader.prototype.handleAjaxUpload = function handleAjaxUpload() {
    var _this2 = this;

    var shouldUpload = this.props.shouldUpload;

    var fileList = this.getFileList();
    fileList.forEach(function (file) {
      if (shouldUpload && shouldUpload(file) === false) {
        return;
      }

      if (file.status === 'inited') {
        _this2.handleUploadFile(file);
      }
    });

    if (this.input) {
      this.input.value = '';
    }
  };

  Uploader.prototype.updateFileList = function updateFileList(nextFile, callback) {
    var fileList = this.getFileList();
    var nextFileList = fileList.map(function (file) {
      return file.fileKey === nextFile.fileKey ? nextFile : file;
    });
    this.setState({
      fileList: nextFileList
    }, callback);
  };

  Uploader.prototype.renderFileItems = function renderFileItems() {
    var _this3 = this;

    var _props = this.props,
        disabled = _props.disabled,
        listType = _props.listType,
        onPreview = _props.onPreview;

    var fileList = this.getFileList();

    return React.createElement(
      'div',
      { key: 'items', className: this.addPrefix('file-items') },
      fileList.map(function (file, index) {
        return React.createElement(_UploadFileItem2.default, {
          key: file.fileKey || index,
          file: file,
          listType: listType,
          disabled: disabled,
          onPreview: onPreview,
          onReupload: _this3.handleReupload,
          onCancel: _this3.handleRemoveFile
        });
      })
    );
  };

  Uploader.prototype.renderUploadTrigger = function renderUploadTrigger() {
    var _props2 = this.props,
        name = _props2.name,
        multiple = _props2.multiple,
        disabled = _props2.disabled,
        accept = _props2.accept,
        children = _props2.children;


    return React.createElement(
      _UploadTrigger2.default,
      {
        name: name,
        key: 'trigger',
        multiple: multiple,
        disabled: disabled,
        accept: accept,
        innerRef: this.inputRef,
        onChange: this.handleUploadTriggerChange
      },
      children
    );
  };

  Uploader.prototype.render = function render() {
    var _props3 = this.props,
        classPrefix = _props3.classPrefix,
        className = _props3.className,
        listType = _props3.listType,
        locale = _props3.locale;

    var classes = (0, _classnames2.default)(classPrefix, this.addPrefix(listType), className);
    var renderList = [this.renderUploadTrigger(), this.renderFileItems()];

    if (listType === 'picture') {
      renderList.reverse();
    }

    return React.createElement(
      _rsuiteIntl.IntlProvider,
      { locale: locale },
      React.createElement(
        'div',
        { className: classes },
        renderList
      )
    );
  };

  return Uploader;
}(React.Component);

Uploader.defaultProps = {
  autoUpload: true,
  timeout: 0,
  name: 'file',
  multiple: false,
  disabled: false,
  withCredentials: false,
  hasPanel: true,
  data: {},
  listType: 'text'
};
Uploader.handledProps = ['accept', 'action', 'autoUpload', 'children', 'className', 'classPrefix', 'data', 'defaultFileList', 'disabled', 'fileList', 'hasPanel', 'headers', 'listType', 'locale', 'multiple', 'name', 'onChange', 'onError', 'onPreview', 'onProgress', 'onRemove', 'onReupload', 'onSuccess', 'onUpload', 'shouldQueueUpdate', 'shouldUpload', 'timeout', 'withCredentials'];
Uploader.propTypes = {
  action: _propTypes2.default.string.isRequired,
  accept: _propTypes2.default.string,
  autoUpload: _propTypes2.default.bool,
  children: _propTypes2.default.node,
  className: _propTypes2.default.string,
  classPrefix: _propTypes2.default.string,
  defaultFileList: _propTypes2.default.arrayOf(_propTypes2.default.shape({
    name: _propTypes2.default.string.isRequired,
    fileKey: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]).isRequired,

    // https://developer.mozilla.org/zh-CN/docs/Web/API/File
    blobFile: function blobFile() {
      return (typeof File === 'function' ? _propTypes2.default.instanceOf(File) : _propTypes2.default.any).apply(this, arguments);
    },
    status: _propTypes2.default.oneOf(['inited', 'uploading', 'error', 'finished']),
    progress: _propTypes2.default.number
  })),
  fileList: _propTypes2.default.arrayOf(_propTypes2.default.shape({
    name: _propTypes2.default.string.isRequired,
    fileKey: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]).isRequired,
    blobFile: function blobFile() {
      return (typeof File === 'function' ? _propTypes2.default.instanceOf(File) : _propTypes2.default.any).apply(this, arguments);
    },
    status: _propTypes2.default.oneOf(['inited', 'uploading', 'error', 'finished']),
    progress: _propTypes2.default.number
  })),
  data: _propTypes2.default.object,
  multiple: _propTypes2.default.bool,
  disabled: _propTypes2.default.bool,
  name: _propTypes2.default.string.isRequired,
  timeout: _propTypes2.default.number,
  withCredentials: _propTypes2.default.bool,
  headers: _propTypes2.default.object,
  locale: _propTypes2.default.object,
  listType: _propTypes2.default.oneOf(['text', 'picture-text', 'picture']).isRequired,
  shouldQueueUpdate: _propTypes2.default.func,
  shouldUpload: _propTypes2.default.func,
  onChange: _propTypes2.default.func,
  onUpload: _propTypes2.default.func,
  onReupload: _propTypes2.default.func,
  onError: _propTypes2.default.func,
  onPreview: _propTypes2.default.func,
  onSuccess: _propTypes2.default.func,
  onProgress: _propTypes2.default.func,
  onRemove: _propTypes2.default.func
};

var _initialiseProps = function _initialiseProps() {
  var _this4 = this;

  this.handleRemoveFile = function (fileKey) {
    var _props4 = _this4.props,
        onChange = _props4.onChange,
        onRemove = _props4.onRemove;

    var fileList = _this4.getFileList();
    var file = (0, _find3.default)(fileList, function (f) {
      return f.fileKey === fileKey;
    });
    var nextFileList = fileList.filter(function (f) {
      return f.fileKey !== fileKey;
    });

    if (_this4.xhrs[file.fileKey] && _this4.xhrs[file.fileKey].readyState !== 4) {
      _this4.xhrs[file.fileKey].abort();
    }

    _this4.setState({ fileList: nextFileList });

    onRemove && onRemove(file);
    onChange && onChange(nextFileList);
  };

  this.handleUploadTriggerChange = function (event) {
    var _props5 = _this4.props,
        autoUpload = _props5.autoUpload,
        shouldQueueUpdate = _props5.shouldQueueUpdate,
        onChange = _props5.onChange;

    var fileList = _this4.getFileList();
    var files = getFiles(event);
    var newFileList = [];

    Array.from(files).forEach(function (file) {
      newFileList.push({
        blobFile: file,
        name: file.name,
        status: 'inited',
        fileKey: guid()
      });
    });

    var nextFileList = [].concat(fileList, newFileList);

    if (shouldQueueUpdate && shouldQueueUpdate(nextFileList, newFileList) === false) {
      return;
    }

    onChange && onChange(nextFileList);

    _this4.setState({ fileList: nextFileList }, function () {
      autoUpload && _this4.handleAjaxUpload();
    });
  };

  this.handleAjaxUploadSuccess = function (response, file) {
    var onSuccess = _this4.props.onSuccess;

    var nextFile = _extends({}, file, {
      status: 'finished',
      progress: 100
    });
    _this4.updateFileList(nextFile, function () {
      onSuccess && onSuccess(response, nextFile);
    });
  };

  this.handleAjaxUploadError = function (reason, file) {
    var onError = _this4.props.onError;

    var nextFile = _extends({}, file, {
      status: 'error'
    });
    _this4.updateFileList(nextFile, function () {
      onError && onError(reason, nextFile);
    });
  };

  this.handleAjaxUploadProgress = function (percent, file) {
    var onProgress = _this4.props.onProgress;

    var nextFile = _extends({}, file, {
      status: 'uploading',
      progress: percent
    });
    _this4.updateFileList(nextFile, function () {
      onProgress && onProgress(percent, nextFile);
    });
  };

  this.handleUploadFile = function (file) {
    var _props6 = _this4.props,
        name = _props6.name,
        action = _props6.action,
        headers = _props6.headers,
        withCredentials = _props6.withCredentials,
        timeout = _props6.timeout,
        data = _props6.data,
        onUpload = _props6.onUpload;

    var xhr = (0, _utils.ajaxUpload)({
      name: name,
      timeout: timeout,
      headers: headers,
      data: data,
      withCredentials: withCredentials,
      file: file.blobFile,
      url: action,
      onError: function onError(reason) {
        _this4.handleAjaxUploadError(reason, file);
      },
      onSuccess: function onSuccess(resp) {
        _this4.handleAjaxUploadSuccess(resp, file);
      },
      onProgress: function onProgress(percent) {
        _this4.handleAjaxUploadProgress(percent, file);
      }
    });
    _this4.updateFileList(_extends({}, file, {
      status: 'uploading'
    }));
    _this4.xhrs[file.fileKey] = xhr;

    onUpload && onUpload(file);
  };

  this.handleReupload = function (file) {
    var onReupload = _this4.props.onReupload;

    _this4.handleUploadFile(file);
    onReupload && onReupload(file);
  };

  this.createFile = function (file) {
    var fileKey = file.fileKey;

    return _extends({}, file, {
      fileKey: fileKey || guid(),
      progress: 0
    });
  };

  this.addPrefix = function (name) {
    return (0, _utils.prefix)(_this4.props.classPrefix)(name);
  };

  this.xhrs = {};
  this.uploadTrigger = null;

  this.inputRef = function (ref) {
    _this4.input = ref;
  };
};

exports.default = (0, _compose2.default)((0, _withLocale2.default)(['Uploader']), (0, _utils.defaultProps)({
  classPrefix: 'uploader'
}))(Uploader);