"use strict";

require("core-js/modules/es.object.assign.js");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

require("core-js/modules/web.dom-collections.iterator.js");

require("core-js/modules/es.promise.js");

var _react = _interopRequireWildcard(require("react"));

var _fiber = require("@react-three/fiber");

var _drei = require("@react-three/drei");

var THREE = _interopRequireWildcard(require("three"));

var _lodash = _interopRequireDefault(require("lodash"));

var _xr = require("@react-three/xr");

const _excluded = ["Action", "mic", "setActionPlayer", "animations", "emojiIcon", "controlEvent"];

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

const TOUCHE_TYPES = {
  ONE: THREE.TOUCH.ROTATE,
  TWO: THREE.TOUCH.DOLLY_ROTATE
};
const STATE = {
  NONE: -1,
  ROTATE: 0,
  DOLLY: 1,
  PAN: 2,
  TOUCH_ROTATE: 3,
  TOUCH_PAN: 4,
  TOUCH_DOLLY_PAN: 5,
  TOUCH_DOLLY_ROTATE: 6
};
let vid = null;
let isRecording = false;
let fwdValue = 0;
let bkdValue = 0;
let rgtValue = 0;
let lftValue = 0;
let _keys = {
  forward: false,
  backward: false,
  left: false,
  right: false,
  space: false,
  shift: false,
  backspace: false
};
let moveDiVec = new THREE.Vector3();
let tempVector = new THREE.Vector3();
let upVector = new THREE.Vector3(0, 1, 0);
let downVector = new THREE.Vector3(0, -1, 0);
let joyManager;
let walkVelocity = 2;
let SPEED = 1; // for rotating character

let previousPosition = new THREE.Vector3();
let directionalVector = new THREE.Vector3();
let quaternion = new THREE.Quaternion();
let tmpDirectionVector = new THREE.Vector3();
const raycaster = new THREE.Raycaster();
const raycasterCamera = new THREE.Raycaster();
let _moveDirection = null; // for BVCameraController

const touchActions = {};
let mapControllerRotateEnabled = true;
let mapControllerZoomEnabled = true;
let mapControllerPanEnabled = false;
let mapControllerState = STATE.NONE;
const rotateStart = new THREE.Vector2();
const panStart = new THREE.Vector2();
const dollyStart = new THREE.Vector2();
const dollyEnd = new THREE.Vector2();
const dollyDelta = new THREE.Vector2();
const rotateEnd = new THREE.Vector2();
const rotateDelta = new THREE.Vector2();
const rotateSpeed = 0.8;
const spherical = new THREE.Spherical();
const sphericalDelta = new THREE.Spherical();
const panEnd = new THREE.Vector2();
const panDelta = new THREE.Vector2();
const panSpeed = 1.0;
const tmpOffset = new THREE.Vector3();
const tmpChangedPanOffset = new THREE.Vector3();
const tmpVector = new THREE.Vector3();
const cameraTarget = new THREE.Vector3();
const panOffset = new THREE.Vector3();
let screenSpacePanning = false;
const zoomSpeed = 1.0;
let mapControllerScale = 1;
let enableZoom = true;
const tmpDestinationTarget = new THREE.Vector3();
const mapControllerDampingFactor = 0.25;
const mapControllerDampingEnabled = false;
const tmpQuat = new THREE.Quaternion();
const tmpQuatInverse = new THREE.Quaternion();
let minAzimuthAngle = -Infinity; // radians

let maxAzimuthAngle = Infinity; // radians

let minPolarAngle = Math.PI / 4;
let maxPolarAngle = Math.PI / 2 + 0.1; // radians

let minDistance = 1.2;
let maxDistance = 4;
const tempTrackerPanPosition = new THREE.Vector3();
const panTracker = new THREE.Vector3();
const gravity = 4;
const forwardSensistivity = 0.05;
const rotationSensitivity = 0.05;
const deadzone = 0.05;
const forwardAxis = 3;
const rotationAxis = 2; // =====

