import react, { useState } from 'react';
import TiledLayer from './TiledLayer';
import { tileKeyToString } from './Map';

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

interface TiledLayersStackProperties {
  height: number;
  width: number;
  shift: Point;
  zoom: number;
  tileSize: number;
  numberOfZoomLevels?: number;
}

const TiledLayersStack: react.FC<TiledLayersStackProperties> = (
  props: TiledLayersStackProperties
) => {
  console.log(`Rendering TiledLayersStack`);

  const [tiledLayerKey, setTiledLayerKey] = useState({
    provider: 'osm',
    zoomLevel: 16,
    x: 33488,
    y: 23939,
  });

  const numberOfZoomLevels =
    props.numberOfZoomLevels === undefined
      ? 1
      : props.numberOfZoomLevels % 2 === 0
      ? props.numberOfZoomLevels + 1
      : props.numberOfZoomLevels;

  const layers = [];

  const safetyZoomLevels = Math.floor(numberOfZoomLevels / 2);

  const nbTiles =
    Math.ceil(
      (Math.max(props.width, props.height) * 2 ** safetyZoomLevels) / 256
    ) + 2;

  const activeZoomLevel = Math.min(
    Math.max(Math.round(Math.log2(props.zoom)) + safetyZoomLevels, 0),
    numberOfZoomLevels - 1
  );

  const getTiledLayer = (zoomLevel: number, isActive: boolean) => {
    const zoom = 2 ** (zoomLevel - safetyZoomLevels);
    const currentTiledLayerKey = {
      provider: tiledLayerKey.provider,
      zoomLevel: zoomLevel - safetyZoomLevels + tiledLayerKey.zoomLevel,
      x: Math.floor(tiledLayerKey.x * zoom),
      y: Math.floor(tiledLayerKey.y * zoom),
    };
    return (
      <TiledLayer
        key={tileKeyToString(currentTiledLayerKey)}
        tiledLayerKey={currentTiledLayerKey}
        height={props.height * zoom}
        width={props.width * zoom}
        shift={{
          x: props.shift.x * zoom,
          y: props.shift.y * zoom,
        }}
        zoom={props.zoom}
        layerZoom={1 / zoom}
        tileSize={256}
        nbTiles={nbTiles * zoom}
        active={isActive}
      />
    );
  };

  // First (ie last) dispay layers with less details (ascending order)
  for (let i = 0; i < activeZoomLevel; i++) {
    layers.push(getTiledLayer(i, false));
  }
  // then dispay layers with more details (descending order)
  for (let i = numberOfZoomLevels - 1; i > activeZoomLevel; i--) {
    layers.push(getTiledLayer(i, false));
  }
  // And then, of course, the active one
  layers.push(getTiledLayer(activeZoomLevel, true));

  return <>{layers}</>;
};

export default TiledLayersStack;
