import React, { Component } from 'react';
import ConfirmModal from 'components/ConfirmModal';
import JSZip from 'jszip';
import saveAs from 'file-saver';
import { request } from 'utils/fetch';
import { api } from 'constants/config';
import EasyvProgress from 'components/EasyvProgress';
import {getAssetsUrl} from 'utils/utils';
interface IProps {
  list: any[];
  onComplete?: () => void;
}

interface IState {
  visible: boolean;
  total: number;
  loaded: number;
  status: 'success' | 'normal' | 'exception' | 'active';
}

class ExportConstantModal extends Component<IProps, IState> {
  constructor(props) {
    super(props);
    this.state = {
      visible: false,
      total: 0,
      loaded: 0,
      status: 'normal'
    };
  }

  controller: AbortController;

  showModal = () => {
    this.setState({
      visible: true
    });

    this.startExport();
  };

  startExport = async () => {
    this.controller = window.AbortController && new AbortController();
    const { list } = this.props;

    this.setState({
      total: list.length,
      loaded: 0,
      status: 'active'
    });

    const zip = new JSZip();
    try {
      await Promise.all(list.map((d) => this.downloadPkg(zip, d)));

      this.hideModal();
      this.props.onComplete && this.props.onComplete();

      zip.generateAsync({ type: 'blob' }).then((blob) => {
        saveAs(blob, `组件包(${list.length}).constant`);
      });
    } catch (error) {
      console.error('组件导出失败', error);
      this.controller && this.controller.abort();
      this.setState({
        status: 'exception'
      });
    }
  };

  hideModal = () => {
    this.controller && this.controller.abort();
    this.setState({
      visible: false
    });
  };

  zipFiles = (zip, src) => {
    const signal = this.controller && this.controller.signal;
    const path = src.slice(0, src.lastIndexOf('/'));
    const name = src.slice(src.lastIndexOf('/') + 1);

    return fetch(getAssetsUrl(`${src}`), { signal, cache: 'no-store' })
      .then((res) => {
        if (res.status === 200) {
          return res.blob();
        } else {
          return Promise.reject(res.statusText);
        }
      })
      .then((result) => {
        this.setState((prev) => ({
          loaded: prev.loaded + 1
        }));
        zip.folder(path).file(name, result);
      });
  };

  renderStatus = (status) => {
    switch (status) {
      case 'exception':
        return '导出失败，请重试';
      case 'success':
        return '导出成功';
      default:
        return '组件正在导出，请稍后...';
    }
  };

  downloadPkg = async (zip, id) => {
    const signal = this.controller && this.controller.signal;
    const result = await request(api.allTenantConstantExport, { id: id }, { format: 'package' }, undefined, { signal });

    const filePaths = result.url.split('/');
    const filename = filePaths[filePaths.length - 1];

    return fetch(getAssetsUrl(`${result.url}`), { signal, cache: 'no-store' })
      .then((res) => {
        if (res.status === 200) {
          return res.blob();
        } else {
          return Promise.reject(res.statusText);
        }
      })
      .then((result) => {
        this.setState((prev) => ({
          loaded: prev.loaded + 1
        }));
        zip.file(filename, result);
      });
  };

  componentWillUnmount() {
    this.controller && this.controller.abort();
  }

  render() {
    const { visible, total, loaded, status } = this.state;
    const percent = loaded ? Math.round((loaded / total) * 100) : 0;

    return (
      <span>
        <span onClick={this.showModal}>{this.props.children}</span>
        <ConfirmModal visible={visible} title="组件导出" onClose={this.hideModal} footer={false} maskClosable={false}>
          <EasyvProgress
            percent={percent}
            status={status}
            title={this.renderStatus(status)}
            statusMsg={{ exception: <i className="icon iconfont icon-btn_reload click" onClick={this.startExport} title="重试" /> }}
          />
        </ConfirmModal>
      </span>
    );
  }
}

export default ExportConstantModal;
