"use strict";

function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
(function ($, w) {
  "use strict";

  $(w).on("elementor/frontend/init", function () {
    if (typeof gsap === "undefined") return;
    var HappyInfiniteMarquee = elementorModules.frontend.handlers.Base.extend({
      onInit: function onInit() {
        if (elementorFrontend.isEditMode()) {
          return;
        }
        elementorModules.frontend.handlers.Base.prototype.onInit.apply(this, arguments);
        this.build();
      },
      onElementChange: function onElementChange(prop) {
        if (prop === "ha_im_switcher" || prop === "ha_im_direction" || prop === "ha_im_speed" || prop === "ha_im_pause_hover" || prop === "ha_im_horizontal_direction" || prop === "ha_im_vertical_direction" || prop === "ha_im_mode" || prop === "ha_im_elips" || prop === "ha_im_elips_curve" || prop === "ha_im_elips_zoom" || prop === "ha_im_elips_rotate" || prop === "ha_im_elips_fade" || prop === "ha_im_elips_blur" || prop === "ha_im_enable_on_mobile") {
          this.destroyMarquee();
          this.build();
        }
      },
      destroyMarquee: function destroyMarquee() {
        if (this._rafId) {
          cancelAnimationFrame(this._rafId);
          this._rafId = null;
        }
        if (this.tween) {
          this.tween.kill();
          this.tween = null;
        }
        if (this._styleSheet && this._styleSheet.parentNode) {
          this._styleSheet.parentNode.removeChild(this._styleSheet);
          this._styleSheet = null;
        }
        if (this._elipsItems) {
          this._elipsItems.forEach(function (el) {
            el.style.transform = "";
            el.style.opacity = "";
            el.style.filter = "";
            el.style.zIndex = "";
            el.style.removeProperty("transition");
          });
          this._elipsItems = null;
        }
        if (this._track) {
          this._track.style.animation = "";
          this._track.style.transform = "";
          this._track.style.willChange = "";
        }
        this.$element.off(".haMarquee");
        this.$element.removeData("ha-init");
      },
      getResponsiveSetting: function getResponsiveSetting(settings, key, respectEmpty) {
        var deviceMode = elementorFrontend.getCurrentDeviceMode();
        if (deviceMode !== 'desktop') {
          var deviceKey = key + '_' + deviceMode;
          if (settings[deviceKey] !== undefined && (respectEmpty || settings[deviceKey] !== '')) {
            return settings[deviceKey];
          }
        }
        return settings[key];
      },
      build: function build() {
        if (elementorFrontend.isEditMode()) {
          return;
        }
        var settings = this.getElementSettings();
        if (settings.ha_im_switcher !== "yes") return;
        if ('mobile' === elementorFrontend.getCurrentDeviceMode() && settings.ha_im_enable_on_mobile !== 'yes') {
          return;
        }
        var pauseOnHover = settings.ha_im_pause_hover === "yes";
        var $wrapper = this.$element;
        if ($wrapper.data("ha-init")) return;
        $wrapper.data("ha-init", true);

        // Detect inner wrapper
        var $inner = $wrapper.children(".e-con-inner");
        var $source;
        if ($inner.length) {
          $source = $inner.children();
        } else {
          $inner = $wrapper;
          $source = $wrapper.children().not(".ha-marquee-content");
        }
        if (!$source.length) return;

        // Get mode and direction settings
        var mode = this.getResponsiveSetting(settings, "ha_im_mode") || "horizontal";
        var isVertical = mode === "vertical";

        // Toggle class
        $wrapper.toggleClass("is-vertical", isVertical);

        // Capture the original rendered size of every item BEFORE moving it.
        var originals = [];
        var fixedSizes = [];
        $source.each(function () {
          var rect = this.getBoundingClientRect();
          fixedSizes.push(isVertical ? rect.height : rect.width);
          originals.push(this);
        });

        // Container (viewport) size, captured before the track
        // replaces the content.
        var containerSize = isVertical ? $inner[0].clientHeight : $inner[0].clientWidth;

        // Create track
        var $track = $('<div class="ha-marquee-content"></div>');

        // Move items into track and lock their original size
        originals.forEach(function (el, i) {
          var $el = $(el).addClass("ha-marquee-item");
          if (fixedSizes[i] > 0) {
            $el.css("flex", "0 0 " + fixedSizes[i] + "px");
          }
          $track.append(el);
        });

        // Append track INSIDE inner wrapper
        $inner.empty().append($track);

        // Force reflow to ensure layout is complete
        $track[0].offsetHeight;

        // Measure one repeating set (original items + trailing gap)
        var probe = originals[0].cloneNode(true);
        $track[0].appendChild(probe);
        var firstRect = originals[0].getBoundingClientRect();
        var probeRect = probe.getBoundingClientRect();
        var setSize;
        if (isVertical) {
          setSize = Math.abs(probeRect.top - firstRect.top);
        } else {
          setSize = Math.abs(probeRect.left - firstRect.left);
        }
        $track[0].removeChild(probe);
        setSize = Math.round(setSize);
        if (!setSize || setSize < 1) setSize = 1;

        // Determine how many sets are needed for a seamless loop
        var setsNeeded = Math.max(1, Math.ceil(containerSize / setSize));

        // Clone enough full sets so the track holds
        // (setsNeeded * 2) copies. To makes the loop visually seamless.
        var totalCopies = setsNeeded * 2;
        for (var s = 1; s < totalCopies; s++) {
          originals.forEach(function (el) {
            $track.append(el.cloneNode(true));
          });
        }

        // Distance the track travels during one full loop
        var loopSize = setSize * setsNeeded;
        var speed = this.getResponsiveSetting(settings, "ha_im_speed") || 120;

        // Determine animation direction
        var from = 0;
        var to = 0;
        var direction;
        if (isVertical) {
          direction = this.getResponsiveSetting(settings, "ha_im_vertical_direction") || "top";
          if (direction === "top") {
            from = 0;
            to = -loopSize;
          } else {
            from = -loopSize;
            to = 0;
          }
        } else {
          direction = this.getResponsiveSetting(settings, "ha_im_horizontal_direction") || "left";
          if (direction === "left") {
            from = 0;
            to = -loopSize;
          } else {
            from = -loopSize;
            to = 0;
          }
        }

        // Handle Hover functionality
        $wrapper.off(".haMarquee");

        // Store track reference for cleanup (shared by both engines)
        this._track = $track[0];

        // Elips (arc) effect — replaces the CSS keyframe animation with a per-frame JS loop
        // Only available in horizontal mode (matches the demo spec).
        var elipsEnabled = settings.ha_im_elips === "yes" && !isVertical;
        if (elipsEnabled) {
          this._startElips({
            $track: $track,
            $inner: $inner,
            direction: direction,
            loopSize: loopSize,
            setSize: setSize,
            speed: speed,
            pauseOnHover: pauseOnHover,
            settings: settings
          });
        } else {
          this._startCssAnimation({
            isVertical: isVertical,
            from: from,
            to: to,
            loopSize: loopSize,
            speed: speed,
            pauseOnHover: pauseOnHover,
            $track: $track
          });
        }
      },
      /**
       * Default engine: CSS @keyframes infinite loop.
       * Used whenever the Elips effect is disabled (and for vertical mode).
       */
      _startCssAnimation: function _startCssAnimation(opts) {
        var _this = this;
        var isVertical = opts.isVertical;
        var from = opts.from;
        var to = opts.to;
        var loopSize = opts.loopSize;
        var speed = opts.speed;
        var pauseOnHover = opts.pauseOnHover;
        var $track = opts.$track;
        var $wrapper = this.$element;

        // Use CSS animation for smoother infinite loop
        var animationName = "ha-marquee-".concat(Date.now());
        var transformFrom = isVertical ? "translate3d(0, ".concat(from, "px, 0)") : "translate3d(".concat(from, "px, 0, 0)");
        var transformTo = isVertical ? "translate3d(0, ".concat(to, "px, 0)") : "translate3d(".concat(to, "px, 0, 0)");
        var keyframes = "\n\t\t\t\t\t\t@keyframes ".concat(animationName, " {\n\t\t\t\t\t\t\tfrom {\n\t\t\t\t\t\t\t\ttransform: ").concat(transformFrom, ";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tto {\n\t\t\t\t\t\t\t\ttransform: ").concat(transformTo, ";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t");

        // Inject keyframes
        var styleSheet = document.createElement("style");
        styleSheet.textContent = keyframes;
        document.head.appendChild(styleSheet);

        // Apply animation to track
        var duration = loopSize / speed;
        $track[0].style.animation = "".concat(animationName, " ").concat(duration, "s linear infinite");
        $track[0].style.willChange = "transform";

        // Store references for cleanup
        this._styleSheet = styleSheet;
        this._animationName = animationName;

        // Hover handlers
        if (pauseOnHover) {
          $wrapper.on("mouseenter.haMarquee", function () {
            $track[0].style.animationPlayState = "paused";
          });
          $wrapper.on("mouseleave.haMarquee", function () {
            $track[0].style.animationPlayState = "running";
          });
        }

        // Create dummy tween object for compatibility
        this.tween = {
          pause: function pause() {
            $track[0].style.animationPlayState = "paused";
          },
          resume: function resume() {
            $track[0].style.animationPlayState = "running";
          },
          kill: function kill() {
            $track[0].style.animation = "";
            if (_this._styleSheet && _this._styleSheet.parentNode) {
              _this._styleSheet.parentNode.removeChild(_this._styleSheet);
            }
          }
        };
      },
      /**
       * Elips (arc) engine: a requestAnimationFrame loop that drives
       * the horizontal scroll AND applies per-item transforms based on
       * each item's distance from the container center:
       */
      _startElips: function _startElips(opts) {
        var _this2 = this;
        var $track = opts.$track;
        var $inner = opts.$inner;
        var direction = opts.direction;
        var loopSize = opts.loopSize;
        var setSize = opts.setSize || loopSize;
        var speed = opts.speed;
        var pauseOnHover = opts.pauseOnHover;
        var settings = opts.settings;
        var $wrapper = this.$element;

        // Elips tunables (all user-controlled)
        var curveRaw = this.getResponsiveSetting(settings, "ha_im_elips_curve");
        var curveDepth = curveRaw ? _typeof(curveRaw) === "object" ? curveRaw.size != null ? curveRaw.size : 130 : curveRaw : 130;
        var zoomEnabled = this.getResponsiveSetting(settings, "ha_im_elips_zoom", true) === "yes";
        var rotateEnabled = this.getResponsiveSetting(settings, "ha_im_elips_rotate", true) === "yes";
        var fadeEnabled = this.getResponsiveSetting(settings, "ha_im_elips_fade", true) === "yes";
        var blurEnabled = this.getResponsiveSetting(settings, "ha_im_elips_blur", true) === "yes";
        var minScale = 0.5;
        var maxScale = 1.0;
        var maxRotate = 14;

        // All track children (originals + clones) get per-frame transforms.
        var trackEl = $track[0];
        var items = Array.prototype.slice.call(trackEl.children);
        this._elipsItems = items;

        // Force-disable CSS transitions on every item. The marquee
        // items are typically Elementor widgets that carry their
        // own transitions (hover/theme effects).
        items.forEach(function (el) {
          el.style.setProperty("transition", "none", "important");
        });

        // Precompute each item's horizontal center relative to the
        // track's left edge ONCE, before any per-frame transforms are applied.
        var initTrackRect = trackEl.getBoundingClientRect();
        var itemCenters = items.map(function (el) {
          var r = el.getBoundingClientRect();
          return r.left + r.width / 2 - initTrackRect.left;
        });

        // Wrap distance = setSize (one repeating set), NOT loopSize.
        var scrollX = direction === "left" ? 0 : -setSize;
        var paused = false;
        var lastTime = performance.now();
        var rafId = null;
        var containerEl = $inner[0];
        var _render = function render(now) {
          // Clamp dt so a backgrounded tab does not jump the track.
          var dt = Math.min(0.05, (now - lastTime) / 1000);
          lastTime = now;
          if (!paused) {
            var delta = speed * dt;
            if (direction === "left") {
              scrollX -= delta;
              if (scrollX <= -setSize) scrollX += setSize;
            } else {
              scrollX += delta;
              if (scrollX >= 0) scrollX -= setSize;
            }
          }
          trackEl.style.transform = "translate3d(".concat(scrollX, "px, 0, 0)");

          // Read container + track rects ONCE per frame for all items, so the per-item transforms are consistent.
          var cRect = containerEl.getBoundingClientRect();
          var tRect = trackEl.getBoundingClientRect();
          var centerX = cRect.left + cRect.width / 2;
          var halfRange = cRect.width / 2;
          var trackLeft = tRect.left;
          for (var i = 0; i < items.length; i++) {
            var el = items[i];
            var itemCenterX = trackLeft + itemCenters[i];

            // UNCLAMPED normalized distance from center
            var norm = halfRange > 0 ? (itemCenterX - centerX) / halfRange : 0;
            // CLAMPED version kept for scale/opacity/blur calculations, so items outside the viewport don't get crazy transforms.
            var clampDist = Math.max(-1, Math.min(1, norm));
            var absDist = Math.abs(clampDist);

            // Quadratic drop using UNCLAMPED norm — items farther from center are lower on the curve.
            var yOffset = norm * norm * curveDepth;
            var scale = 1;
            if (zoomEnabled) {
              scale = maxScale - absDist * (maxScale - minScale);
            }
            var rotate = 0;
            if (rotateEnabled) {
              // Rotation follows the TANGENT of the parabolic curve, so the slope is computed from the UNCLAMPED norm.
              var slope = halfRange > 0 ? 2 * curveDepth * norm / halfRange : 0;
              rotate = Math.atan(slope) * 180 / Math.PI;
            }
            var opacity = 1;
            if (fadeEnabled) {
              opacity = 1 - absDist * 0.35;
            }
            var filterStr = "";
            if (blurEnabled && absDist > 0.7) {
              filterStr = "blur(".concat((absDist - 0.7) * 4, "px)");
            }

            // translate3d (Z=0) keeps the item on its own GPU layer, which is important for smooth per-frame transforms.
            el.style.transform = "translate3d(0, ".concat(yOffset, "px, 0) scale(").concat(scale, ") rotate(").concat(rotate, "deg)");
            if (fadeEnabled) {
              el.style.opacity = opacity;
            }
            if (blurEnabled) {
              el.style.filter = filterStr;
            }
            el.style.zIndex = String(Math.round((1 - absDist) * 100));
          }
          rafId = requestAnimationFrame(_render);
          _this2._rafId = rafId;
        };

        // Render the first frame synchronously so items receive their initial transforms
        _render(performance.now());

        // Hover handlers
        if (pauseOnHover) {
          $wrapper.on("mouseenter.haMarquee", function () {
            paused = true;
          });
          $wrapper.on("mouseleave.haMarquee", function () {
            paused = false;
            lastTime = performance.now();
          });
        }

        // Dummy tween object for API compatibility with the CSS path
        this.tween = {
          pause: function pause() {
            paused = true;
          },
          resume: function resume() {
            paused = false;
            lastTime = performance.now();
          },
          kill: function kill() {
            if (rafId) {
              cancelAnimationFrame(rafId);
              rafId = null;
            }
            _this2._rafId = null;
            trackEl.style.transform = "";
            items.forEach(function (el) {
              el.style.transform = "";
              el.style.opacity = "";
              el.style.filter = "";
              el.style.zIndex = "";
              el.style.removeProperty("transition");
            });
          }
        };
      }
    });

    // HANDLER REGISTRATION
    elementorFrontend.hooks.addAction("frontend/element_ready/global", function ($scope) {
      elementorFrontend.elementsHandler.addHandler(HappyInfiniteMarquee, {
        $element: $scope
      });
    });
  });
})(jQuery, window);