text: import { createNamespace, addUnit } from '../utils';
  import { toArray, readFile, isOversize, isImageFile } from './utils';
  import Icon from '../icon';
  import Image from '../image';
  import ImagePreview from '../image-preview';
  
  const [createComponent, bem] = createNamespace('uploader');
  
  export default createComponent({
    inheritAttrs: false,
  
    model: {
      prop: 'fileList'
    },
  
    props: {
      disabled: Boolean,
      uploadText: String,
      afterRead: Function,
      beforeRead: Function,
      previewSize: [Number, String],
      name: {
        type: [Number, String],
        default: ''
      },
      accept: {
        type: String,
        default: 'image/*'
      },
      fileList: {
        type: Array,
        default: () => []
      },
      maxSize: {
        type: Number,
        default: Number.MAX_VALUE
      },
      maxCount: {
        type: Number,
        default: Number.MAX_VALUE
      },
      previewImage: {
        type: Boolean,
        default: true
      },
      resultType: {
        type: String,
        default: 'dataUrl'
      }
    },
  
    computed: {
      detail() {
        return {
          name: this.name
        };
      },
  
      previewSizeWithUnit() {
        return addUnit(this.previewSize);
      }
    },
  
    methods: {
      onChange(event) {
        let { files } = event.target;
  
        if (this.disabled || !files.length) {
          return;
        }
  
        files = files.length === 1 ? files[0] : [].slice.call(files);
  
        if (this.beforeRead) {
          const response = this.beforeRead(files, this.detail);
  
          if (!response) {
            this.resetInput();
            return;
          }
  
          if (response.then) {
            response
              .then(() => {
                this.readFile(files);
              })
              .catch(this.resetInput);
  
            return;
          }
        }
  
        this.readFile(files);
      },
  
      readFile(files) {
        const oversize = isOversize(files, this.maxSize);
  
        if (Array.isArray(files)) {
          const maxCount = this.maxCount - this.fileList.length;
  
          if (files.length > maxCount) {
            files = files.slice(0, maxCount);
          }
  
          Promise.all(files.map(file => readFile(file, this.resultType))).then(contents => {
            const fileList = files.map((file, index) => ({
              file,
              content: contents[index]
            }));
  
            this.onAfterRead(fileList, oversize);
          });
        } else {
          readFile(files, this.resultType).then(content => {
            this.onAfterRead({ file: files, content }, oversize);
          });
        }
      },
  
      onAfterRead(files, oversize) {
        if (oversize) {
          this.$emit('oversize', files, this.detail);
          return;
        }
  
        this.resetInput();
        this.$emit('input', [...this.fileList, ...toArray(files)]);
  
        if (this.afterRead) {
          this.afterRead(files, this.detail);
        }
      },
  
      onDelete(file, index) {
        const fileList = this.fileList.slice(0);
        fileList.splice(index, 1);
  
        this.$emit('input', fileList);
        this.$emit('delete', file);
      },
  
      resetInput() {
        /* istanbul ignore else */
        if (this.$refs.input) {
          this.$refs.input.value = '';
        }
      },
  
      onPreviewImage(item) {
        const imageFiles = this.fileList
          .filter(item => isImageFile(item))
          .map(item => item.content || item.url);
  
        ImagePreview({
          images: imageFiles,
          startPosition: imageFiles.indexOf(item.content || item.url)
        });
      },
  
      renderPreview() {
        if (!this.previewImage) {
          return;
        }
  
        return this.fileList.map((item, index) => (
          <div class={bem('preview')}>
            {isImageFile(item) ? (
              <Image
                fit="cover"
                src={item.content || item.url}
                class={bem('preview-image')}
                width={this.previewSize}
                height={this.previewSize}
                onClick={() => {
                  this.onPreviewImage(item);
                }}
              />
            ) : (
              <div
                class={bem('file')}
                style={{
                  width: this.previewSizeWithUnit,
                  height: this.previewSizeWithUnit
                }}
              >
                <Icon class={bem('file-icon')} name="description" />
                <div class={[bem('file-name'), 'van-ellipsis']}>
                  {item.file ? item.file.name : item.url}
                </div>
              </div>
            )}
            <Icon
              name="delete"
              class={bem('preview-delete')}
              onClick={() => {
                this.onDelete(item, index);
              }}
            />
          </div>
        ));
      },
  
      renderUpload() {
        if (this.fileList.length >= this.maxCount) {
          return;
        }
  
        const slot = this.slots();
  
        const Input = (
          <input
            {...{ attrs: this.$attrs }}
            ref="input"
            type="file"
            accept={this.accept}
            class={bem('input')}
            disabled={this.disabled}
            onChange={this.onChange}
          />
        );
  
        if (slot) {
          return (
            <div class={bem('input-wrapper')}>
              {slot}
              {Input}
            </div>
          );
        }
  
        let style;
        if (this.previewSize) {
          const size = this.previewSizeWithUnit;
          style = {
            width: size,
            height: size
          };
        }
  
        return (
          <div class={bem('upload')} style={style}>
            <Icon name="plus" class={bem('upload-icon')} />
            {this.uploadText && <span class={bem('upload-text')}>{this.uploadText}</span>}
            {Input}
          </div>
        );
      }
    },
  
    render() {
      return (
        <div class={bem()}>
          <div class={bem('wrapper')}>
            {this.renderPreview()}
            {this.renderUpload()}
          </div>
        </div>
      );
    }
  });
  