import { Canvas } from '@tarojs/components'
import Taro from '@tarojs/taro'
import { forwardRef, useImperativeHandle, useRef, useState } from 'react'
import Downloader from './lib/downloader'
import Pen from './lib/pen'
import { equal, toPx } from './lib/util'
/**
 *
 * 入参 palette 格式
 * const imgDraw = {
    width: '1124rpx',
    height: '1578rpx',
    background: getCDNSource('/user/inviteCodePopup.png'),
    views: [
      {
        type: 'image',
        url: 'https://qiniu-image.qtshe.com/1560248372315_467.jpg',
        css: {
          top: '32rpx',
          left: '30rpx',
          right: '32rpx',
          width: '688rpx',
          height: '420rpx',
          borderRadius: '16rpx',
        },
      },
      {
        type: 'text',
        text: '青团子',
        css: {
          top: '532rpx',
          fontSize: '28rpx',
          left: '375rpx',
          align: 'center',
          color: '#3c3c3c',
        },
      },
    ],
  }
 *
 */
const downloader = new Downloader()

let SystemInfo = Taro.getSystemInfoSync()

// 最大尝试的绘制次数
const MAX_PAINT_COUNT = 5

interface PropsType {
  customStyle?: React.CSSProperties
  painterStyle?: React.CSSProperties
  dirty?: boolean
  palette?: any // 参考上方
  onImgErr: (result) => void
  onImgOK: (result) => void
}
// 绘画
const Painter = (props: PropsType, ref) => {
  const { customStyle, painterStyle: _painterStyle, dirty, palette, onImgErr, onImgOK } = props
  const [painterStyle, setPainterStyle] = useState(_painterStyle)
  const canvasWidthInPx = useRef(0)
  const canvasHeightInPx = useRef(0)
  const paintCount = useRef(0)

  const [, setForceUpdate] = useState({})
  const canvasNode = useRef<any>(null)
  const ctx = useRef<any>(null)
  /**
     * 判断一个 object 是否为 空
     * @param {object} object
     */
  const isEmpty = (object) => {
    for (const i in object) {
      if (i) {
        return false
      }
    }
    return true
  }
  const isNeedRefresh = (newVal, oldVal) => {
    if (!newVal || isEmpty(newVal) || (dirty && equal(newVal, oldVal))) {
      return false
    }
    return true
  }

  const downloadImages = () => {
    return new Promise((resolve, reject) => {
      let preCount = 0
      let completeCount = 0
      const paletteCopy = JSON.parse(JSON.stringify(palette))
      if (paletteCopy.background) {
        preCount++
        downloader.download(paletteCopy.background).then((path) => {
          paletteCopy.background = path
          completeCount++
          if (preCount === completeCount) {
            resolve(paletteCopy)
          }
        }, () => {
          completeCount++
          if (preCount === completeCount) {
            resolve(paletteCopy)
          }
        })
      }
      if (paletteCopy.views) {
        for (const view of paletteCopy.views) {
          if (view && view.type === 'image' && view.url) {
            preCount++
            console.log('url', view.url)
            /* eslint-disable no-loop-func */
            downloader.download(view.url).then((path) => {
              console.log('path', path)
              view.url = path
              Taro.getImageInfo({
                src: view.url,
                success: (res) => {
                  // 获得一下图片信息，供后续裁减使用
                  view.sWidth = res.width
                  view.sHeight = res.height
                },
                fail: (error) => {
                  console.log(`imgDownloadErr failed, ${JSON.stringify(error)}`)
                  onImgErr({ error })
                },
                complete: () => {
                  completeCount++
                  if (preCount === completeCount) {
                    resolve(paletteCopy)
                  }
                },
              })
            }, () => {
              completeCount++
              if (preCount === completeCount) {
                resolve(paletteCopy)
              }
            })
          }
        }
      }
      if (preCount === 0) {
        resolve(paletteCopy)
      }
    })
  }
  // 初始化 canvas
  const initCanvas = async() => {
    return new Promise<{ canvas: Taro.Canvas; ctx: Taro.RenderingContext }>((resolve, reject) => {
      Taro.nextTick(() => {
        const query = Taro.createSelectorQuery()
        query.select('#canvas').node(({ node: canvas }: { node: Taro.Canvas }) => {
          console.log('canvas==>', canvas)
          const context = canvas.getContext('2d')
          console.log('ctx', context)
          canvasNode.current = canvas
          ctx.current = context
          console.log('canvas', canvas)
          setForceUpdate({})
          resolve({ canvas: canvasNode.current, ctx: ctx.current })
        }).exec()
      })
    })
  }
  // 开始绘制
  const _startPaint = () => {
    if (isEmpty(palette)) {
      return
    }
    console.log('startPaint', palette)
    if (!(SystemInfo && SystemInfo.screenWidth)) {
      try {
        SystemInfo = Taro.getSystemInfoSync()
      }
      catch (e) {
        const error = `Painter get system info failed, ${JSON.stringify(e)}`
        // that.triggerEvent('imgErr', { error })
        onImgErr({ error })
        console.log(error)
        return
      }
    }

    downloadImages().then((palette: any) => {
      const { width, height } = palette
      canvasWidthInPx.current = toPx(width)
      canvasHeightInPx.current = toPx(height)
      if (!width || !height) {
        console.log(`You should set width and height correctly for painter, width: ${width}, height: ${height}`)
        return
      }
      console.log('palette', palette, width, height)
      setPainterStyle({
        width: `${width}`,
        height: `${height}`,
      })
      // 初始化canvas
      initCanvas().then(({ ctx, canvas }) => {
        // const ctx = Taro.createCanvasContext('k-canvas', this)
        const pen = new Pen(ctx, canvas, palette)
        pen.paint((canvas) => {
          // eslint-disable-next-line @typescript-eslint/no-use-before-define
          saveImgToLocal(canvas)
        })
      })
    })
  }

  const getImageInfo = (filePath: string) => {
    Taro.getImageInfo({
      src: filePath,
      success: (infoRes) => {
        if (paintCount.current > MAX_PAINT_COUNT) {
          const error = `The result is always fault, even we tried ${MAX_PAINT_COUNT} times`
          console.log(error)
          onImgErr({ error })
          return
        }
        // 比例相符时才证明绘制成功，否则进行强制重绘制
        if (Math.abs((infoRes.width * canvasHeightInPx.current - canvasWidthInPx.current * infoRes.height) / (infoRes.height * canvasHeightInPx.current)) < 0.01) {
          onImgOK({ path: filePath })
        }
        else {
          console.log('infoRes filePath', infoRes, filePath, canvasHeightInPx.current, canvasWidthInPx.current)
          _startPaint()
        }
        paintCount.current++
      },
      fail: (error) => {
        console.log(`getImageInfo failed, ${JSON.stringify(error)}`)
        onImgErr({ error })
      },
    })
  }
  const saveImgToLocal = (canvas) => {
    setTimeout(() => {
      Taro.canvasToTempFilePath({
        canvas,
        fileType: 'png',
        success(res) {
          console.log('tempFilePath', res.tempFilePath, canvas)
          getImageInfo(res.tempFilePath)
        },
        fail(error) {
          console.log(`canvasToTempFilePath failed, ${JSON.stringify(error)}`)
          // that.triggerEvent('imgErr', { error })
          onImgErr({ error })
        },
      }, this)
    }, 300)
  }
  // 暴露
  useImperativeHandle(
    ref,
    () => {
      return {
        startPaint: () => {
          paintCount.current = 0
          _startPaint()
        },
      }
    },
    [paintCount.current],
  )
  return <Canvas style={{ ...customStyle, ...painterStyle }} id="canvas" type="2d" />
}
export default forwardRef(Painter)
