# canvas生成笔记图片

import styles from './index.less'
import { PureComponent, createRef } from 'react'
import QRCode from 'qrcode'
import html2canvas from 'html2canvas'
import classnames from 'classnames'
import preventScroll from 'prevent-scroll'
import growingService from '@xb/services/growing'
import MaskBasic from '@xb/components/Mask/Basic'
import MaskCenter from '@xb/components/Mask/Center'
import ButtonBasic from '@xb/components/Button/Basic'
import Line from '@xb/components/Line/Basic'
import { MountPoint, sleep } from '@xb/utils/dom'
import { device } from '@xb/utils/userAgent'
import creditService from '@xb/services/credit'

import iconLogoComplete from '@xb/assets/icons/icon-logo-complete.png'
import ellipseBg from '@xb/assets/ellipse-bg.png'
import userImg from '@xb/assets/user.png'

class ModalComponent extends PureComponent {
 constructor(props) {
   super(props)
   const { onClick, uniqueId, noteId } = this.props
   this.onClick = onClick
   this.node = createRef()
   this.container = createRef()
   this.saveImage = createRef()
   this.avatar = createRef()
   this.startTime = ''
   this.endTime = ''

   const link = `${window.location.origin}/course/note/landing/${uniqueId}/${noteId}?sourceType=h5wxshare`
   this.action.generateQR(link)
   this.state = {
     once: true,
     qrcode: false,
   }
 }

 action = {
   generateQR: async url => {
     try {
       const baseImage = await QRCode.toDataURL(url)
       const image = new Image()
       image.src = baseImage
       this.node.current.appendChild(image)
       this.setState({ qrcode: true })
     } catch (err) {
       console.error(err)
     }
   },
   generateImage: async () => {
     const canvas = this.action.drawCanvas(this.container.current)
     await sleep(300)
     html2canvas(this.container.current, {
       useCORS: true,
       logging: false,
       canvas,
       scale: 10,
       letterRendering: true,
     }).then(canvas => {
       const image = new Image()
       image.src = canvas.toDataURL('image/png')
       this.saveImage.current.appendChild(image)
     })
   },
   checkPicture: async url => {
     return new Promise(resolve => {
       const image = new Image()
       image.src = url
       image.onload = () => {
         resolve(url)
       }
       image.onerror = () => {
         resolve(userImg)
       }
     })
   },
   DPR: () => {
     if (window.devicePixelRatio && window.devicePixelRatio > 1) {
       return window.devicePixelRatio
     }
     return 1
   },
   parseValue: value => {
     return parseInt(value, 10)
   },
   drawCanvas: node => {
     const box = window.getComputedStyle(node)
     // DOM 节点计算后宽高
     const width = this.action.parseValue(box.width)
     const height = this.action.parseValue(box.height)
     // 获取像素比
     const scaleBy = this.action.DPR()
     // 创建自定义 canvas 元素
     const canvas = document.createElement('canvas')
     // 设定 canvas 元素属性宽高为 DOM 节点宽高 * 像素比
     canvas.width = width * scaleBy
     canvas.height = height * scaleBy
     // 设定 canvas css宽高为 DOM 节点宽高
     canvas.style.width = `${width}px`
     canvas.style.height = `${height}px`
     // 获取画笔
     const context = canvas.getContext('2d')
     // 【重要】关闭抗锯齿
     context.mozImageSmoothingEnabled = false
     context.msImageSmoothingEnabled = false
     context.imageSmoothingEnabled = false
     // 将所有绘制内容放大像素比倍
     context.scale(scaleBy, scaleBy)

     return canvas
   },
   touchstart: () => {
     this.startTime = +new Date()
   },
   touchend: () => {
     this.endTime = +new Date()
     const { uniqueId } = this.props

     if (this.endTime - this.startTime > 700) {
       const { payload } = this.props
       growingService.noteShareImage(payload)
       try {
         creditService.shareNote(uniqueId)
       } catch (error) {
         console.error(error)
       }
     }
   },
 }

 render() {
   const { userUrl, userName, createdTime, content, productTitle } = this.props
   const { once, qrcode } = this.state
   const isIOSBox = device.isIOS ? styles.isIOSBox : ''
   const isIOSNote = device.isIOS ? styles.isIOSNote : ''

   const avatar = this.action.checkPicture(userUrl)
   avatar.then(url => {
     this.avatar.current.src = url
     if (once && qrcode) {
       this.action.generateImage()
       this.setState({ once: false })
     }
   })

   return (
     <MaskBasic onClick={this.onClick}>
       <MaskCenter>
         <div className={classnames(styles.box, isIOSBox)} onClick={e => e.stopPropagation()}>
           <div
             ref={this.saveImage}
             className={styles.containerImage}
             onTouchStart={this.action.touchstart}
             onTouchEnd={this.action.touchend}
           />
           <div ref={this.container} className={styles.container}>
             <img className={styles.logo} src={iconLogoComplete} />
             <img className={styles.ellipse} src={ellipseBg} />
             <div className={styles.content}>
               <div className={styles.product}>
                 <span>来自课程</span>
                 <p>{productTitle}</p>
               </div>
               <div className={styles.userInfo}>
                 <img ref={this.avatar} className={styles.avatar} crossOrigin='anonymous' />
                 <div className={styles.user}>
                   <h3>{userName}</h3>
                   <p>{createdTime}</p>
                 </div>
               </div>
               <p className={classnames(styles.note, isIOSNote)}>{content}</p>
               <Line className={styles.line} size={15} />
               <div className={styles.qrcodeInfo}>
                 <div className={styles.qrcode} ref={this.node} />
                 <div className={styles.description}>
                   <h3>长按识别二维码</h3>
                   <p>查看完整笔记,亦可点赞评论</p>
                 </div>
               </div>
             </div>
           </div>
           <div className={styles.button}>
             <ButtonBasic style={{ width: '100%', color: '#222222', fontWeight: 400, boxShadow: 'none' }}>长按按钮分享笔记</ButtonBasic>
           </div>
         </div>
         <div className={styles.close} />
       </MaskCenter>
     </MaskBasic>
   )
 }
}

class GlobalModalSharePicture extends MountPoint {
 hide = () => {
   preventScroll.off()
   this.removeMountPoint()
 }

 show = options => {
   preventScroll.on()
   this.render(<ModalComponent onClick={this.hide} {...options} />)
 }
}

export default new GlobalModalSharePicture()