import { MediaSet, MediaSetServiceClientImpl } from './generated/media_set';
import { newRPC } from './App';
import { useEffect, useRef } from 'react';

interface Props {
  mediaSet: MediaSet;
  position: number;
  duration: number;
  height: number;
  video: HTMLVideoElement;
}

export const VideoPreview: React.FC<Props> = ({
  mediaSet,
  position,
  duration,
  height,
  video,
}: Props) => {
  const videoCanvasRef = useRef<HTMLCanvasElement>(null);

  // effects

  // render canvas
  useEffect(() => {
    // TODO: not sure if requestAnimationFrame is recommended here.
    requestAnimationFrame(() => {
      (async function () {
        const canvas = videoCanvasRef.current;
        if (canvas == null) {
          console.error('no canvas ref available');
          return;
        }

        const ctx = canvas.getContext('2d');
        if (ctx == null) {
          console.error('no 2d context available');
          return;
        }

        // Set aspect ratio.
        canvas.width =
          canvas.height * (canvas.clientWidth / canvas.clientHeight);

        // If the required position is 0, display the thumbnail instead of
        // trying to render the video. The most important use case is before a
        // click event has happened, when autoplay restrictions will prevent
        // the video being rendered to canvas.
        if (position == 0) {
          const service = new MediaSetServiceClientImpl(newRPC());
          const thumbnail = await service.GetVideoThumbnail({
            id: mediaSet.id,
          });

          // TODO: avoid fetching the image every re-render:
          const url = URL.createObjectURL(
            new Blob([thumbnail.image], { type: 'image/jpeg' })
          );
          const img = new Image(thumbnail.width, thumbnail.height);

          img.src = url;
          img.onload = () => ctx.drawImage(img, 0, 0, 177, 100);
          return;
        }

        // otherwise, render the video, which (should) work now.
        const durSecs = duration / 1000;
        const ratio = position / durSecs;
        const x = (canvas.width - 177) * ratio;
        ctx.clearRect(0, 0, x, canvas.height);
        ctx.clearRect(x + 177, 0, canvas.width - 177 - x, canvas.height);
        ctx.drawImage(video, x, 0, 177, 100);
      })();
    });
  }, [mediaSet, position]);

  // render component

  const containerStyles = {
    height: height + 'px',
    position: 'relative',
    flexGrow: 0,
  } as React.CSSProperties;

  const canvasStyles = {
    position: 'absolute',
    width: '100%',
    height: '100%',
    display: 'block',
    zIndex: 1,
  } as React.CSSProperties;

  return (
    <>
      <div style={containerStyles}>
        <canvas
          width="500"
          height="100"
          ref={videoCanvasRef}
          style={canvasStyles}
        ></canvas>
        <canvas style={canvasStyles}></canvas>
      </div>
    </>
  );
};
