import "./index.css";
import _Promise from "@babel/runtime-corejs2/core-js/promise";
import "core-js/modules/web.dom.iterable";

/* script */
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
import GdFile from './gd-file';
import Icon from '../icon';
import { componentMixin, createComponentName } from '../../utils/base';
import Oss from '../../service/oss';
const TYPE2CN = {
  image: '图片',
  text: '文本',
  audio: '音频',
  video: '视频',
  application: '二进制'
};
const __vue_script__ = {
  name: createComponentName('upload'),
  components: {
    Icon
  },
  mixins: [componentMixin],
  // TODO: fileList 支持 v-model
  // model: {
  //     prop: 'fileList',
  //     event: 'update',
  // },
  props: {
    // 接受上传的文件类型
    accept: {
      type: String,
      default: 'image/jpeg, image/png, image/gif'
    },

    /**
     * 上传前处理钩子
     * @args { GdFile }
     * @return { Promise | boolean | File | Blob | GdFile } 如果返回 false 将会终止上传并删除文件
     */
    beforeUpload: {
      // `(gdFile): Promise | boolean | File | Blob | GdFile`
      type: Function
    },
    action: {
      type: Function
    },
    // 上传文件夹, IE 不支持
    directory: {
      type: Boolean,
      default: false
    },
    // 是否支持多选文件
    multiple: {
      type: Boolean,
      default: false
    },
    // 选择文件立即上传
    autoUpload: {
      type: Boolean,
      default: true
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false
    },
    // 最大上传数目
    limit: {
      type: Number,
      // 0 表示 不限制
      default: 0
    },
    concurrent: {
      type: Number,
      default: 1
    },
    type: {
      // `card` `normal`
      type: String,
      default: 'normal'
    }
  },

  data() {
    return {
      fileList: []
    };
  },

  created() {
    this.willUploadFileds = [];
  },

  methods: {
    onClick() {
      if (!this.disabled && this.$refs.input) this.$refs.input.click();
    },

    verifyAccept(type) {
      if (this.accept && this.accept !== '*') {
        const reg = new RegExp(this.accept.split(',').map(type => type.trim()).join('|').toLowerCase());
        return reg.test(type.toLowerCase());
      }

      return true;
    },

    accepterrorText() {
      if (this.accept) {
        const types = this.accept.replace(/\s+/g, '').split(',').map(MIME => {
          const [type, subtype] = MIME.toLowerCase().split('/');

          if (subtype === '*') {
            return TYPE2CN[type] || type;
          }

          return subtype.toUpperCase();
        }).join('/');
        return `仅支持${types}文件`;
      }

      return '无效的文件格式';
    },

    onError(error, gdFile) {
      this.removeFile(gdFile);

      if (error.message === 'stop') {
        gdFile.status = 'cancel';
        return;
      }

      gdFile.error = error;
      gdFile.status = 'error';
      this.$emit('error', error, gdFile);
    },

    onChange(e) {
      const files = []; // 如果使用 [...e.target.files] 编译到 lib 会转成 e.target.files.concat() 导致报错

      for (const file of e.target.files) {
        files.push(file);
      }

      if (this.limit && files.length + this.fileList.length > this.limit) {
        // 超出限上线触发
        this.$emit('exceed', files, this.fileList);
        return;
      }

      const gdFiles = files.map(file => {
        const gdFile = new GdFile(file);

        if (!this.verifyAccept(gdFile.type)) {
          const error = new Error(this.accepterrorText());
          this.onError(error, gdFile);
          return false;
        }

        return gdFile;
      }).filter(f => f);
      this.$refs.input.value = null;
      this.$emit('change', gdFiles);
      gdFiles.forEach(gdFile => {
        this.fileList.push(gdFile);

        if (this.autoUpload) {
          this.uplaodFile(gdFile);
        }

        if (this.type === 'card') {
          gdFile.src = gdFile.toURL();
        }
      });
    },

    async uplaodFile(gdFile) {
      /**
       * TODO: 支持其他格式上传
      */
      if (!/image\//.test(gdFile.type)) {
        return this.onError(new Error('目前只支持上传图片文件'), gdFile);
      }

      if (this.beforeUpload) {
        let res;

        try {
          let res = await this.beforeUpload(gdFile);
          if (!res) return this.removeFile(gdFile);
        } catch (error) {
          return this.removeFile(gdFile);
        }

        const type = Object.prototype.toString.call(res);

        if (type === '[object Blob]') {
          gdFile = new File([res], gdFile.name, {
            type: gdFile.type
          });
          gdFile.originFile = gdFile;
        } else if (type === '[object File]') {
          for (const key in res) {
            if (res.hasOwnProperty(key)) {
              gdFile[key] = res[key];
              gdFile.originFile = gdFile;
            }
          }
        }
      }

      if (this.concurrent && this.fileList.filter(f => f.status === 'uploading').length >= this.concurrent) {
        return this.willUploadFileds.push(gdFile);
      }

      await this.post(gdFile);
      const num = this.concurrent - this.fileList.filter(f => f.status === 'uploading').length;

      if (this.concurrent && num) {
        const files = this.willUploadFileds.splice(0, num);
        files.forEach(file => this.uplaodFile(file));
      }
    },

    removeFile(gdFile) {
      gdFile.status = 'error';
      const index = this.fileList.indexOf(gdFile);

      if (index > -1) {
        this.$emit('remove', gdFile, this.fileList);
        this.fileList.splice(index, 1);
      }
    },

    post(gdFile) {
      gdFile.status = 'uploading';
      const oss = new Oss();

      gdFile.cancel = () => oss.cancel('stop');

      return oss.uploadFile(gdFile.originFile, {
        onProgress: e => {
          gdFile.percent = e.percent;
          this.$emit('progress', e, gdFile, this.fileList);
        }
      }).then(src => {
        gdFile.src = src;
        gdFile.status = 'done';
        gdFile.cancel = null;
        this.$emit('success', gdFile, this.fileList);
      }).catch(error => {
        this.onError(error, gdFile);
      });
    },

    /**
     * @vuese
     * 上传所有 status: 'ready' 的文件列表
     */
    async uploadFiles() {
      await _Promise.all(this.fileList.filter(f => f.status === 'ready').map(f => this.uplaodFile(f)));
      return this.fileList;
    },

    cancel(gdFile) {
      const index = this.willUploadFileds.indexOf(gdFile);

      if (index > -1) {
        this.willUploadFileds.splice(index, 1);
      }

      if (gdFile.cancel) {
        gdFile.cancel();
        gdFile.cancel = null;
        gdFile.status = 'ready';
      }
    },

    cancelAll() {
      this.fileList.forEach(f => this.cancel(f));
    },

    /**
     * @vuese
     * 清空文件列表
     */
    clearFiles() {
      this.fileList = [];
    }

  }
};
/* template */

