"use strict";

require("core-js/modules/es.weak-map.js");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
require("core-js/modules/es.array.reduce.js");
require("core-js/modules/es.number.to-fixed.js");
require("core-js/modules/es.parse-float.js");
require("core-js/modules/es.parse-int.js");
require("core-js/modules/es.regexp.exec.js");
require("core-js/modules/es.regexp.to-string.js");
require("core-js/modules/es.string.match.js");
require("core-js/modules/esnext.iterator.constructor.js");
require("core-js/modules/esnext.iterator.map.js");
require("core-js/modules/esnext.iterator.reduce.js");
require("core-js/modules/web.dom-collections.iterator.js");
var _react = _interopRequireWildcard(require("react"));
var _stylesModule = _interopRequireDefault(require("./styles.module.css"));
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const Carousel = _ref => {
  let {
    posterItems,
    onUpArrow,
    onDownArrow,
    onFrontPosterChange,
    isStatic
  } = _ref;
  const postersN = posterItems.length;
  const currentPosterIndex = (0, _react.useRef)(0);
  const rotationAngle = (0, _react.useRef)(0);
  const animationFrameId = (0, _react.useRef)(null);
  const ringRef = _react.default.useRef(null);
  const stageRef = _react.default.useRef(null);
  const spinSpeed = (0, _react.useRef)(0);
  const isSlowing = (0, _react.useRef)(false);
  const isSpinning = (0, _react.useRef)(false);

  // Refs for dragging
  const isDragging = _react.default.useRef(false);
  const initialPosition = _react.default.useRef({
    x: 0,
    y: 0
  });
  const lastPosition = _react.default.useRef({
    x: 0,
    y: 0
  });
  const lastTime = _react.default.useRef(0);

  // Constants for adjusting sensitivity and friction
  const rotationSensitivity = -0.2; // Adjust this value to change drag sensitivity
  const friction = .97; // Adjust this value to change deceleration rate
  const speedMultiplier = 1; // Adjust this value to change spin speed after drag
  const velocityThreshold = 15; // Minimum velocity to trigger full spin
  const minSpinSpeed = .5; // Minimum spin speed after releasing drag
  const minDeltaTime = 16; // Minimum deltaTime to prevent unrealistic velocities
  const scrollMultiplier = 0.2; // Adjust this value to control scroll sensitivity

  const [dimensions, setDimensions] = (0, _react.useState)({
    stageWidth: 0,
    stageHeight: 0,
    posterWidth: 0,
    posterHeight: 0,
    ringRadius: 0
  });
  (0, _react.useEffect)(() => {
    if (!isStatic) {
      spinSpeed.current = .9;
      startAnimation();
    }
  }, [dimensions, isStatic]);
  (0, _react.useEffect)(() => {
    const frontFacingIndex = _getLargerNumberAndIdx(getTranslations().map(t => t.translateZ)).largerNumberIdx;
    onFrontPosterChange(posterItems[frontFacingIndex]);
  }, []);
  (0, _react.useEffect)(() => {
    if (onUpArrow) {
      onUp();
    }
  }, [onUpArrow]);
  (0, _react.useEffect)(() => {
    if (onDownArrow) {
      onDown();
    }
  }, [onDownArrow]);
  (0, _react.useEffect)(() => {
    const handleResize = () => {
      if (stageRef.current) {
        const stageWidth = stageRef.current.clientWidth;
        const stageHeight = stageRef.current.clientHeight;
        const posterWidth = calculatePosterWidth(stageWidth, stageHeight);
        const posterHeight = stageHeight * 0.2; // Adjust as needed
        const ringRadius = calculateRingRadius(stageWidth, stageHeight);
        setDimensions({
          stageWidth,
          stageHeight,
          posterWidth,
          posterHeight,
          ringRadius
        });
      }
    };

    // Initial calculation
    handleResize();

    // Recalculate on window resize
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  (0, _react.useEffect)(() => {
    /* Event listeners for wheel */
    const stage = stageRef.current;
    if (!stage) return;
    const handleWheel = event => {
      event.preventDefault();
      if (isSlowing.current) return;
      const normalizedDeltaY = normalizeWheelDelta(event, scrollMultiplier);

      // Apply the delta directly to rotation angle for smooth scrolling
      rotationAngle.current += normalizedDeltaY;
      applyRotation(currentPosterIndex.current);
    };
    !isStatic && stage.addEventListener('wheel', handleWheel, {
      passive: false
    });
    return () => {
      stage.removeEventListener('wheel', handleWheel);
    };
  }, [dimensions]);

  // Function to start the animation
  const startAnimation = () => {
    isSpinning.current = true;
    const rotate = () => {
      if (!ringRef.current) return;

      // Increment the rotation angle
      rotationAngle.current += spinSpeed.current;

      // Apply friction to spinSpeed
      spinSpeed.current *= friction; // Decrease spinSpeed over time

      // If spinSpeed is below a threshold, stop spinning
      // and bring to focus the front facing poster
      if (Math.abs(spinSpeed.current) < .5) {
        spinSpeed.current = 0;
        stopAnimation(true);
        return;
      }

      // Apply the rotation transformation to each poster
      applyRotation(currentPosterIndex.current);

      // Request the next frame
      animationFrameId.current = requestAnimationFrame(rotate);
    };

    // Start the animation
    animationFrameId.current = requestAnimationFrame(rotate);
  };

  // Function to stop the animation
  const stopAnimation = function stopAnimation() {
    let shouldFocus = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
    isSpinning.current = false;
    if (animationFrameId.current !== null) {
      cancelAnimationFrame(animationFrameId.current);
      animationFrameId.current = null;
    }
    shouldFocus && focusFrontPoster();
  };

  // Function to apply rotation to posters
  const applyRotation = function applyRotation() {
    let startingIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
    if (!ringRef.current) return;
    const ring = ringRef.current;
    const posters = ring.childNodes;

    // recalculate poster indices based on starting index
    const rotatedIndices = getRotatedIndices(startingIndex, postersN);
    for (let k = 0; k < rotatedIndices.length; k++) {
      const i = rotatedIndices[k];
      const poster = posters[i];
      const xRotation = 360 / postersN * k + rotationAngle.current;
      const opacity = calculatePosterOpacity(xRotation);
      poster.style.opacity = opacity;
      poster.style.transform = "rotateX(".concat(xRotation, "deg) translateZ(").concat(dimensions.ringRadius, "px)");
    }
    const frontFacingIndex = _getLargerNumberAndIdx(getTranslations().map(t => t.translateZ)).largerNumberIdx;
    onFrontPosterChange(posterItems[frontFacingIndex]);
  };

  /* Change the opacity of the posters based on their distance from the front */
  const calculatePosterOpacity = xRotation => {
    const transformedRotation = transfromTo360(xRotation);
    let opacity = 1;
    if (transformedRotation > 90 && transformedRotation < 270) {
      opacity = 0;
    } else if (transformedRotation > 0 && transformedRotation < 90) {
      opacity = 1 - transformedRotation / 90;
    } else if (transformedRotation > 270 && transformedRotation < 360) {
      opacity = 1 - (360 - transformedRotation) / 90;
    }
    return opacity.toString();
  };

  /* Event handlers for drag */
  const handleStart = event => {
    var _stageRef$current, _stageRef$current2;
    event.preventDefault();

    // Capture all subsequent pointer events for this pointer
    event.target.setPointerCapture(event.pointerId);
    isDragging.current = true;
    const {
      clientX,
      clientY
    } = event;
    initialPosition.current = {
      x: clientX,
      y: clientY
    };
    lastPosition.current = {
      x: clientX,
      y: clientY
    };
    lastTime.current = event.timeStamp;
    stopAnimation();

    // Add event listeners to document
    (_stageRef$current = stageRef.current) === null || _stageRef$current === void 0 || _stageRef$current.addEventListener('pointermove', handleMove);
    (_stageRef$current2 = stageRef.current) === null || _stageRef$current2 === void 0 || _stageRef$current2.addEventListener('pointerup', handleEnd);
  };
  const handleMove = event => {
    if (!isDragging.current) return;
    event.preventDefault();
    const {
      clientX,
      clientY
    } = event;
    const deltaY = clientY - lastPosition.current.y;
    rotationAngle.current += deltaY * rotationSensitivity;
    lastPosition.current = {
      x: clientX,
      y: clientY
    };
    lastTime.current = event.timeStamp;
    applyRotation(currentPosterIndex.current);
  };
  const handleEnd = event => {
    var _stageRef$current3, _stageRef$current4;
    if (!isDragging.current) return;
    event.preventDefault();

    // Release the pointer capture
    event.target.releasePointerCapture(event.pointerId);
    isDragging.current = false;
    const endTime = event.timeStamp;
    let deltaTime = endTime - lastTime.current;

    // Ensure deltaTime is not too small
    if (deltaTime < minDeltaTime) {
      deltaTime = minDeltaTime;
    }
    const totalDeltaY = lastPosition.current.y - initialPosition.current.y;
    let velocity = totalDeltaY / deltaTime;

    // If the velocity doesn't pass a threshold, don't fully spin
    if (Math.abs(velocity) < velocityThreshold) {
      velocity = minSpinSpeed;
    }
    spinSpeed.current = velocity * speedMultiplier;
    if (spinSpeed.current !== 0) {
      startAnimation();
    }

    // Remove event listeners
    (_stageRef$current3 = stageRef.current) === null || _stageRef$current3 === void 0 || _stageRef$current3.removeEventListener('pointermove', handleMove);
    (_stageRef$current4 = stageRef.current) === null || _stageRef$current4 === void 0 || _stageRef$current4.removeEventListener('pointerup', handleEnd);
  };
  /* End Event handlers for drag */

  const focusFrontPoster = function focusFrontPoster() {
    let idxOffset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
    let speed = arguments.length > 1 ? arguments[1] : undefined;
    // get rotation value for each of the posters
    const translations = getTranslations();
    const zTranslations = translations.map(t => t.translateZ);
    let frontFacingIndex = _getLargerNumberAndIdx(zTranslations).largerNumberIdx;
    frontFacingIndex = ((frontFacingIndex + idxOffset) % postersN + postersN) % postersN;
    currentPosterIndex.current = frontFacingIndex;
    onFrontPosterChange(posterItems[frontFacingIndex]);
    rotationAngle.current = 0;
    slowlyFocusFrontPoster(frontFacingIndex, speed);
  };
  const slowlyFocusFrontPoster = (frontPosterIdx, speed_) => {
    if (!ringRef.current) return;
    const ring = ringRef.current;
    const posters = ring.childNodes;
    const rotatedIndices = getRotatedIndices(frontPosterIdx, postersN);
    const targetRotation = 0;
    const rotations = getRotations();
    let frontPosterRotationTransformed = transfromTo360(rotations[frontPosterIdx].rotateX);
    let shouldDecrease;
    if (frontPosterRotationTransformed < 180 && frontPosterRotationTransformed > 0) {
      shouldDecrease = true;
    } else {
      shouldDecrease = false;
    }
    const speed = speed_ || 0.2; // Adjust as needed for smoothness
    let frontPosterRotation = rotations[frontPosterIdx].rotateX; // reset to the current scale
    isSlowing.current = true;
    const animate = () => {
      if (shouldDecrease && frontPosterRotationTransformed <= targetRotation || !shouldDecrease && frontPosterRotationTransformed >= 360 || !shouldDecrease && frontPosterRotationTransformed === 0 || shouldDecrease && frontPosterRotationTransformed === 0) {
        // Animation complete
        isSlowing.current = false;
        return;
      }
      frontPosterRotation += +(shouldDecrease ? -speed : speed).toFixed(3);
      frontPosterRotationTransformed += +(shouldDecrease ? -speed : speed).toFixed(3);
      for (let k = 0; k < rotatedIndices.length; k++) {
        const i = rotatedIndices[k];
        const poster = posters[i];
        let newRotation = shouldDecrease ? rotations[i].rotateX - speed : rotations[i].rotateX + speed;
        // newRotation = transfromTo360(newRotation);
        rotations[i].rotateX = newRotation;
        const opacity = calculatePosterOpacity(newRotation);
        poster.style.opacity = opacity;
        poster.style.transform = "rotateX(".concat(newRotation, "deg) translateZ(").concat(dimensions.ringRadius, "px)");
      }
      requestAnimationFrame(animate);
    };
    requestAnimationFrame(animate);
  };
  const getTranslations = () => {
    if (!ringRef.current) return [];
    const ring = ringRef.current;
    const posters = ring.childNodes;
    const translations = [];
    for (let i = 0; i < posters.length; i++) {
      const poster = posters[i];
      const computedStyle = window.getComputedStyle(poster);
      const transform = computedStyle.transform;
      const {
        translateX,
        translateY,
        translateZ
      } = _getTranslate(transform);
      translations.push({
        translateX,
        translateY,
        translateZ
      });
    }
    return translations;
  };
  const getRotations = () => {
    if (!ringRef.current) return [];
    const ring = ringRef.current;
    const posters = ring.childNodes;
    const rotations = [];
    for (let i = 0; i < posters.length; i++) {
      const poster = posters[i];
      const {
        rotateX
      } = _getRotate2(poster.style.transform);
      rotations.push({
        rotateX
      });
    }
    return rotations;
  };
  const onUp = () => {
    focusFrontPoster(+1, 1);
  };
  const onDown = () => {
    focusFrontPoster(-1, 1);
  };
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
    className: _stylesModule.default.stage,
    ref: stageRef,
    children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
      className: _stylesModule.default.rotate,
      children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
        onPointerDown: isStatic ? () => {} : handleStart,
        className: [_stylesModule.default.ring].join(' '),
        ref: ringRef,
        children: posterItems.map((poster, i) => {
          const xRotation = 360 / postersN * i;
          const opacity = calculatePosterOpacity(xRotation);
          const transform = "rotateX(".concat(xRotation, "deg) translateZ(").concat(dimensions.ringRadius, "px)");
          return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
            className: _stylesModule.default.poster,
            style: {
              transform,
              opacity,
              width: "".concat(dimensions.posterWidth, "px"),
              height: "".concat(dimensions.posterHeight, "px"),
              marginLeft: "-".concat(dimensions.posterWidth / 2, "px"),
              // Center horizontally
              marginTop: "-".concat(dimensions.posterHeight / 2, "px") // Center vertically
            },
            children: /*#__PURE__*/(0, _jsxRuntime.jsx)(poster.icon, {})
          }, i);
        })
      })
    })
  });
};
var _default = exports.default = Carousel;
const _getTranslate = function _getTranslate(matrix) {
  const regexResult = matrix.match(/matrix.*\((.+)\)/);
  if (!regexResult) return {
    translateZ: 0,
    translateY: 0,
    translateX: 0
  };
  const matrixValues = regexResult[1].split(', ');
  return {
    translateX: parseFloat(matrixValues[12]),
    translateY: parseFloat(matrixValues[13]),
    translateZ: parseFloat(matrixValues[14])
  };
};

