import {
  forwardRef,
  memo,
  useEffect,
  useRef,
  useState,
} from 'react'

import { isMobileDevice } from 'config'

import { defaultTheme } from 'features/Theme/config'

import {
  Button,
  Svg,
  Path,
} from './styled'

const COLOR_PAIRS = [
  ['#FF0000', '#FFDF00'],
  ['#70FF00', '#0001FF'],
  ['#CD00FF', defaultTheme.colors.white],
  [defaultTheme.colors.white, defaultTheme.colors.white],
  [defaultTheme.colors.white, defaultTheme.colors.white],
  [defaultTheme.colors.white, defaultTheme.colors.white],
  ['#FF0000', '#FFDF00'],
  ['#70FF00', '#0001FF'],
  ['#CD00FF', defaultTheme.colors.white],
  [],
]

const OFFSET_CHANGE_SPEED = isMobileDevice ? 20 : 5

const ANIMATION_INTERVAL = 5000

const FREEZE_TIME = 6000

const PARTICLES_GENERATION_TIME = 1500

type Props = {
  onClick: () => void,
  setGenerateParticles: (state: boolean) => void,
}

const LikeButtonFC = forwardRef<HTMLButtonElement, Props>((
  {
    onClick,
    setGenerateParticles,
  },
  ref,
) => {
  const stop1Ref = useRef<SVGStopElement>(null)
  const stop2Ref = useRef<SVGStopElement>(null)

  const [canAnimate, setCanAnimate] = useState(false)
  const [isDisabled, setIsDisabled] = useState(false)
  const freezeTimeoutIdRef = useRef<NodeJS.Timeout | null>(null)
  const generateTimeoutIdRef = useRef<NodeJS.Timeout | null>(null)

  const startGenerateParticles = () => setGenerateParticles(true)

  const stopGenerateParticles = () => setGenerateParticles(false)

  const handleClick = () => {
    onClick()
    setIsDisabled(true)
    startGenerateParticles()

    freezeTimeoutIdRef.current = setTimeout(() => setIsDisabled(false), FREEZE_TIME)
    generateTimeoutIdRef.current = setTimeout(stopGenerateParticles, PARTICLES_GENERATION_TIME)
  }

  useEffect(() => {
    let requestAnimationId: number
    let timeoutId: NodeJS.Timeout
    let index = 0
    let offset = 100

    const animate = () => {
      if (!stop1Ref.current || !stop2Ref.current) return

      stop1Ref.current.setAttribute('offset', `${offset}%`)
      stop2Ref.current.setAttribute('offset', `${offset}%`)
      stop1Ref.current.setAttribute('stop-color', `${COLOR_PAIRS[index][0]}`)
      stop2Ref.current.setAttribute('stop-color', `${COLOR_PAIRS[index][1]}`)

      offset = Math.max(offset - OFFSET_CHANGE_SPEED, 0)

      if (offset === 0) {
        offset = 100
        index = index + 1 <= COLOR_PAIRS.length - 1
          ? index + 1
          : 0
      }

      if (index === COLOR_PAIRS.length - 1 && offset === 100) {
        requestAnimationId && cancelAnimationFrame(requestAnimationId)
        setCanAnimate(false)
        index = 0

        timeoutId = setTimeout(() => {
          requestAnimationId = requestAnimationFrame(animate)
        }, ANIMATION_INTERVAL)
      } else {
        requestAnimationId = requestAnimationFrame(animate)
        setCanAnimate(true)
      }
    }

    timeoutId = setTimeout(animate, ANIMATION_INTERVAL)

    return () => {
      timeoutId && clearTimeout(timeoutId)
      requestAnimationId && cancelAnimationFrame(requestAnimationId)
    }
  }, [])

  useEffect(() => () => {
    freezeTimeoutIdRef.current && clearTimeout(freezeTimeoutIdRef.current)
    generateTimeoutIdRef.current && clearTimeout(generateTimeoutIdRef.current)
  }, [])

  return (
    <Button
      disabled={isDisabled}
      canAnimate={canAnimate}
      ref={ref}
      aria-label='Like this moment'
      onClick={handleClick}
    >
      <Svg
        width='30'
        height='30'
        viewBox='0 0 30 30'
        fill='none'
      >
        <defs>
          <linearGradient id='gradient'>
            <stop
              ref={stop1Ref}
              offset='50%'
              stopColor={defaultTheme.colors.white}
            />
            <stop
              ref={stop2Ref}
              offset='50%'
              stopColor={defaultTheme.colors.white}
            />
          </linearGradient>
        </defs>

        <g>
          <Path
            fill={canAnimate ? 'url(#gradient)' : defaultTheme.colors.white}
            d='M17.0939 0.686035C15.6852 0.686035 16.1589 3.64594 16.1589 3.64594C16.1589 3.64594 13.1482 11.8087 10.2685 13.9842C9.65136 14.6215 9.26489 15.3262 9.02179 15.9023C8.96569 16.0432 8.91583 16.178 8.87219 16.3006C8.67896 16.6867 8.26757 17.2811 7.38867 17.802L10.2685 30.1135C10.2685 30.1135 14.7252 30.6834 19.1945 30.5915C20.9835 30.7324 22.8784 30.7447 24.3868 30.426C29.5106 29.3536 28.2265 25.8422 28.2265 25.8422C30.9879 23.8015 29.4171 21.2522 29.4171 21.2522C31.873 18.7335 29.4607 16.6193 29.4607 16.6193C29.4607 16.6193 30.7884 14.5847 29.0743 13.0466C26.9363 11.1223 21.1331 12.4031 21.1331 12.4031C20.7279 12.4705 20.2978 12.5563 19.8365 12.6666C19.8365 12.6666 17.8294 13.5858 19.8365 7.59861C21.8499 1.61139 18.5026 0.686035 17.0939 0.686035ZM8.19893 29.2249L6.01728 19.0338C5.89261 18.4516 5.29422 17.9736 4.68959 17.9736H0.525765L0.519531 30.279H7.32003C7.9309 30.2851 8.32359 29.8071 8.19893 29.2249Z'
          />
        </g>
      </Svg>
    </Button>
  )
})

export const LikeButton = memo(LikeButtonFC)

