import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { utils } from 'amos-tool';
import { Overlay, Icon } from 'amos-framework';
import imgStatic from '@gm/graphmod-assets';
import './import.scss';

const progressCount = 1000;
const mmTime = 1000;

/**
 * 文件上传（带进度条）
 *
 * @class FileImport
 * @extends {Component}
 */
class FileImport extends Component {

  static propTypes = {
    visible: PropTypes.bool,
    url: PropTypes.string,
    payload: PropTypes.func,
    headers: PropTypes.object,
    uploadText: PropTypes.string,
    onRefresh: PropTypes.func,
    onImport: PropTypes.func
  };

  static defaultProps = {
    uploadText: '导入'
  };

  constructor(props) {
    super(props);
    this.ot = Date.now();
    this.oloaded = 0;
    this.state = {
      visible: false,
      fileName: '',
      uploadStatus: '0',
      tip: 'noStart',
      value: 0,
      max: 100,
      progress: 0,
      speed: 0,
      units: 'b/s',
      resttime: 0
    };
  }

  componentWillUnmount() {
    this.timer && clearInterval(this.timer);
  }


  onStart = () => {
    this.file.click();
  }

  handleFileChange = (file) => {
    if (file) {
      this.setState({ fileName: (file.target.files[0] || {}).name, tip: 'running', visible: true });
      this.upladFile(file.target.files[0]);
      this.file.value = '';
    } else {
      this.cancleUploadFile();
    }
  }

  handleClose = () => {
    this.setState({
      visible: false,
      fileName: '',
      uploadStatus: '0',
      tip: 'noStart',
      value: 0,
      progress: 0,
      max: 100,
      speed: 0,
      units: 'b/s',
      resttime: 0
    });
    this.props.onImport(false);
  }

  upladFile = (file) => {
    const { url, headers } = this.props;
    const fileObj = file; // js 获取文件对象
    const form = new FormData(); // FormData 对象
    form.append('file', fileObj); // 文件对象

    this.xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
    this.xhr.open('post', url, true); // post方式，url为服务器请求地址，true 该参数规定请求是否异步处理。
    this.xhr.onload = this.uploadFinish; // 请求完成
    this.xhr.onerror = this.uploadFinish; // 请求失败
    this.xhr.upload.onprogress = this.progressFunction;// 【上传进度调用方法实现】
    this.xhr.upload.onloadstart = function () {// 上传开始执行方法
      this.ot = new Date().getTime();   // 设置上传开始时间
      this.oloaded = 0;// 设置上传开始时，以上传的文件大小为0
    };
    // this.xhr.setRequestHeader('token', 'ff114b06-6bf4-4072-8f0a-b2b47b72c554');
    // this.xhr.setRequestHeader('product', 'AMOS-WEB-ADMIN');
    // this.xhr.setRequestHeader('appKey', 'AMOS_ADMIN');
    Object.keys(headers || {}).map(e => {
      this.xhr.setRequestHeader(e, headers[e]);
      return e;
    });
    this.xhr.send(form); // 开始上传，发送form数据
    this.props.onImport(true);
  }

  progressFunction = (evt) => {

    // event.total是需要传输的总字节，event.loaded是已经传输的字节。如果event.lengthComputable不为真，则event.total等于0
    if (evt.lengthComputable) {//
      const progress = Math.round(evt.loaded / evt.total * progressCount);

      this.setState({ progress, max: evt.total, value: evt.loaded });
    }
    const nt = new Date().getTime();// 获取当前时间
    let pertime = (nt - this.ot) / mmTime; // 计算出上次调用该方法时到现在的时间差，单位为s
    this.ot = new Date().getTime(); // 重新赋值时间，用于下次计算

    let perload = evt.loaded - this.oloaded; // 计算该分段上传的文件大小，单位b

    this.oloaded = evt.loaded;// 重新赋值已上传文件大小，用以下次计算
    // 上传速度计算
    let speed = perload / pertime; // 单位b/s
    let bspeed = speed;
    const oneMb = 1024;
    let units = 'b/s';// 单位名称
    if (speed / oneMb > 1) {
      speed = speed / oneMb;
      units = 'k/s';
    }
    if (speed / oneMb > 1) {
      speed = speed / oneMb;
      units = 'M/s';
    }
    speed = speed.toFixed(1);
    console.log('传输测试', evt.total, evt.loaded, bspeed);
    let resttime = 0;
    if (bspeed !== 0) {
      // 剩余时间
      resttime = ((evt.total - evt.loaded) / bspeed).toFixed(1);
    }
    console.log('传输测试', resttime, resttime === 0);
    this.setState({ speed, units, resttime });
    if (parseInt(resttime) === 0) {
      this.setState({ tip: 'parse' });
      this.timer = setInterval(() => {
        let { value, max } = this.state;
        value = value + (((max * 2) - value) * 0.05);
        this.setState({ value });
      }, 200);
    }
  }