// no need but cool function
const _getRotate = function _getRotate(matrix) {
  let rotateX = 0,
    rotateY = 0,
    rotateZ = 0;
  if (matrix !== 'none') {
    // do some magic
    var values = matrix.split('(')[1].split(')')[0].split(','),
      pi = Math.PI,
      sinB = parseFloat(values[8]),
      b = Math.round(Math.asin(sinB) * 180 / pi),
      cosB = Math.cos(b * pi / 180),
      matrixVal10 = parseFloat(values[9]),
      a = Math.round(Math.asin(-matrixVal10 / cosB) * 180 / pi),
      matrixVal1 = parseFloat(values[0]),
      c = Math.round(Math.acos(matrixVal1 / cosB) * 180 / pi);
    rotateX = a;
    rotateY = b;
    rotateZ = c;
  }
  return {
    rotateX: rotateX,
    rotateY: rotateY,
    rotateZ: rotateZ
  };
};
const _getRotate2 = function _getRotate2(transformValue) {
  const rotateRegex = /rotateX\((-?\d+(\.\d+)?)deg\)/;
  const rotateMatch = transformValue.match(rotateRegex);
  const rotateX = rotateMatch ? +parseInt(rotateMatch[1]).toFixed(3) : 0;
  return {
    rotateX
  };
};
function _getLargerNumberAndIdx(numbers) {
  const largerNumber = numbers.reduce((largest, current) => {
    return current > largest ? current : largest;
  }, numbers[0]);
  const largerNumberIdx = numbers.indexOf(largerNumber);
  return {
    largerNumber,
    largerNumberIdx
  };
}
function getRotatedIndices(startIdx, n) {
  const result = [];
  for (let i = 0; i < n; i++) {
    result.push((startIdx + i) % n);
  }
  return result;
}
function transfromTo360(deg) {
  return +Math.abs((deg + 360) % 360).toFixed(3);
}
const normalizeWheelDelta = (event, scrollMultiplier) => {
  let delta = event.deltaY;
  switch (event.deltaMode) {
    case WheelEvent.DOM_DELTA_PIXEL:
      // Delta in pixels, no change needed
      break;
    case WheelEvent.DOM_DELTA_LINE:
      // Approximate line height to pixels (depends on font size, usually ~16px)
      delta *= 16;
      break;
    case WheelEvent.DOM_DELTA_PAGE:
      // Approximate page height to pixels (assuming 800px)
      delta *= 800;
      break;
    default:
      break;
  }

  // Invert delta to match the direction of your rotation (optional)
  delta = -delta;

  // Apply a multiplier to adjust sensitivity
  return delta * scrollMultiplier;
};
const calculateRingRadius = (stageWidth, stageHeight) => {
  let res = stageWidth * 0.4;
  const ratio = stageWidth / stageHeight;
  console.log("\n=====================\n" + ratio.toString());
  console.log(stageWidth + "\n=====================\n");
  if (ratio > .5) {
    if (stageWidth < 50) {
      res = stageWidth * 1;
    } else if (stageWidth < 100) {
      res = stageWidth * .8;
    } else if (stageWidth < 200) {
      res = stageWidth * 0.6;
    } else if (stageWidth < 300) {
      res = stageWidth * .23;
    } else if (stageWidth < 400) {
      res = stageWidth * .23;
    } else if (stageWidth < 500) {
      res = stageWidth * 0.24;
    } else {
      res = stageWidth * 0.4;
    }
  } else if (ratio > .3) {
    if (stageWidth < 50) {
      res = stageWidth * 0.5;
    } else if (stageWidth < 100) {
      res = stageWidth * .44;
    } else if (stageWidth < 200) {
      res = stageWidth * 0.4;
    } else if (stageWidth < 300) {
      res = stageWidth * 0.41;
    } else if (stageWidth < 400) {
      res = stageWidth * 0.4;
    } else if (stageWidth < 500) {
      res = stageWidth * 0.35;
    } else {
      res = stageWidth * 0.4;
    }
  } else if (ratio > .1) {
    if (stageWidth < 50) {
      res = stageWidth * 1;
    } else if (stageWidth < 100) {
      res = stageWidth * .8;
    } else if (stageWidth < 200) {
      res = stageWidth * 0.55;
    } else if (stageWidth < 300) {
      res = stageWidth * 0.52;
    } else if (stageWidth < 400) {
      res = stageWidth * 0.43;
    } else if (stageWidth < 500) {
      res = stageWidth * 0.24;
    } else {
      res = stageWidth * 0.4;
    }
  } else if (ratio > 0.0) {
    if (stageWidth < 50) {
      res = stageWidth * 1;
    } else if (stageWidth < 100) {
      res = stageWidth * 1.1;
    } else if (stageWidth < 200) {
      res = stageWidth * 0.55;
    } else if (stageWidth < 300) {
      res = stageWidth * 0.52;
    } else if (stageWidth < 400) {
      res = stageWidth * 0.43;
    } else if (stageWidth < 500) {
      res = stageWidth * 0.24;
    } else {
      res = stageWidth * 0.4;
    }
  }
  return res;
};
const calculatePosterWidth = (stageWidth, stageHeight) => {
  const ratio = stageWidth / stageHeight;
  let res = stageWidth * 0;
  if (ratio > .5) {
    if (stageWidth < 50) {
      res = stageWidth * 0.5;
    } else if (stageWidth < 100) {
      res = stageWidth * 0.45;
    } else if (stageWidth < 200) {
      res = stageWidth * 0.35;
    } else if (stageWidth < 300) {
      res = stageWidth * 0.13;
    } else if (stageWidth < 400) {
      res = stageWidth * 0.13;
    } else if (stageWidth < 500) {
      res = stageWidth * 0.24;
    } else {
      res = stageWidth * 0.4;
    }
  } else if (ratio > .3) {
    if (stageWidth < 50) {
      res = stageWidth * 0.1;
    } else if (stageWidth < 100) {
      res = stageWidth * 0.25;
    } else if (stageWidth < 200) {
      res = stageWidth * 0.22;
    } else if (stageWidth < 300) {
      res = stageWidth * 0.23;
    } else if (stageWidth < 400) {
      res = stageWidth * 0.23;
    } else if (stageWidth < 500) {
      res = stageWidth * 0.2;
    } else {
      res = stageWidth * 0.4;
    }
  } else if (ratio > .1) {
    if (stageWidth < 50) {
      res = stageWidth * 0.5;
    } else if (stageWidth < 100) {
      res = stageWidth * 0.45;
    } else if (stageWidth < 200) {
      res = stageWidth * 0.29;
    } else if (stageWidth < 300) {
      res = stageWidth * 0.3;
    } else if (stageWidth < 400) {
      res = stageWidth * 0.25;
    } else if (stageWidth < 500) {
      res = stageWidth * 0.24;
    } else {
      res = stageWidth * 0.4;
    }
  } else if (ratio > 0.0) {
    if (stageWidth < 50) {
      res = stageWidth * 0.5;
    } else if (stageWidth < 100) {
      res = stageWidth * 0.65;
    } else if (stageWidth < 200) {
      res = stageWidth * 0.29;
    } else if (stageWidth < 300) {
      res = stageWidth * 0.3;
    } else if (stageWidth < 400) {
      res = stageWidth * 0.25;
    } else if (stageWidth < 500) {
      res = stageWidth * 0.24;
    } else {
      res = stageWidth * 0.4;
    }
  }
  return res;
};