<script>
import UploadList from './upload-list';
import Upload from './upload';
import ImageEditor from '../../image-editor';
import ElProgress from 'bml-workstand-ui/packages/progress';
import Migrating from 'bml-workstand-ui/src/mixins/migrating';

function noop() {}

export default {
  name: 'BmlUpload',

  mixins: [Migrating],

  components: {
    ElProgress,
    UploadList,
    Upload,
    ImageEditor
  },
  provide() {
    return {
      uploader: this
    };
  },
  inject: {
    bmlForm: {
      default: ''
    }
  },
  props: {
    action: {
      type: String,
      required: true
    },
    viewActions:{
      type: Boolean,
      default: false
    },
    previewable: {
      type: Boolean,
      default: false
    },
    editable: {
      type: Boolean,
      default: false
    },
    readonly: {
      type: Boolean,
      default: false
    },
    // 剪裁图片的宽
		editorWidth: {
			type: Number,
			default: 196
		},
		// 剪裁图片的高
		editorHeight: {
			type: Number,
			default: 196
		},
    // 列表图片宽
		width: {
			type: String,
			default: '96px'
		},
		// 列表图片高
		height: {
			type: String,
			default: '96px'
		},
    noRotate: {
			type: Boolean,
			default: false
		},
		// 不预览圆形图片
		noCircle: {
			type: Boolean,
			default: false
		},
		// 不预览方形图片
		noSquare: {
			type: Boolean,
			default: false
    },
    // 图片上传格式
		imgFormat: {
			type: String,
			'default': 'png'
		},
		// 图片背景 jpg情况下生效
		imgBgc: {
			type: String,
			'default': '#fff'
		},
    headers: {
      type: Object,
      default() {
        return {};
      }
    },
    data: Object,
    multiple: Boolean,
    name: {
      type: String,
      default: 'file'
    },
    drag: Boolean,
    dragger: Boolean,
    withCredentials: Boolean,
    showFileList: {
      type: Boolean,
      default: true
    },
    accept: String,
    type: {
      type: String,
      default: 'select'
    },
    beforeUpload: Function,
    beforeRemove: Function,
    onRemove: {
      type: Function,
      default: noop
    },
    onChange: {
      type: Function,
      default: noop
    },
    onPreview: {
      type: Function
    },
    onSuccess: {
      type: Function,
      default: noop
    },
    onProgress: {
      type: Function,
      default: noop
    },
    onError: {
      type: Function,
      default: noop
    },
    fileList: {
      type: Array,
      default() {
        return [];
      }
    },
    autoUpload: {
      type: Boolean,
      default: true
    },
    listType: {
      type: String,
      default: 'text' // text,picture,picture-card
    },
    httpRequest: Function,
    disabled: Boolean,
    limit: Number,
    onExceed: {
      type: Function,
      default: noop
    }
  },

  data() {
    return {
      uploadFiles: [],
      dragOver: false,
      draging: false,
      tempIndex: 1,

      showImageEditor: false,
      editFileName:'',
      editImageSource: '',
      edit: true,
    };
  },

  computed: {
    uploadDisabled() {
      return this.disabled || (this.bmlForm || {}).disabled;
    }
  },

  watch: {
    listType(type) {
      if (type === 'picture-card' || type === 'picture') {
        this.uploadFiles = this.uploadFiles.map(file => {
          if (!file.url && file.raw) {
            try {
              file.url = URL.createObjectURL(file.raw);
            } catch (err) {
              console.error('[Element Error][Upload]', err);
            }
          }
          return file;
        });
      }
    },
    fileList: {
      immediate: true,
      handler(fileList) {
        this.uploadFiles = fileList.map(item => {
          item.uid = item.uid || (Date.now() + this.tempIndex++);
          item.status = item.status || 'success';
          return item;
        });
      }
    }
  },

  methods: {
    /**
     * 图像处理开始，
     * 
     * @param (File) - 选择上传的文件
     * @returns （boolean） - true:立即上传、false: 暂不上传
     */
    handleStart(rawFile) {

      /**
       * 编辑模式：图片上传后对照片进行编辑操作
       */
      if(this.editable){
        
        let fn = rawFile.name.slice(0,rawFile.name.length-4);

        this.editImageSource = URL.createObjectURL(rawFile);
        this.editFileName = fn;
        this.edit = true;
        this.showImageEditor = true;
        return false;
      }

      let fileUrl;
      if (this.listType === 'picture-card' || this.listType === 'picture') {
        try {
          fileUrl = URL.createObjectURL(rawFile);
        } catch (err) {
          console.error('[Element Error][Upload]', err);
          return false;
        }
      }

      rawFile.uid = Date.now() + this.tempIndex++;
      let file = {
        status: 'ready',
        name: rawFile.name,
        size: rawFile.size,
        percentage: 0,
        uid: rawFile.uid,
        raw: rawFile,
        url: fileUrl
      };

      this.uploadFiles.push(file);
      this.onChange(file, this.uploadFiles);

      return true;
    },

    /**
     * 图片剪切完成回调
     */
    handleEditSuccess(rawFile) {
      let fileUrl = URL.createObjectURL(rawFile);
      let uid = Date.now() + this.tempIndex++;
      rawFile.uid = uid;
      let file = {
        status: 'ready',
        name: rawFile.name,
        size: rawFile.size,
        percentage: 0,
        uid: uid,
        raw: rawFile,
        url: fileUrl
      };

      // 上传编辑后的文件
      this.$refs['upload-inner'].upload(rawFile);

      this.showImageEditor = false;
      this.uploadFiles.push(file);
      this.onChange(file, this.uploadFiles);
    },

    /**
     * 关闭对话框
     */
    handleClose() {
      this.showImageEditor = false;
    },
    
    handleProgress(ev, rawFile) {
      const file = this.getFile(rawFile);
      this.onProgress(ev, file, this.uploadFiles);
      file.status = 'uploading';
      file.percentage = ev.percent || 0;
    },
    handleSuccess(res, rawFile) {
      const file = this.getFile(rawFile);
      if (file) {
        if (res.url) {
          file.url = res.url;
        }
        if (res.icon) {
          file.icon = res.icon;
        }
        if (res.name) {
          file.name = res.name;
        } 
        if (res.icon) {
          file.icon = res.icon;
        }
        
        file.status = 'success';
        file.response = res;

        this.onSuccess(res, file, this.uploadFiles);
        this.onChange(file, this.uploadFiles);
      }
    },
    handleError(err, rawFile) {
      const file = this.getFile(rawFile);
      const fileList = this.uploadFiles;

      if (file) {
        file.status = 'fail';
      }

      fileList.splice(fileList.indexOf(file), 1);

      this.onError(err, file, this.uploadFiles);
      this.onChange(file, this.uploadFiles);
    },

    handleEdit(file) {

      console.log(file);

      this.editImageSource = URL.createObjectURL(file.raw);
      this.edit = true;
      this.showImageEditor = true;

    },

    handleRemove(file, raw) {
      if (raw) {
        file = this.getFile(raw);
      }
      let doRemove = () => {
        this.abort(file);
        let fileList = this.uploadFiles;
        fileList.splice(fileList.indexOf(file), 1);
        this.onRemove(file, fileList);
      };

      if (!this.beforeRemove) {
        doRemove();
      } else if (typeof this.beforeRemove === 'function') {
        const before = this.beforeRemove(file, this.uploadFiles);
        if (before && before.then) {
          before.then(() => {
            doRemove();
          }, noop);
        } else if (before !== false) {
          doRemove();
        }
      }
    },

    getFile(rawFile) {
      let fileList = this.uploadFiles;
      let target;
      fileList.every(item => {
        target = rawFile.uid === item.uid ? item : null;
        return !target;
      });
      return target;
    },

    selectFile() {
      this.$refs['upload-inner'].handleClick();
    },

    abort(file) {
      this.$refs['upload-inner'].abort(file);
    },

    clearFiles() {
      this.uploadFiles = [];
    },

    submit() {
      this.uploadFiles
        .filter(file => file.status === 'ready')
        .forEach(file => {
          this.$refs['upload-inner'].upload(file.raw);
        });
    }
  },

  beforeDestroy() {
    this.uploadFiles.forEach(file => {
      if (file.url && file.url.indexOf('blob:') === 0) {
        URL.revokeObjectURL(file.url);
      }
    });
  },

  render(h) {
    let uploadList;

    const editorData = {
      props: {
        file: this.editImageSource,
        filename: this.editFileName,
        visible: this.showImageEditor,
        edit: this.edit,
        width: this.editorWidth,
        height: this.editorHeight,
        noRotate: this.noRotate,
        noCircle: this.noCircle,
        noSquare: this.noSquare,
        imgFormat: this.imgFormat,
        imgBgc: this.imgBgc,
        'on-success': this.handleEditSuccess,
        'on-close': this.handleClose
      }
    };

    if (this.showFileList) {
      uploadList = (
        <UploadList
          limit = {this.limit}
          readonly = {this.readonly}
          viewActions={this.viewActions}
          previewable = {this.previewable}
          editable = {this.editable}
          disabled={this.uploadDisabled}
          listType={this.listType}
          width={this.width}
          height={this.height}
          files={this.uploadFiles}
          on-remove={this.handleRemove}
          handlePreview={this.onPreview}
          handleEdit={this.handleEdit}>
          {
            (props) => {
              if (this.$scopedSlots.file) {
                return this.$scopedSlots.file({
                  file: props.file
                });
              }
            }
          }
        </UploadList>
      );
    }

    const uploadData = {
      props: {
        type: this.type,
        drag: this.drag,
        action: this.action,
        multiple: this.multiple,
        'before-upload': this.beforeUpload,
        'with-credentials': this.withCredentials,
        headers: this.headers,
        name: this.name,
        data: this.data,
        accept: this.accept,
        fileList: this.uploadFiles,
        autoUpload: this.autoUpload,
        listType: this.listType,
        disabled: this.uploadDisabled,
        editable: this.editable,
        readonly: this.readonly,
        width: this.width,
        height: this.height,
        limit: this.limit,
        'on-exceed': this.onExceed,
        'on-start': this.handleStart,
        'on-progress': this.handleProgress,
        'on-success': this.handleSuccess,
        'on-error': this.handleError,
        'on-preview': this.onPreview,
        'on-remove': this.handleRemove,
        'http-request': this.httpRequest
      },
      ref: 'upload-inner'
    };

    const trigger = this.$slots.trigger || this.$slots.default;
    const uploadComponent = <upload {...uploadData}>{trigger}</upload>;
    const imageEditorComponent = <image-editor {...editorData}></image-editor>;

    return (
      <div>
        { this.listType !== 'file-card' ? imageEditorComponent : ''}
        { (this.listType === 'picture-card' || this.listType === 'file-card') ? uploadList : ''}
        {
          this.$slots.trigger
            ? [uploadComponent, this.$slots.default]
            : uploadComponent
        }
        {this.$slots.tip}
        { this.listType !== 'picture-card' && this.listType !== 'file-card' ? uploadList : ''}
      </div>
    );
  }
};
</script>
