import React, { useRef, useEffect } from 'react';

interface BubbleProps {
  y: number;
  bubbleW?: number;
  bubbleH?: number;
}

const Bubble: React.FC<BubbleProps> = ({ bubbleW = 50, bubbleH = 80, y = 0 }) => {
  const devicePixelRatio = window.devicePixelRatio || 2;
  const width = bubbleW * devicePixelRatio;
  const height = bubbleH * devicePixelRatio;
  const initRadius = 18 * devicePixelRatio;
  const minHeadRadius = 12 * devicePixelRatio;
  const minTailRadius = 5 * devicePixelRatio;
  const initArrowRadius = 10 * devicePixelRatio;
  const minArrowRadius = 6 * devicePixelRatio;
  const arrowWidth = 3 * devicePixelRatio;
  const maxDistance = 40 * devicePixelRatio;;
  const initCenterX = 25 * devicePixelRatio;
  const initCenterY = 25 * devicePixelRatio;
  const headCenter = {
    x: initCenterX,
    y: initCenterY
  }
  const bubbleEle = useRef<HTMLCanvasElement>(null);
  const style: React.CSSProperties = { width, height, transform: `scale(${0.92 / devicePixelRatio}) translateY(${-y}px)` }
  const _getDistance = () => {
    return Math.max(0, Math.min(y * devicePixelRatio, maxDistance))
  }
  const _draw = () => {
    const bubble: HTMLCanvasElement = bubbleEle.current as HTMLCanvasElement;
    const ctx: CanvasRenderingContext2D = bubble.getContext('2d') as CanvasRenderingContext2D;
    ctx.clearRect(0, 0, bubble.width, bubble.height)
    _drawBubble(ctx)
    _drawArrow(ctx)
  }
  const _drawBubble = (ctx: CanvasRenderingContext2D) => {
    ctx.save()
    ctx.beginPath()
    const _distance = _getDistance();
    const rate = _distance / maxDistance;
    const headRadius = initRadius - (initRadius - minHeadRadius) * rate
    headCenter.y = initCenterY - (initRadius - minHeadRadius) * rate
    // 画上半弧线
    ctx.arc(headCenter.x, headCenter.y, headRadius, 0, Math.PI, true);
    // 画左侧贝塞尔
    const tailRadius = initRadius - (initRadius - minTailRadius) * rate;
    const tailCenter = {
      x: headCenter.x,
      y: headCenter.y + _distance
    }
    const tailPointL = {
      x: tailCenter.x - tailRadius,
      y: tailCenter.y
    }
    const controlPointL = {
      x: tailPointL.x,
      y: tailPointL.y - _distance / 2
    }
    ctx.quadraticCurveTo(controlPointL.x, controlPointL.y, tailPointL.x, tailPointL.y);
    // 画下半弧线
    ctx.arc(tailCenter.x, tailCenter.y, tailRadius, Math.PI, 0, true);
    // 画右侧贝塞尔
    const headPointR = {
      x: headCenter.x + headRadius,
      y: headCenter.y
    }
    const controlPointR = {
      x: tailCenter.x + tailRadius,
      y: headPointR.y + _distance / 2
    }
    ctx.quadraticCurveTo(controlPointR.x, controlPointR.y, headPointR.x, headPointR.y);
    ctx.fillStyle = 'rgb(170,170,170)'
    ctx.fill()
    ctx.strokeStyle = 'rgb(153,153,153)'
    ctx.stroke();
    ctx.restore();
  }
  const _drawArrow = (ctx: CanvasRenderingContext2D) => {
    ctx.save();
    ctx.beginPath();
    const _distance = _getDistance();
    const rate = _distance / maxDistance;
    const arrowRadius = initArrowRadius - (initArrowRadius - minArrowRadius) * rate;
    // 画内圆
    ctx.arc(headCenter.x, headCenter.y, arrowRadius - (arrowWidth - rate), -Math.PI / 2, 0, true);
    // 画外圆
    ctx.arc(headCenter.x, headCenter.y, arrowRadius, 0, Math.PI * 3 / 2, false);
    ctx.lineTo(headCenter.x, headCenter.y - arrowRadius - arrowWidth / 2 + rate);
    ctx.lineTo(headCenter.x + arrowWidth * 2 - rate * 2, headCenter.y - arrowRadius + arrowWidth / 2);
    ctx.lineTo(headCenter.x, headCenter.y - arrowRadius + arrowWidth * 3 / 2 - rate);
    ctx.fillStyle = 'rgb(255,255,255)'
    ctx.fill()
    ctx.strokeStyle = 'rgb(170,170,170)'
    ctx.stroke()
    ctx.restore()
  }

  useEffect(() => {
    _draw()
  })
  return <canvas ref={bubbleEle} width={width} height={height} style={style}></canvas>
}

export default Bubble;