var __vue_render__ = function () {
  var _vm = this;

  var _h = _vm.$createElement;

  var _c = _vm._self._c || _h;

  return _c("div", {
    class: _vm.bem(),
    attrs: {
      disabled: _vm.disabled
    }
  }, [_vm.type === "card" ? _c("div", {
    class: _vm.bem("card-list")
  }, [_vm._l(_vm.fileList, function (file) {
    return _c("div", {
      key: file.id,
      class: _vm.bem("card")
    }, [_c("i", {
      class: _vm.bem("remove-btn"),
      on: {
        click: function ($event) {
          _vm.removeFile(file);
        }
      }
    }, [_c("icon", {
      attrs: {
        name: "close",
        color: "#fff",
        size: "small"
      }
    })], 1), _vm._v(" "), _c("img", {
      class: _vm.bem("thumbnail"),
      attrs: {
        src: file.src
      }
    })]);
  }), _vm._v(" "), !_vm.limit || _vm.limit !== _vm.fileList.length ? _c("div", {
    class: _vm.bem("card", ["input"]),
    on: {
      click: _vm.onClick
    }
  }, [_vm._t("default", [_c("div", [_c("Icon", {
    attrs: {
      name: "upload",
      size: "big"
    }
  }), _vm._v(" "), _c("div", [_vm._v("上传")])], 1)])], 2) : _vm._e()], 2) : _c("div", {
    on: {
      click: _vm.onClick
    }
  }, [_vm._t("default")], 2), _vm._v(" "), _c("input", {
    ref: "input",
    staticStyle: {
      display: "none"
    },
    attrs: {
      type: "file",
      webkitdirectory: _vm.directory,
      multiple: _vm.multiple,
      disabled: _vm.disabled,
      accept: _vm.accept
    },
    on: {
      change: _vm.onChange
    }
  })]);
};

var __vue_staticRenderFns__ = [];
__vue_render__._withStripped = true;
/* style */

const __vue_inject_styles__ = undefined;
/* scoped */

const __vue_scope_id__ = undefined;
/* module identifier */

const __vue_module_identifier__ = undefined;
/* functional template */

const __vue_is_functional_template__ = false;
/* component normalizer */

import __vue_normalize__ from '../../utils/vue-normalize-component.js';
/* style inject */

/* style inject SSR */

export default __vue_normalize__({
  render: __vue_render__,
  staticRenderFns: __vue_staticRenderFns__
}, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, undefined, undefined);