const handledirectionOffset = input => {
  let directionOffset = 0; // console.log(input);

  if (input._moveDirection) {
    if (input._moveDirection.x === 0) {
      if (input._moveDirection.y > 0) {
        directionOffset = Math.PI;
      } else {
        directionOffset = 2.0 * Math.PI;
      }
    } else if (input._moveDirection.y === 0) {
      if (input._moveDirection.x > 0) {
        directionOffset = 0.5 * Math.PI;
      } else {
        directionOffset = 1.5 * Math.PI;
      }
    } else {
      if (input._moveDirection.x > 0 && input._moveDirection.y < 0) {
        directionOffset = Math.atan2(input._moveDirection.x, input._moveDirection.y * -1.0);
      } else if (input._moveDirection.x > 0 && input._moveDirection.y > 0) {
        directionOffset = 0.5 * Math.PI + Math.atan2(input._moveDirection.y, input._moveDirection.x);
      } else if (input._moveDirection.x < 0 && input._moveDirection.y > 0) {
        directionOffset = Math.PI + Math.atan2(input._moveDirection.x * -1.0, input._moveDirection.y);
      } else if (input._moveDirection.x < 0 && input._moveDirection.y < 0) {
        directionOffset = 1.5 * Math.PI + Math.atan2(input._moveDirection.y * -1.0, input._moveDirection.x * -1.0);
      }
    }
  } else {
    if (input._keys.forward) {
      if (input._keys.left) {
        directionOffset = Math.PI / 4.0;
      } else if (input._keys.right) {
        directionOffset = -Math.PI / 4.0;
      }
    } else if (input._keys.backward) {
      if (input._keys.left) {
        directionOffset = Math.PI / 4.0 + Math.PI / 2.0;
      } else if (input._keys.right) {
        directionOffset = -Math.PI / 4.0 - Math.PI / 2.0;
      } else {
        directionOffset = Math.PI;
      }
    } else if (input._keys.left) {
      directionOffset = Math.PI / 2.0;
    } else if (input._keys.right) {
      directionOffset = -Math.PI / 2.0;
    }

    directionOffset += Math.PI;
  }

  return directionOffset;
};

