import react, { useCallback, useState } from 'react';
import Handlers from './Handlers';
import Tile from './Tile';
import TiledLayer from './TiledLayer';
import { Point, TileFactory } from './types';

export interface MapProperties {}

/**
 *
 * @returns A Map component
 */
export const Map: react.FC<MapProperties> = (props: MapProperties) => {
  const [coordinateSystem, setCoordinateSystem] = useState({
    zoom: 1,
    shift: { x: 0, y: 0 },
  });

  const simpleTileFactory: TileFactory = useCallback(
    (keyObject) => (
      <Tile
        href={`https://tile.openstreetmap.org/${keyObject.zoomLevel}/${keyObject.x}/${keyObject.y}.png`}
      />
    ),
    []
  );

  const transformMap = (
    deltaShift: Point | null,
    deltaZoom: number | null,
    zoomCenter: Point | null
  ) => {
    const actualDeltaShift = deltaShift === null ? { x: 0, y: 0 } : deltaShift;
    const actualDeltaZoom = deltaZoom === null ? 1 : deltaZoom;
    const actualZoomCenter = zoomCenter === null ? { x: 0, y: 0 } : zoomCenter;
    var newCoordinateSystem = {
      shift: {
        x:
          coordinateSystem.shift.x +
          actualDeltaShift.x +
          (coordinateSystem.shift.x - actualZoomCenter.x) *
            (actualDeltaZoom - 1),
        y:
          coordinateSystem.shift.y +
          actualDeltaShift.y +
          (coordinateSystem.shift.y - actualZoomCenter.y) *
            (actualDeltaZoom - 1),
      },
      zoom: coordinateSystem.zoom * actualDeltaZoom,
    };
    setCoordinateSystem(newCoordinateSystem);
  };

  const viewPort = {
    topLeft: {
      x: Math.floor(-coordinateSystem.shift.x / coordinateSystem.zoom / 256),
      y: Math.floor(-coordinateSystem.shift.y / coordinateSystem.zoom / 256),
    },
    bottomRight: {
      x: Math.ceil(
        (-coordinateSystem.shift.x + window.innerWidth) /
          coordinateSystem.zoom /
          256
      ),
      y: Math.ceil(
        (-coordinateSystem.shift.y + window.innerHeight) /
          coordinateSystem.zoom /
          256
      ),
    },
  };

  return (
    <>
      <Handlers transformMap={transformMap} />
      <svg width={window.innerWidth} height={window.innerHeight}>
        <g
          transform={`translate(${coordinateSystem.shift.x}, ${coordinateSystem.shift.y}) scale(${coordinateSystem.zoom})`}
        >
          <g transform='scale(256)'>
            <TiledLayer
              keyObject={{ provider: 'osm', zoomLevel: 16, x: 33485, y: 23936 }}
              viewPort={viewPort}
              tileFactory={simpleTileFactory}
            />
          </g>
        </g>
      </svg>
    </>
  );
};

export default Map;
