import useAnimationFrame from '@/lib/useAnimationFrame';
import { court, lightLine, lightPastelBlue } from '@/styles/colors';
import styled from '@emotion/styled';
import { useCallback, useRef } from 'react';
import OnScreenOnly from '../OnScreenOnly';

const GridAnimationWrapper = styled.div`
  position: relative;
  background: ${lightLine};
  width: 100%;
  aspect-ratio: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  > div {
    width: 100%;
    height: 100%;
  }
`;

const CompressionCanvas = styled.canvas`
  transform-origin: 0 0;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
`;

const amplitudes: number[] = [];
let currAmplitude = 1;
for (let i = 0; i < 240; i++) {
  currAmplitude -= 1 / 60;
  if (i % 60 === 0) {
    currAmplitude = 1;
  } else if ((i + 8) % 60 === 0) {
    currAmplitude = 0.65;
  }
  amplitudes.push(currAmplitude);
}

const SidechainCompression = () => {
  const canvasRef = useRef<HTMLCanvasElement>(null);

  useAnimationFrame(
    useCallback(() => {
      const canvas = canvasRef.current;
      if (!canvas) return;
      const ctx = canvas.getContext('2d');
      if (!ctx) return;

      const now = Date.now();

      ctx.clearRect(0, 0, canvas.width, canvas.height);
      const idealWidth = Math.ceil(canvas.parentElement!.clientWidth * window.devicePixelRatio);
      const idealHeight = Math.ceil(canvas.parentElement!.clientHeight * window.devicePixelRatio);
      if (canvas.width !== idealWidth || canvas.height !== idealHeight) {
        canvas.width = idealWidth;
        canvas.height = idealHeight;
        canvas.setAttribute('style', `transform: scale(${1 / window.devicePixelRatio})`);
      }

      ctx.save();
      const interpolatedIndex = (now / 30) % amplitudes.length;
      const selectedIndex = Math.floor(interpolatedIndex);

      const amplitude = amplitudes[selectedIndex];
      const interpolatedAmplitude =
        amplitudes[(selectedIndex + 1) % amplitudes.length] * (interpolatedIndex % 1) +
        amplitude * (1 - (interpolatedIndex % 1));

      const x = interpolatedAmplitude * idealWidth;

      ctx.lineWidth = 2 * window.devicePixelRatio;
      ctx.strokeStyle = court;
      ctx.beginPath();
      ctx.moveTo(0, idealHeight);
      ctx.lineTo(idealWidth / 2, idealHeight / 2);
      ctx.lineTo(idealWidth, idealHeight * (0.5 - 1 / 8));
      ctx.lineTo(idealWidth, idealHeight);
      ctx.closePath();
      ctx.clip();

      ctx.fillStyle = lightPastelBlue;
      ctx.globalAlpha = 0.4;
      ctx.fillRect(x, 0, idealWidth, idealHeight);

      ctx.restore();

      // waveform
      for (let i = 0; i < amplitudes.length; i++) {
        ctx.fillStyle = i === selectedIndex ? 'white' : lightPastelBlue;
        ctx.fillRect(
          Math.floor((i / amplitudes.length) * idealWidth),
          idealHeight - (amplitudes[i] * idealHeight) / 4,
          Math.ceil((1 / amplitudes.length) * idealWidth),
          (amplitudes[i] * idealHeight) / 4
        );
      }
    }, [])
  );

  return (
    <GridAnimationWrapper>
      <OnScreenOnly>
        <CompressionCanvas ref={canvasRef} />
      </OnScreenOnly>
    </GridAnimationWrapper>
  );
};

export default SidechainCompression;