  uploadFinish = (evt) => {
    const data = evt.currentTarget;
    const { payload } = this.props;
    const statu = 200;
    if (data.status !== statu) {
      this.setState({ tip: 'error', value: this.state.max * 2 });
      this.timer && clearInterval(this.timer);
      setTimeout(() => this.cancleUploadFile(), progressCount);
    } else {
      if (data.response && utils.isString(data.response)) {
        const response = JSON.parse(data.response);
        if (payload) {
          payload(response).then(d => {
            this.setState({ tip: 'success', value: this.state.max * 2 });
            this.timer && clearInterval(this.timer);
            setTimeout(() => this.cancleUploadFile(), mmTime);
          }).catch(() => {
            this.setState({ tip: 'error', value: this.state.max * 2 });
            this.timer && clearInterval(this.timer);
            setTimeout(() => this.cancleUploadFile(), mmTime);
          });
        } else {
          this.setState({ tip: 'success', value: this.state.max * 2 });
          this.timer && clearInterval(this.timer);
          setTimeout(() => this.cancleUploadFile(), mmTime);
        }
      } else {
        this.setState({ tip: 'error', value: this.state.max * 2 });
        this.timer && clearInterval(this.timer);
        setTimeout(() => this.cancleUploadFile(), mmTime);
      }
    }
    this.props.onRefresh();
  }

  uploadFailed = (evt) => {
    this.setState({ tip: 'error', value: this.state.max * 2 });
    this.timer && clearInterval(this.timer);
    setTimeout(() => this.cancleUploadFile(), mmTime);
  }

  cancleUploadFile = () => {
    this.xhr && this.xhr.abort();
    this.handleClose();
  }

  render() {
    const { visible, tip, value, max, fileName, units, speed, resttime, progress } = this.state;
    return (
      <React.Fragment>
        <Overlay className="gm-tablepage-excel-upload" usePortal={document.body} visible={visible} onClose={this.cancleUploadFile}>
          <div className="gm-tablepage-excel-upload-content">
            <div className="gm-tablepage-excel-upload-header">
              {tip === 'running' && <React.Fragment>
                <img className="gm-tablepage-excel-upload-running" src={imgStatic.mods.running} alt="" /><span>上传中...</span></React.Fragment>}
              {tip === 'success' && <React.Fragment><img src={imgStatic.mods.success} alt="" /><span>导入成功</span></React.Fragment>}
              {tip === 'error' && <React.Fragment><img src={imgStatic.mods.error} alt="" /><span>导入失败</span></React.Fragment>}
              {tip === 'parse' && <React.Fragment>
                <img className="gm-tablepage-excel-upload-running" src={imgStatic.mods.running} alt="" /><span>上传解析中...</span></React.Fragment>}
              <span className="gm-tablepage-excel-upload-data">
                {tip === 'running' && <span>上传进度{progress}%,速度: {speed}{units}, 剩余时间{resttime}s</span>}
                <Icon icon="cross" onClick={this.cancleUploadFile} style={{ fontSize: 16, color: '#08c' }} />
              </span>
            </div>
            <div className="gm-tablepage-excel-upload-body">
              <img className="gm-tablepage-excel-upload-fileicon" src={imgStatic.mods.file} alt="" />
              <span className="gm-tablepage-excel-upload-filename">{fileName}</span>
              <progress
                className="gm-tablepage-excel-upload-progress"
                id="progressBar"
                value={value}
                max={max * 2}
              />
            </div>
          </div>
        </Overlay>
        <input
          ref={node => this.file = node}
          style={{ display: 'none' }}
          className="gm-tablepage-excel-upload-input"
          onChange={this.handleFileChange}
          accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
          type="file"
          name="file"
          multiple="multiple"
        />
      </React.Fragment>
    );
  }
}

export default FileImport;
