// 核心库
import React, { Component } from 'react'
import PropTypes from 'prop-types'
// 组件库
import Canvg from 'canvg'
import html2canvas from 'html2canvas'
import printJS from 'print-js'
import { Button } from 'antd'

class HttpPrint extends Component {
  constructor (props) {
    super(props)
    this.nodesBackup = []
  }

  converSvg = (printDom) => {
    this.nodesBackup = []
    // html2canvas 不支持 svg，所以将 svg 转换成 img
    const canvgs = []
    const svgs = printDom.getElementsByTagName('svg')
    Array.from(svgs).forEach(svg => {
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      const { width, height, color } = window.getComputedStyle(svg)
      svg.setAttribute('width', width)
      svg.setAttribute('height', height)
      svg.setAttribute('fill', color)
      const svg_xml = (new window.XMLSerializer()).serializeToString(svg)
      canvgs.push({
        promiseFunc: Canvg.from(ctx, svg_xml),
        svg,
        canvas
      })
    })

    return Promise.all(canvgs.map(cvg => cvg.promiseFunc)).then(cvgs => {
      cvgs.forEach((v, i) => {
        v.start()

        const parentNode = canvgs[i].svg.parentNode
        const { width, height } = window.getComputedStyle(parentNode)
        const img = document.createElement('img')
        img.style = `width: ${width}; height: ${height}`
        img.src = canvgs[i].canvas.toDataURL()
        this.nodesBackup.push({
          parent: parentNode,
          recover: canvgs[i].svg,
          remove: img
        })
      })
      // 移除 svg，并添加 img，为 html2canvas 截屏做准备
      this.nodesBackup.forEach(node => {
        const { parent, recover, remove } = node
        parent.removeChild(recover)
        parent.appendChild(remove)
      })
    })
  }

  captureDom = (printDom) => {
    // html2canvas 截屏输出 base64 图片文件给 print-js 打印
    return html2canvas(printDom, {
      allowTaint: false,
      useCORS: true
    }).then(canvas => {
      printJS(canvas.toDataURL(), 'image')
      // 还原去除的 svg
      this.nodesBackup.forEach(node => {
        const { parent, recover, remove } = node
        parent.removeChild(remove)
        parent.appendChild(recover)
      })
    })
  }

  handlePrint = () => {
    let printDom = document.getElementsByTagName('body')[0]
    const { type, container } = this.props
    if (container) {
      let targetDom = null
      switch (type) {
        case 'id':
          targetDom = printDom.querySelector(`#${container}`)
          break
        default:
          targetDom = printDom.getElementsByClassName(container)[0]
      }
      targetDom && (printDom = targetDom)
    }
    this.converSvg(printDom).then(() => this.captureDom(printDom))
    this.props.onClick instanceof Function && this.props.onClick()
  }

  render () {
    return <span onClick={this.handlePrint}>{this.props.children ? this.props.children : <Button>打印</Button>}</span>
  }
}

HttpPrint.propTypes = {
  type: PropTypes.string,
  container: PropTypes.string,
  onClick: PropTypes.func
}

HttpPrint.defaultProps = {
  type: 'classname',
  container: 'index-page__mainTabContent',
  onClick: () => null
}

export default HttpPrint
