import react, { useCallback, useState } from 'react';

import _ from 'lodash';

import { Transformation } from './viewport';

interface DoubleTouchHandlerProps {
  applyTransformations: (transformations: Transformation[]) => void;
  children: any;
}

const DoubleTouchHandler: react.FC<DoubleTouchHandlerProps> = (
  props: DoubleTouchHandlerProps
) => {
  const initialTouchState = {
    state: 'up',
    touches: [
      { x: -1, y: -1 },
      { x: -1, y: -1 },
    ],
    distance: -1,
    initialZoom: 1,
  };

  const [touchState, setTouchState] = useState(initialTouchState);

  console.log('DoubleTouchHandler, touchState: ' + JSON.stringify(touchState));

  const genericHandler = (event: any) => {
    console.log('Log - Event: ' + event.type);
    if (event.type.startsWith('touch')) {
      if (event.touches.length > 1) {
        console.log(
          `${event.touches.length} touches, (${event.touches[0].pageX}, ${event.touches[0].pageY}), (${event.touches[1].pageX}, ${event.touches[1].pageY})`
        );
      }

      console.log('touchState: ' + JSON.stringify(touchState));
      return;
    }
  };
  const touchCancelHandler = (event: any) => {
    genericHandler(event);
    throtteledTouchMoveHandler.cancel();
    setTouchState(initialTouchState);
  };

  const touchStartHandler = (event: any) => {
    genericHandler(event);
    if (event.touches.length === 2) {
      setTouchState({
        state: 'double',
        touches: [
          { x: event.touches[0].pageX, y: event.touches[0].pageY },
          { x: event.touches[1].pageX, y: event.touches[1].pageY },
        ],
        distance: Math.sqrt(
          (event.touches[0].pageX - event.touches[1].pageX) ** 2 +
            (event.touches[0].pageY - event.touches[1].pageY) ** 2
        ),
        initialZoom: 1,
      });
    }
  };

  const touchEndHandler = (event: any) => {
    genericHandler(event);
    setTouchState(initialTouchState);
    throtteledTouchMoveHandler.cancel();
  };

  const touchMoveHandler = (event: any) => {
    if (touchState.state === 'double') {
      if (event.touches.length === 2) {
        genericHandler(event);
        const newDistance = Math.sqrt(
          (event.touches[0].pageX - event.touches[1].pageX) ** 2 +
            (event.touches[0].pageY - event.touches[1].pageY) ** 2
        );
        const factor = newDistance / touchState.distance;
        console.log(`+++++++++ ZOOM Factor is ${factor} ++++++++++`);
        setTouchState({
          state: 'double',
          touches: [
            { x: event.touches[0].pageX, y: event.touches[0].pageY },
            { x: event.touches[1].pageX, y: event.touches[1].pageY },
          ],
          distance: touchState.distance,
          initialZoom: 1,
        });
        const previousCenter = {
          x: (touchState.touches[0].x + touchState.touches[1].x) / 2,
          y: (touchState.touches[0].y + touchState.touches[1].y) / 2,
        };
        const currentCenter = {
          x: (event.touches[0].pageX + event.touches[1].pageX) / 2,
          y: (event.touches[0].pageY + event.touches[1].pageY) / 2,
        };
        props.applyTransformations([
          {
            scale: {
              factor: factor,
              center: currentCenter,
            },
          },
          {
            translate: {
              x: currentCenter.x - previousCenter.x,
              y: currentCenter.y - previousCenter.y,
            },
          },
        ]);
      }
    }
  };

  const throtteledTouchMoveHandler = useCallback(
    _.throttle(touchMoveHandler, 100),
    [touchState.state]
  );

  return (
    <div
      className='viewport double-touch-handler'
      onTouchStart={touchStartHandler}
      onTouchMove={throtteledTouchMoveHandler}
      onTouchEnd={touchEndHandler}
      onTouchCancel={touchCancelHandler}
    >
      {props.children}
    </div>
  );
};

export default DoubleTouchHandler;
