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

import _ from 'lodash';

import Background from './background';

import '../theme/viewport.css';

const Viewport: react.FC<{}> = (props: {}) => {
  console.log(`--- Rendering viewport, props: ${JSON.stringify(props)} ---`);

  const [shift, setShift] = useState({ x: 1000, y: 1000 });

  const initialMouseState = {
    down: false,
    starting: { x: -1, y: -1 },
  };

  const initialTouchState = {
    state: 'up',
    touches: [
      { x: -1, y: -1 },
      { x: -1, y: -1 },
    ],
  };

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

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

  const genericHandler = (event: any) => {
    console.log('Log - Event: ' + event.type);
    if (event.type.startsWith('mouse')) {
      console.log(`Mouse : ${event.pageX}, ${event.pageY}`);
      console.log('mouseState: ' + JSON.stringify(mouseState));
      return;
    }
    if (event.type.startsWith('touch')) {
      if (event.touches.length > 0) {
        console.log(
          `Touch : ${event.touches.length} touches, ${event.touches[0].pageX}, ${event.touches[0].pageY}`
        );
      }
      console.log('touchState: ' + JSON.stringify(touchState));
      return;
    }
  };

  // TODO: implement resize event
  // TODO: check boundaries

  const mouseLeaveHandler = (event: any) => {
    genericHandler(event);
    event.preventDefault();
    throtteledMouseMoveHandler.cancel();
    throtteledTouchMoveHandler.cancel();
    setMouseState(initialMouseState);
    setTouchState(initialTouchState);
  };

  const mouseDownHandler = (event: any) => {
    genericHandler(event);
    event.preventDefault();
    setMouseState({
      down: true,
      starting: { x: event.pageX, y: event.pageY },
    });
  };

  const mouseUpHandler = (event: any) => {
    genericHandler(event);
    event.preventDefault();
    setMouseState(initialMouseState);
  };

  const mouseMoveHandler = (event: any) => {
    event.preventDefault();
    if (mouseState.down) {
      genericHandler(event);
      // setShift((shift) => ({
      //   x: shift.x + (mouseState.starting.x - event.pageX),
      //   y: shift.y + (mouseState.starting.y - event.pageY),
      // }));
      // setMouseState((mouseState) => ({
      //   down: true,
      //   starting: {
      //     x: event.pageX,
      //     y: event.pageY,
      //   },
      // }));
      setShift({
        x: shift.x + (mouseState.starting.x - event.pageX),
        y: shift.y + (mouseState.starting.y - event.pageY),
      });
      setMouseState({
        down: true,
        starting: {
          x: event.pageX,
          y: event.pageY,
        },
      });
    }
  };

  const throtteledMouseMoveHandler = useCallback(
    _.throttle(mouseMoveHandler, 50),
    [mouseState.down]
  );

  // Touch

  const touchStartHandler = (event: any) => {
    genericHandler(event);
    //    event.preventDefault();
    if (event.touches.length === 1) {
      setTouchState({
        state: 'pointer',
        touches: [{ x: event.touches[0].pageX, y: event.touches[0].pageY }],
      });
    }
  };

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

  const touchMoveHandler = (event: any) => {
    //  event.preventDefault();
    if (touchState.state === 'pointer') {
      if (event.touches.length === 1) {
        genericHandler(event);
        setShift({
          x: shift.x + (touchState.touches[0].x - event.touches[0].pageX),
          y: shift.y + (touchState.touches[0].y - event.touches[0].pageY),
        });
        setTouchState({
          state: 'pointer',
          touches: [
            {
              x: event.touches[0].pageX,
              y: event.touches[0].pageY,
            },
          ],
        });
      }
    }
  };

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

  return (
    <div
      className='viewport'
      onMouseDown={mouseDownHandler}
      onMouseMove={throtteledMouseMoveHandler}
      onMouseUp={mouseUpHandler}
      onMouseLeave={mouseLeaveHandler}
      onTouchStart={touchStartHandler}
      onTouchMove={throtteledTouchMoveHandler}
      onTouchEnd={touchEndHandler}
      onTouchCancel={mouseLeaveHandler}
    >
      <Background shift={shift} />
    </div>
  );
};

export default Viewport;
