import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
import { Button, Modal, Tooltip } from 'antd'
import { fetch, apis } from '../../utils/request'

import Style from './style.less'

const fetchQRCode = fetch(apis.image.qrcode)

function encodeParam (o) {
  return Object.keys(o).map((k) => {
    const v = encodeURIComponent(o[k] || '')
    return `${k}=${v}`
  }).join('&')
}

class MiniQRCode extends PureComponent {
  constructor(props) {
    super(props)

    this.state = {
      previewVisible: false,
      qrcode: undefined,
      loading: false,
    }
  }

  componentDidMount() {
    if (this.props.targetId && this.props.value) {
      const params = this.getQRCodeParams(this.props)

      if (!params) return;

      this.setState({
        qrcode: {
          img: this.props.value,
          params,
        }
      })
    }
  }

  componentDidUpdate(prevProps) {
    const preParams = this.getQRCodeParams(prevProps)
    const curParams = this.getQRCodeParams(this.props)

    // 需要重新生成二维码
    if (preParams !== curParams) {
      this.createQRCode()
      return
    }

    // 如果 value 有了更新
    const { img } = this.state.qrcode || {}
    if (prevProps.value !== this.props.value && this.props.value !== img) {
      this.setState({
        qrcode: {
          img: this.props.value,
          params: curParams,
        }
      })
    }
  }

  getQRCodeParams = (props) => {
    const { targetId, sceneParams = {}, page, params = {} } = props

    if (!targetId || !page) {
      return;
    }

    const sceneObj = {
      id: targetId,
      ...sceneParams,
    }

    return JSON.stringify({
      scene: encodeParam(sceneObj),
      page,
      ...params,
    })
  }

  createQRCode = () => {
    const params = this.getQRCodeParams(this.props)

    if (!params) {
      return;
    }

    this.setState({ loading: true }, () => {
      fetchQRCode({ data: { params } }).then((img) => {
        this.setState({ qrcode: { img, params }, loading: false }, () => {
          if (this.props.onChange) {
            this.props.onChange(img)
          }
        })
      })
    })
  }

  handleThumbClick = () => {
    this.setState({ previewVisible: true })
  }

  handleCancel = () => {
    this.setState({ previewVisible: false })
  }

  handleBtnClick = () => {
    this.createQRCode()
  }

  render() {
    const { loading, qrcode = {}, previewVisible } = this.state
    const { className, style, size } = this.props
    const icon = !qrcode.img ? 'plus' : 'redo'
    const btnText = !qrcode.img ? '生成' : '重新生成'
    const clsList = classNames(Style.miniQRCode, className)
    const styleUsed = style || {}
    const thumbSize = size || 120
    const thumbStyle = {
      width: `${thumbSize}px`,
      height: `${thumbSize}px`,
    }
    const btnSize = thumbSize > 96 ? 'default' : 'small'

    return (
      <div className={clsList} style={styleUsed}>
        {
          qrcode.img && (
            <Tooltip title={qrcode.params}>
              <div className={Style.thumb} onClick={this.handleThumbClick} style={thumbStyle}>
                <img src={qrcode.img} alt=""/>
              </div>
            </Tooltip>
          )
        }
        <div className={Style.body}>
          <Button loading={loading} size={btnSize} icon={icon} onClick={this.handleBtnClick}>{btnText}</Button>
        </div>
        <Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
          <img alt="preview" style={{ width: '100%' }} src={qrcode.img} />
        </Modal>
      </div>
    );
  }
}

MiniQRCode.propTypes = {
  value: PropTypes.string,
  onChange: PropTypes.func,
  targetId: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
  ]),
  page: PropTypes.string,
  sceneParams: PropTypes.object,
  params: PropTypes.object,
  className: PropTypes.string,
  style: PropTypes.object,
  size: PropTypes.number,
}

export default MiniQRCode
