import react, { useEffect, useState } from 'react';
import Tile from './Tile';
import fakeTile from './FakeTile.svg';
import { TileKey, tileKeyToString } from './Map';

interface Point {
  x: number;
  y: number;
}

interface TiledLayerProperties {
  height: number;
  width: number;
  shift: Point;
  zoom: number;
  layerZoom: number;
  tileSize: number;
  nbTiles: number;
  active: boolean;
  tiledLayerKey: TileKey;
}

const TiledLayer: react.FC<TiledLayerProperties> = (
  props: TiledLayerProperties
) => {
  var initialTiles: any[][] = [];
  for (let row = 0; row < props.nbTiles; row++) {
    let tileRow = [];
    for (let col = 0; col < props.nbTiles; col++) {
      const tileKey: TileKey = {
        provider: props.tiledLayerKey.provider,
        zoomLevel: props.tiledLayerKey.zoomLevel,
        x: props.tiledLayerKey.x + col,
        y: props.tiledLayerKey.y + row,
      };
      tileRow.push(<g key={tileKeyToString(tileKey)} />);
    }
    initialTiles.push(tileRow);
  }

  const [tiles, setTiles] = useState(initialTiles);

  useEffect(() => {
    if (props.active) {
      const firstVisibleTiles = {
        x: Math.max(
          Math.floor(-props.shift.x / props.tileSize / props.zoom),
          0
        ),
        y: Math.max(
          Math.floor(-props.shift.y / props.tileSize / props.zoom),
          0
        ),
      };

      const lastVisibleTiles = {
        x: Math.min(
          Math.ceil(
            firstVisibleTiles.x + props.width / props.tileSize / props.zoom
          ),
          props.nbTiles - 1
        ),
        y: Math.min(
          Math.ceil(
            firstVisibleTiles.y + props.height / props.tileSize / props.zoom
          ),
          props.nbTiles - 1
        ),
      };
      console.log(
        `Adding new tiles if needed for  ${JSON.stringify(
          firstVisibleTiles
        )}/${JSON.stringify(lastVisibleTiles)}.`
      );
      const newTiles: any[][] = [];
      for (let row = 0; row < props.nbTiles; row++) {
        let tileRow = [];
        for (let col = 0; col < props.nbTiles; col++) {
          const tileKey: TileKey = {
            provider: props.tiledLayerKey.provider,
            zoomLevel: props.tiledLayerKey.zoomLevel,
            x: props.tiledLayerKey.x + col,
            y: props.tiledLayerKey.y + row,
          };
          if (
            tiles[row][col].type === 'g' &&
            row >= firstVisibleTiles.y &&
            row <= lastVisibleTiles.y &&
            col >= firstVisibleTiles.x &&
            col <= lastVisibleTiles.x
          ) {
            console.log(`Adding tile ${row}/${col}`);
            tileRow.push(
              <Tile
                key={tileKeyToString(tileKey)}
                tileKey={tileKey}
                href={fakeTile}
                x={col * props.tileSize}
                y={row * props.tileSize}
                tileSize={props.tileSize}
                delay={1000}
              />
            );
          } else {
            tileRow.push(tiles[row][col]);
          }
        }
        newTiles.push(tileRow);
      }

      setTiles(newTiles);
    }
  }, [
    props.shift,
    props.zoom,
    props.nbTiles,
    props.height,
    props.width,
    props.active,
    props.tileSize,
  ]);

  return <g transform={`scale(${props.layerZoom})`}>{tiles}</g>;
};

export default TiledLayer;
