import react, { memo, useEffect, useRef } from 'react';
import { isEqual } from 'lodash';
import { TileKeyObject } from './types';
import { getTileUrl } from './tile-providers';

export interface TileProperties {
  /** The image's source URL  */
  keyObject: TileKeyObject;
  /** A delay to add (for test/debug purposes)  */
  delay?: number;
}

/**
 *
 * @param props
 * @returns A tile
 *
 * Tile components are containers for images.
 *
 * They return an empty `<g/>` element immediately so that the rendering can proceed
 * and append an `<image/>` element whenever the image is loaded.
 *
 * They are designed to be part of {@link components/map/TiledLayer!TiledLayer} components in SVG `<g/>` elements
 * in which the unit is the tile size. In this coordinate system their size is thus always equal to 1.
 */
export const Tile: react.FC<TileProperties> = memo((props: TileProperties) => {
  const g = useRef<SVGGElement>(null);

  const timeout = (ms: number) => {
    return new Promise((resolve) => setTimeout(resolve, ms));
  };
  // console.log(`Rendering tile: ${JSON.stringify(props)}`);
  useEffect(() => {
    const loadImage = async () => {
      //      console.log(`Pre loading: ${props.href}`);
      const href = getTileUrl(props.keyObject);
      const image = new Image(1, 1);
      image.loading = 'eager';
      // @ts-ignore
      image.setAttribute('href', href);
      if (!image.complete) {
        await image.decode();
      }
      if (props.delay !== undefined) {
        await timeout(props.delay);
      }
      const svgImage = document.createElementNS(
        'http://www.w3.org/2000/svg',
        'image'
      ) as unknown as SVGImageElement;
      svgImage.setAttribute('width', '1');
      svgImage.setAttribute('height', '1');
      // @ts-ignore
      svgImage.setAttribute('href', href);
      g.current?.replaceChildren(svgImage);
    };
    loadImage();
  }, [props.keyObject]);

  return (
    <g
      ref={g}
      transform={`translate(${props.keyObject.x}, ${props.keyObject.y})`}
    />
  );
}, isEqual);

export default Tile;
