import { IonContent } from '@ionic/react';
import react, { useState } from 'react';

import './Map.css';
import MouseHandler from './MouseHandler';
import SlippyBoard from './SlippyBoard';
import SingleTouchHandler from './SingleTouchHandler';
import DoubleTouchHandler from './DoubleTouchHandler';
import TiledLayer from './TiledLayer';

interface MapProperties {
  height: number;
  width: number;
}

const Map: react.FC<MapProperties> = (props: MapProperties) => {
  const nbTiles =
    Math.ceil((Math.max(props.width, props.height) * 2) / 256) + 2;
  const boardSize = nbTiles * 256;

  const [shift, setShift] = useState({ x: -boardSize / 2, y: -boardSize / 2 });
  const [zoom, setZoom] = useState(1);

  const addShift = (deltaShift: { x: number; y: number }) => {
    setShift({ x: shift.x + deltaShift.x, y: shift.y + deltaShift.y });
  };

  const addZoom = (
    zoomFactor: number,
    center: { x: number; y: number },
    deltaShift: { x: number; y: number } = { x: 0, y: 0 }
  ) => {
    addShift({
      x: (shift.x - center.x) * (zoomFactor - 1) + deltaShift.x,
      y: (shift.y - center.y) * (zoomFactor - 1) + deltaShift.y,
    });
    setZoom(zoom * zoomFactor);
  };

  console.log(`Rendering Map, zoom:${zoom}, shift:${JSON.stringify(shift)}`);

  return (
    <IonContent fullscreen={true}>
      <div
        className='map'
        style={{ width: props.width + 'px', height: props.height + 'px' }}
      >
        <MouseHandler
          shift={shift}
          addShift={addShift}
          zoom={zoom}
          addZoom={addZoom}
          boardSize={boardSize}
        >
          <SingleTouchHandler
            shift={shift}
            addShift={addShift}
            zoom={zoom}
            addZoom={addZoom}
            boardSize={boardSize}
          >
            <DoubleTouchHandler
              shift={shift}
              addShift={addShift}
              zoom={zoom}
              addZoom={addZoom}
              boardSize={boardSize}
            />
          </SingleTouchHandler>
        </MouseHandler>
        <SlippyBoard
          boardSize={boardSize}
          shift={shift}
          zoom={zoom}
          layers={[
            {
              key: 'background',
              content: (
                <rect
                  x='0'
                  y='0'
                  width={boardSize}
                  height={boardSize}
                  fill='red'
                />
              ),
            },
            {
              key: 'tiles1',
              content: (
                <TiledLayer
                  height={props.height}
                  width={props.width}
                  shift={shift}
                  zoom={zoom}
                  tileSize={256}
                  nbTiles={nbTiles}
                  active={zoom < 2}
                />
              ),
            },
            {
              key: 'tiles2',
              transform: 'scale(.5)',
              content: (
                <TiledLayer
                  height={props.height * 2}
                  width={props.width * 2}
                  shift={{ x: shift.x * 2, y: shift.y * 2 }}
                  zoom={zoom}
                  tileSize={256}
                  nbTiles={nbTiles * 2}
                  active={zoom >= 2}
                />
              ),
            },
            { key: 'circle', content: <circle cx='50' cy='50' r='50' /> },
          ]}
        />
      </div>
    </IonContent>
  );
};

export default Map;