const Layout = _ref => {
  let {
    Action,
    mic,
    setActionPlayer,
    animations,
    emojiIcon,
    controlEvent
  } = _ref,
      props = _objectWithoutProperties(_ref, _excluded);

  // console.log('props::', props);
  const {
    scene,
    camera,
    setSize
  } = (0, _fiber.useThree)();
  const Mycamera = (0, _react.useRef)();
  const [aName, setaName] = (0, _react.useState)(''); // const [BeforeaName, setBeforeaName] = useState('idle');

  const moveRef = props.children.ref;
  const socketController = props.socketController;
  const walls = props.walls;
  const CameraDistance = props.CameraDistance || 1;
  const [nipplejs] = (0, _react.useState)(() => require('nipplejs')); // const rightController = useController('right')
  // const { player } = useXR()

  const forward = (0, _react.useRef)(new THREE.Vector3());
  (0, _react.useEffect)(() => {
    addJoystick();
    const canvas = document.querySelector('canvas');
    document.addEventListener('keydown', e => _onKeyDown(e));
    document.addEventListener('keyup', e => _onKeyUp(e));

    if (canvas) {
      canvas.addEventListener('pointerdown', e => _onTouchStart(e));
      canvas.addEventListener('pointermove', e => _onTouchMove(e));
      canvas.addEventListener('pointerup', e => _onTouchEnd(e));
      canvas.addEventListener('pointercancel', e => _onTouchCancel(e));
      canvas.addEventListener('touchstart', e => _onTouchStart(e), {
        passive: false
      });
      canvas.addEventListener('touchmove', e => _onTouchMove(e));
      canvas.addEventListener('touchend', e => _onTouchEnd(e));
      canvas.addEventListener('touchcancel', e => _onTouchCancel(e));
      canvas.addEventListener('wheel', e => onMouseWheel(e));
    }
  }, []);
  (0, _react.useEffect)(() => {
    if (Action) {
      handleAnimation(Action);
    } else {
      handleAnimation('idle');
    }
  }, [Action]);
  (0, _react.useEffect)(() => {
    if (aName == 'walk' || aName == 'run') {
      setActionPlayer('');
    }
  }, [aName]);

  const handleAnimation = a => {
    if (a !== aName) {
      setaName(a);
      handleUpdateSocket(a);
    }
  }; // for BVCameraController


  const UpdateCameraController = () => {
    tmpDestinationTarget.copy(moveRef.current.position);
    tmpDestinationTarget.y += 1;
    let moveOffset = tmpDestinationTarget.sub(cameraTarget);

    if (mapControllerDampingEnabled) {
      cameraTarget.addScaledVector(moveOffset, mapControllerDampingFactor);
    } else {
      cameraTarget.add(moveOffset);
    } // so camera.up is the orbit axis


    tmpQuat.setFromUnitVectors(Mycamera.current.up, upVector);
    tmpQuatInverse.copy(tmpQuat).invert();
    const twoPI = 2 * Math.PI;
    const position = Mycamera.current.position;
    tmpOffset.copy(position).sub(cameraTarget); // rotate offset to "y-axis-is-up" space

    tmpOffset.applyQuaternion(tmpQuat); // angle from z-axis around y-axis

    spherical.setFromVector3(tmpOffset);

    if (mapControllerDampingEnabled) {
      spherical.theta += sphericalDelta.theta * mapControllerDampingFactor;
      spherical.phi += sphericalDelta.phi * mapControllerDampingFactor;
    } else {
      spherical.theta += sphericalDelta.theta;
      spherical.phi += sphericalDelta.phi;
    }

    let min = minAzimuthAngle;
    let max = maxAzimuthAngle;

    if (isFinite(min) && isFinite(max)) {
      if (min < -Math.PI) min += twoPI;else if (min > Math.PI) min -= twoPI;
      if (max < -Math.PI) max += twoPI;else if (max > Math.PI) max -= twoPI;

      if (min <= max) {
        spherical.theta = Math.max(min, Math.min(max, spherical.theta));
      } else {
        spherical.theta = spherical.theta > (min + max) / 2 ? Math.max(min, spherical.theta) : Math.min(max, spherical.theta);
      }
    } // restrict phi to be between desired limits


    spherical.phi = Math.max(minPolarAngle, Math.min(maxPolarAngle, spherical.phi));
    spherical.makeSafe();
    spherical.radius *= mapControllerScale; // restrict radius to be between desired limits

    spherical.radius = Math.max(minDistance, Math.min(maxDistance, spherical.radius)); // move target to panned location

    tempTrackerPanPosition.copy(panTracker);

    if (mapControllerDampingEnabled) {
      cameraTarget.addScaledVector(panOffset, mapControllerDampingFactor);
    } else {
      cameraTarget.add(panOffset);
    }

    tmpOffset.setFromSpherical(spherical); // rotate offset back to "camera-up-vector-is-up" space

    tmpOffset.applyQuaternion(tmpQuatInverse);
    position.copy(cameraTarget).add(tmpOffset);
    doesCollideAnyColliderCamera(cameraTarget, tmpOffset);
    Mycamera.current.lookAt(cameraTarget);

    if (mapControllerDampingEnabled) {
      sphericalDelta.theta *= 1 - mapControllerDampingFactor;
      sphericalDelta.phi *= 1 - mapControllerDampingFactor;
      panOffset.multiplyScalar(1 - mapControllerDampingFactor);
    } else {
      sphericalDelta.set(0, 0, 0);
      panOffset.set(0, 0, 0);
    }

    mapControllerScale = 1;
  };

  const _pan = (deltaX, deltaY) => {
    // perspective
    const position = Mycamera.current.position;
    tmpOffset.copy(position).sub(cameraTarget);
    let targetDistance = tmpOffset.length(); // half of the fov is center to top of screen

    targetDistance *= Math.tan(Mycamera.current.fov / 2 * Math.PI / 180.0); // we use only clientHeight here so aspect ratio does not distort speed

    _panLeft(2 * deltaX * targetDistance / window.innerHeight, Mycamera.current.matrix);
  };

  const _panLeft = (distance, objectMatrix) => {
    tmpVector.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix

    tmpVector.multiplyScalar(-distance);
    panOffset.add(tmpVector);
  };

  const _panUp = (distance, objectMatrix) => {
    if (screenSpacePanning) {
      tmpVector.setFromMatrixColumn(objectMatrix, 1);
    } else {
      tmpVector.setFromMatrixColumn(objectMatrix, 0);
      tmpVector.crossVectors(Mycamera.current.up, tmpVector);
    }

    tmpVector.multiplyScalar(distance);
    panOffset.add(tmpVector);
  };

  const _handleTouchMovePan = touches => {
    if (touches.length == 1) {
      panEnd.set(touches[0].pageX, touches[0].pageY);
    } else {
      const x = 0.5 * (touches[0].pageX + touches[1].pageX);
      const y = 0.5 * (touches[0].pageY + touches[1].pageY);
      panEnd.set(x, y);
    }

    panDelta.subVectors(panEnd, panStart).multiplyScalar(panSpeed);

    _pan(panDelta.x, panDelta.y);

    panStart.copy(panEnd);
  };

  const _rotateLeft = angle => {
    sphericalDelta.theta -= angle;
  };

  const _rotateUp = angle => {
    sphericalDelta.phi -= angle;
  };

  const _handleTouchMoveDolly = touches => {
    const dx = touches[0].pageX - touches[1].pageX;
    const dy = touches[0].pageY - touches[1].pageY;
    const distance = Math.sqrt(dx * dx + dy * dy);
    dollyEnd.set(0, distance);
    dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, zoomSpeed));
    dollyOut(dollyDelta.y);
    dollyStart.copy(dollyEnd);
  };

  const _handleTouchMoveRotate = touches => {
    if (touches.length === 1) {
      rotateEnd.set(touches[0].pageX, touches[0].pageY);
    } else {
      const x = 0.5 * (touches[0].pageX + touches[1].pageX);
      const y = 0.5 * (touches[0].pageY + touches[1].pageY);
      rotateEnd.set(x, y);
    }

    rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(rotateSpeed);

    _rotateLeft(2 * Math.PI * rotateDelta.x / window.innerWidth); // yes, height


    _rotateUp(2 * Math.PI * rotateDelta.y / window.innerHeight);

    rotateStart.copy(rotateEnd);
  };

  const _handleTouchMoveDollyPan = touches => {
    if (mapControllerZoomEnabled) _handleTouchMoveDolly(touches);
    if (mapControllerPanEnabled) _handleTouchMovePan(touches);
  };

  const onMouseWheel = event => {
    if (enableZoom === false || mapControllerState !== STATE.NONE && mapControllerState !== STATE.ROTATE) return;
    handleMouseWheel(event);
  };

  const getZoomScale = () => {
    return Math.pow(0.95, zoomSpeed);
  };

  const handleMouseWheel = event => {
    if (event.deltaY < 0) {
      dollyIn(getZoomScale());
    } else if (event.deltaY > 0) {
      dollyOut(getZoomScale());
    }

    ;
  };

  const dollyIn = dollyScale => {
    mapControllerScale *= dollyScale;
  };

  const dollyOut = dollyScale => {
    mapControllerScale /= dollyScale;
  };

  const _onTouchMove = event => {
    //event.preventDefault();
    if ('ontouchstart' in document.documentElement) {
      if (!event.touches) {
        // prevent double event from pointermove in mobile
        return;
      }
    }

    let touches = [];

    if (event.touches) {
      touches.push(event.touches[0]);

      if (event.touches.length > 1) {
        touches.push(event.touches[1]);
      }
    } else {
      touches.push(event);
    }

    if (_moveDirection && (_moveDirection.x !== 0 || _moveDirection.y !== 0)) {
      touches.splice(0, 1);
    }

    if (mapControllerState === STATE.NONE) {
      return;
    }

    switch (mapControllerState) {
      case STATE.TOUCH_ROTATE:
        if (mapControllerRotateEnabled === false) return;

        _handleTouchMoveRotate(touches);

        ;
        break;

      case STATE.TOUCH_PAN:
        if (mapControllerPanEnabled === false) return;

        _handleTouchMovePan(touches);

        ;
        break;

      case STATE.TOUCH_DOLLY_PAN:
        if (mapControllerZoomEnabled === false && mapControllerPanEnabled === false) return;

        _handleTouchMoveDollyPan(touches);

        ;
        break;

      case STATE.TOUCH_DOLLY_ROTATE:
        if (mapControllerZoomEnabled === false && mapControllerRotateEnabled === false) return;

        _handleTouchMoveDollyRotate(touches);

        ;
        break;

      default:
        mapControllerState = STATE.NONE;
    }
  };

  const _handleTouchMoveDollyRotate = touches => {
    if (mapControllerZoomEnabled) _handleTouchMoveDolly(touches);
    if (mapControllerRotateEnabled) _handleTouchMoveRotate(touches);
  };

  const _handleTouchStartRotate = (touch0, touch1) => {
    if (touch1) {
      const x = 0.5 * (touch0.pageX + touch1.pageX);
      const y = 0.5 * (touch0.pageY + touch1.pageY);
      rotateStart.set(x, y);
    } else {
      rotateStart.set(touch0.pageX, touch0.pageY);
    }
  };

  const _handleTouchStartPan = (touch0, touch1) => {
    if (touch1) {
      const x = 0.5 * (touch0.pageX + touch1.pageX);
      const y = 0.5 * (touch0.pageY + touch1.pageY);
      panStart.set(x, y);
    } else {
      panStart.set(touch0.pageX, touch0.pageY);
    }
  };

  const _handleTouchStartDolly = (touch0, touch1) => {
    const dx = touch0.pageX - touch1.pageX;
    const dy = touch0.pageY - touch1.pageY;
    const distance = Math.sqrt(dx * dx + dy * dy);
    dollyStart.set(0, distance);
  };

  const _handleTouchStartDollyPan = (touch0, touch1) => {
    if (mapControllerZoomEnabled) _handleTouchStartDolly(touch0, touch1);
    if (mapControllerPanEnabled) _handleTouchStartPan(touch0, touch1);
  };

  const _handleTouchStartDollyRotate = (touch0, touch1) => {
    if (mapControllerZoomEnabled) _handleTouchStartDolly(touch0, touch1);
    if (mapControllerRotateEnabled) _handleTouchStartRotate(touch0, touch1);
  };

  const _onTouchEnd = event => {
    //event.preventDefault();
    if ('ontouchstart' in document.documentElement) {
      if (!event.touches) {
        // prevent double event from pointerup in mobile
        return;
      }
    }

    mapControllerState = STATE.NONE;

    if (event.changedTouches && event.touches) {
      for (let changedTouchIndex = event.changedTouches.length - 1; changedTouchIndex >= 0; changedTouchIndex--) {
        const theTouch = event.changedTouches[changedTouchIndex];

        if (touchActions['' + theTouch.identifier]) {
          delete touchActions['' + theTouch.identifier];
        }
      }
    } else {
      if (touchActions['' + event.identifier]) {
        delete touchActions['' + event.identifier];
      }
    }
  };

  const _onTouchStart = event => {
    //event.preventDefault();
    // if(lastDownTarget == canvas)
    // if ('ontouchstart' in document.documentElement) {
    //     if (!event.touches) {
    //         // prevent double event from pointerdown in mobile
    //     }
    // }
    let touches = [];

    if (event.touches) {
      touches.push(event.touches[0]);

      if (event.touches.length > 1) {
        touches.push(event.touches[1]);
      }
    } else {
      touches.push(event);
    }

    if (_moveDirection && (_moveDirection.x !== 0 || _moveDirection.y !== 0)) {
      touches.splice(0, 1);
    } // touches = touches.filter((theTouch) => {
    //   return !touchActions[''+theTouch.identifier];
    // });


    switch (touches.length) {
      case 1:
        switch (TOUCHE_TYPES.ONE) {
          case THREE.TOUCH.ROTATE:
            if (mapControllerRotateEnabled === false) return;

            _handleTouchStartRotate(touches[0], touches[1]);

            mapControllerState = STATE.TOUCH_ROTATE;
            break;

          case THREE.TOUCH.PAN:
            if (mapControllerPanEnabled === false) return;

            _handleTouchStartPan(touches[0], touches[1]);

            mapControllerState = STATE.TOUCH_PAN;
            break;

          default:
            mapControllerState = STATE.NONE;
        }

        break;

      case 2:
        switch (TOUCHE_TYPES.TWO) {
          case THREE.TOUCH.DOLLY_PAN:
            if (mapControllerZoomEnabled === false && mapControllerPanEnabled === false) return;

            _handleTouchStartDollyPan(touches[0], touches[1]);

            mapControllerState = STATE.TOUCH_DOLLY_PAN;
            break;

          case THREE.TOUCH.DOLLY_ROTATE:
            if (mapControllerZoomEnabled === false && mapControllerRotateEnabled === false) return;

            _handleTouchStartDollyRotate(touches[0], touches[1]);

            mapControllerState = STATE.TOUCH_DOLLY_ROTATE;
            break;

          default:
            mapControllerState = STATE.NONE;
        }

        break;

      default:
        mapControllerState = STATE.NONE;
    }
  };

  const _onTouchCancel = event => {};

  const getAzimuthalAngle = () => {
    return spherical.theta;
  }; // =====


  const _onKeyDown = e => {
    switch (e.keyCode) {
      case 87:
        // w
        _keys.forward = true;
        break;

      case 65:
        // a
        _keys.left = true;
        break;

      case 83:
        // s
        _keys.backward = true;
        break;

      case 68:
        // d
        _keys.right = true;
        break;

      case 32:
        // SPACE
        _keys.space = true;
        break;

      case 16:
        // SHIFT
        _keys.shift = true;
        break;

      case 8:
        // BACKSPACE
        _keys.backspace = true;
        break;

      default:
        break;
    }
  };

  const _onKeyUp = e => {
    switch (e.keyCode) {
      case 87:
        // w
        _keys.forward = false;
        break;

      case 65:
        // a
        _keys.left = false;
        break;

      case 83:
        // s
        _keys.backward = false;
        break;

      case 68:
        // d
        _keys.right = false;
        break;

      case 32:
        // SPACE
        _keys.space = false;
        break;

      case 16:
        // SHIFT
        _keys.shift = false;
        break;

      case 8:
        // BACKSPACE
        _keys.backspace = false;
        break;

      default:
        break;
    }
  };

  const addJoystick = () => {
    const options = {
      zone: document.getElementById('joystickWrapper1'),
      size: 100,
      multitouch: true,
      maxNumberOfNipples: 2,
      mode: 'static',
      restJoystick: true,
      shape: 'circle',
      position: {
        bottom: '40%',
        left: '90px'
      },
      dynamicPage: true,
      color: '#fff'
    };
    joyManager = nipplejs.create(options);
    joyManager.on('move', function (evt, data) {
      const forward = data.vector.y;
      const turn = data.vector.x;

      if (_moveDirection === null) {
        _moveDirection = {
          x: 0,
          y: 0
        };
      }

      _moveDirection.x = turn;
      _moveDirection.y = forward;

      if (forward > 0) {
        fwdValue = Math.abs(forward);
        bkdValue = 0;
      } else if (forward < 0) {
        fwdValue = 0;
        bkdValue = Math.abs(forward);
      }

      if (turn > 0) {
        lftValue = 0;
        rgtValue = Math.abs(turn);
      } else if (turn < 0) {
        lftValue = Math.abs(turn);
        rgtValue = 0;
      }
    });
    joyManager.on('end', function (evt) {
      bkdValue = 0;
      fwdValue = 0;
      lftValue = 0;
      rgtValue = 0;
      _moveDirection = null;
    });
  };

  const moveControl = (angle, delta) => {
    if (controlEvent) return false; // if (rightController) {
    //     if (rightController.inputSource.gamepad) {
    //         if (rightController.inputSource.gamepad.axes) {
    //             if (rightController.inputSource.gamepad.axes[2] || rightController.inputSource.gamepad.axes[3]) {
    //                 _keys.right = false;
    //                 _keys.left = false;
    //                 _keys.forward = false;
    //                 _keys.backward = false;
    //                 if (rightController.inputSource.gamepad.axes[2] * 1 > 0) {
    //                     _keys.right = true;
    //                 } else if (rightController.inputSource.gamepad.axes[2] * 1 < 0) {
    //                     _keys.left = true;
    //                 }
    //                 if (rightController.inputSource.gamepad.axes[3] * 1 > 0) {
    //                     _keys.backward = true;
    //                 } else if (rightController.inputSource.gamepad.axes[3] * 1 < 0) {
    //                     _keys.forward = true;
    //                 }
    //             }
    //         }
    //     }
    // }

    if (!_keys.forward && !_keys.backward && !_keys.left && !_keys.right && _moveDirection === null) {
      return false;
    }

    let directionOffset;

    if (_moveDirection) {
      directionOffset = handledirectionOffset({
        _moveDirection
      });
      const speedSize = Math.sqrt(_moveDirection.x * _moveDirection.x + _moveDirection.y * _moveDirection.y);

      if (speedSize < 0.5) {
        handleAnimation('walk'); // handleUpdateSocket('walk')
      } else {
        handleAnimation('run'); // handleUpdateSocket('run')
      }

      SPEED = speedSize * 2;
    } else {
      if (_keys.space) {
        handleAnimation('jump'); // handleUpdateSocket('run')
      } else if (!_keys.shift) {
        handleAnimation('run'); // handleUpdateSocket('run')

        SPEED = 2;
      } else if (_keys.forward || _keys.backward || _keys.left || _keys.right) {
        handleAnimation('walk'); // handleUpdateSocket('walk')

        SPEED = 1;
      } else {
        return false;
      }

      directionOffset = handledirectionOffset({
        _keys
      });
    }

    quaternion.setFromAxisAngle(upVector, angle + directionOffset);
    moveRef.current.quaternion.rotateTowards(quaternion, 0.7);
    tempVector.copy(moveRef.current.position);
    Mycamera.current.getWorldDirection(moveDiVec);
    moveDiVec.y = 0;
    moveDiVec.normalize();
    moveDiVec.applyAxisAngle(upVector, directionOffset);
    moveDiVec.x *= -1;
    moveDiVec.z *= -1; // character center height

    tempVector.y += 0.8; // to do check wall

    if (doesCollideAnyCollider(tempVector, moveDiVec)) {
      return true;
    }

    const theFirstFloorInfo = getFirstFloorInfo(tempVector);
    const movedX = moveDiVec.x * walkVelocity * SPEED * delta;
    const movedZ = moveDiVec.z * walkVelocity * SPEED * delta;
    moveRef.current.position.x += movedX;
    moveRef.current.position.z += movedZ;

    if (theFirstFloorInfo.object) {
      // tempVector.y = theFirstFloorInfo.y * gravity * delta;
      tempVector.y = theFirstFloorInfo.y;
    } else {
      tempVector.y -= 0.8;
    }

    if (controlEvent) {
      const movedY = (tempVector.y - moveRef.current.position.y) * walkVelocity * gravity * delta;
      moveRef.current.position.y += movedY;
      Mycamera.current.position.x += movedX;
      Mycamera.current.position.y += movedY;
      Mycamera.current.position.z += movedZ;
    }

    return true;
  };

  const getFirstFloorInfo = thePotision => {
    let leastDistance = 1000;
    const firstFloorInfo = {
      object: null,
      y: 0
    };

    for (let collisionBoxIndex = 0; collisionBoxIndex < walls.length; collisionBoxIndex++) {
      const collisionBox = walls[collisionBoxIndex];
      raycaster.set(thePotision, downVector);
      const intersects = raycaster.intersectObject(collisionBox);

      for (let intersectIndex = 0; intersectIndex < intersects.length; intersectIndex++) {
        const theIntersect = intersects[intersectIndex];

        if (theIntersect.distance < leastDistance) {
          leastDistance = theIntersect.distance;
          firstFloorInfo.object = collisionBox;
          firstFloorInfo.y = theIntersect.point.y;
        }
      }
    }

    return firstFloorInfo;
  };

  const doesCollideAnyCollider = (thePotision, theDirection) => {
    for (let collisionBoxIndex = 0; collisionBoxIndex < walls.length; collisionBoxIndex++) {
      const collisionBox = walls[collisionBoxIndex];
      raycaster.set(thePotision, theDirection);
      const intersects = raycaster.intersectObject(collisionBox);

      for (let intersectIndex = 0; intersectIndex < intersects.length; intersectIndex++) {
        const theIntersect = intersects[intersectIndex];

        if (theIntersect.distance <= 0.3) {
          return true;
        }
      }
    }

    return false;
  };

  const doesCollideAnyColliderCamera = (thePotision, theDirection) => {
    for (let collisionBoxIndex = 0; collisionBoxIndex < walls.length; collisionBoxIndex++) {
      const collisionBox = walls[collisionBoxIndex];
      raycasterCamera.set(thePotision, theDirection);
      const intersects = raycasterCamera.intersectObject(collisionBox, false);

      for (let intersectIndex = 0; intersectIndex < intersects.length; intersectIndex++) {
        const theIntersect = intersects[intersectIndex];

        if (theIntersect.distance * CameraDistance < thePotision.distanceTo(theDirection)) {
          camera.position.copy(theIntersect.point);
        }
      }
    }
  };

  const handleUpdateSocket = state => {
    socketController.SendUpdatedTransform(state, moveRef.current.position, moveRef.current.quaternion, emojiIcon);
  };

  const updatePlayer = delta => {
    if (controlEvent) return; // move the player

    const angle = getAzimuthalAngle();

    if (!moveControl(angle, delta)) {
      // no move => idle
      if (!Action) {
        handleAnimation('idle');
      }
    }

    cameraTarget.copy(moveRef.current.position);
    const hudGroup = scene.getObjectByName("hudGroup");

    if (hudGroup) {
      hudGroup.position.copy(Mycamera.current.position);
      Mycamera.current.getWorldDirection(tmpDirectionVector);
      hudGroup.position.add(tmpDirectionVector.multiplyScalar(Math.sqrt(3.0) / 2.0));
      hudGroup.lookAt(Mycamera.current.position);
      hudGroup.scale.set(1, 1, 1);
    }
  };

  (0, _fiber.useFrame)(async (state, delta) => {
    UpdateCameraController();
    updatePlayer(delta);
    handleUpdateSocket(aName); // if (rightController && player) {
    //     const { axes } = rightController.inputSource.gamepad;
    //     const camera = player.children[0];
    //     const cameraMatrix = camera.matrixWorld.elements;
    //     forward.current
    //         .set(-cameraMatrix[8], -cameraMatrix[9], -cameraMatrix[10])
    //         .normalize();
    //     forward.current.y = 0;
    //     player.position.add(
    //         forward.current.multiplyScalar(
    //             (Math.abs(axes[forwardAxis]) > deadzone ? -axes[forwardAxis] : 0) *
    //             forwardSensistivity,
    //         ),
    //     );
    //     player.rotation.y -=
    //         (Math.abs(axes[rotationAxis]) > deadzone ? axes[rotationAxis] : 0) *
    //         rotationSensitivity;
    //     moveRef.current.quaternion.rotateTowards(player.quaternion, 0.7)
    //     moveRef.current.position.copy(player.position)
    // }
  });
  (0, _react.useEffect)(() => {
    if (animations && Object.keys(animations).length > 0) {
      if (aName !== 'walk' && aName !== 'run' && aName !== 'idle' && aName !== 'sitting_idle') {
        var _animations$aName;

        (_animations$aName = animations[aName]) === null || _animations$aName === void 0 ? void 0 : _animations$aName.action.setLoop(THREE.LoopOnce).reset().fadeIn(0.3).play();
      } else {
        var _animations$aName2;

        (_animations$aName2 = animations[aName]) === null || _animations$aName2 === void 0 ? void 0 : _animations$aName2.action.reset().fadeIn(0.3).play();
      }
    }

    return () => {
      var _animations$aName3, _animations$aName3$ac;

      (_animations$aName3 = animations[aName]) === null || _animations$aName3 === void 0 ? void 0 : (_animations$aName3$ac = _animations$aName3.action) === null || _animations$aName3$ac === void 0 ? void 0 : _animations$aName3$ac.fadeOut(0.3);
    };
  }, [aName]);
  return /*#__PURE__*/_react.default.createElement("group", null, props.children, /*#__PURE__*/_react.default.createElement(_drei.PerspectiveCamera, _extends({
    ref: Mycamera,
    fov: 55
  }, props.cameraConfig, {
    aspect: window.innerWidth / window.innerHeight,
    near: 0.99 * Math.sqrt(3.0) / 2.0,
    far: 1000,
    makeDefault: true,
    rotation: [Math.PI / 2, 0, 0]
  })));
};

var _default = Layout;
exports.default = _default;