(function ($) {
  "use strict";

  var SLOT_ORDER_NEXT = ["left", "right-top", "right-bottom"];
  var SLOT_ORDER_PREV = ["right-bottom", "right-top", "left"];
  var PLACEHOLDER_TEXT = "Brak obrazu";
  var DATA_PREFIX = "ts";

  function parseBoolean(value, fallback) {
    if (value === undefined || value === null || value === "") {
      return fallback;
    }
    if (typeof value === "boolean") {
      return value;
    }
    return String(value).toLowerCase() === "true";
  }

  function parseNumber(value, fallback) {
    var num = Number(value);
    return Number.isFinite(num) ? num : fallback;
  }

  function supportsReducedMotion(setting) {
    if (setting === "on") {
      return true;
    }
    if (setting === "off") {
      return false;
    }
    return window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  }

  function nextIndex(current, total, loop) {
    if (current + 1 >= total) {
      return loop ? 0 : current;
    }
    return current + 1;
  }

  function prevIndex(current, total, loop) {
    if (current - 1 < 0) {
      return loop ? total - 1 : current;
    }
    return current - 1;
  }

  function extractSlideData($scene) {
    var bySlot = {};
    SLOT_ORDER_NEXT.forEach(function (slot) {
      var $img = $scene.find('.ts-panel[data-slot="' + slot + '"] img').first();
      bySlot[slot] = {
        src: $img.attr("src") || "",
        alt: $img.attr("alt") || ""
      };
    });

    var $title = $scene.find(".ts-title").first();
    var $description = $scene.find(".ts-description").first();
    var $cta = $scene.find(".ts-cta").first();

    return {
      slots: bySlot,
      title: $title.length ? $title.text() : "",
      description: $description.length ? $description.text() : "",
      ctaText: $cta.length ? $cta.text() : "",
      ctaHref: $cta.length ? ($cta.attr("href") || "#") : "",
      colors: {
        title: $scene.data("titleColor") || "",
        description: $scene.data("descriptionColor") || "",
        ctaBg: $scene.data("ctaBg") || "",
        ctaColor: $scene.data("ctaColor") || ""
      }
    };
  }

  function createFrame(media, slide, isLazy) {
    var $item = $('<div class="ts-frame"></div>');
    if (!media || !media.src) {
      $item.append('<div class="ts-placeholder" aria-hidden="true">' + PLACEHOLDER_TEXT + "</div>");
    } else {
      var $img = $("<img>", {
        src: media.src,
        alt: media.alt || "",
        decoding: "async",
        loading: isLazy ? "lazy" : "eager"
      });
      $img.on("error", function () {
        $(this).remove();
        if ($item.find(".ts-placeholder").length === 0) {
          $item.append('<div class="ts-placeholder" aria-hidden="true">' + PLACEHOLDER_TEXT + "</div>");
        }
      });
      $item.append($img);
    }

    var titleColor = slide && slide.colors && slide.colors.title ? slide.colors.title : "";
    var descriptionColor = slide && slide.colors && slide.colors.description ? slide.colors.description : "";
    var ctaBg = slide && slide.colors && slide.colors.ctaBg ? slide.colors.ctaBg : "";
    var ctaColor = slide && slide.colors && slide.colors.ctaColor ? slide.colors.ctaColor : "";
    var style = "";
    if (titleColor) {
      style += "--ts-frame-title-color:" + titleColor + ";";
    }
    if (descriptionColor) {
      style += "--ts-frame-description-color:" + descriptionColor + ";";
    }
    if (ctaBg) {
      style += "--ts-frame-cta-bg:" + ctaBg + ";";
    }
    if (ctaColor) {
      style += "--ts-frame-cta-color:" + ctaColor + ";";
    }

    var $content = $('<div class="ts-frame-content"' + (style ? ' style="' + style + '"' : "") + "></div>");
    var hasContent = false;
    if (slide && slide.title) {
      $content.append($('<h3 class="ts-frame-title"></h3>').text(slide.title));
      hasContent = true;
    }
    if (slide && slide.description) {
      $content.append($('<p class="ts-frame-description"></p>').text(slide.description));
      hasContent = true;
    }
    if (slide && slide.ctaText) {
      $content.append(
        $('<a class="ts-frame-cta"></a>')
          .attr("href", slide.ctaHref || "#")
          .text(slide.ctaText)
      );
      hasContent = true;
    }
    if (hasContent) {
      $item.append($content);
    }

    return $item;
  }

  function TripleSlider($root, options) {
    this.$root = $root;
    this.options = options;
    this.$sourceScenes = this.$root.find(".ts-scene");
    this.$prev = this.$root.find(".ts-prev");
    this.$next = this.$root.find(".ts-next");
    this.$autoplayToggle = this.$root.find(".ts-autoplay-toggle");
    this.current = this.$sourceScenes.index(this.$sourceScenes.filter(".is-active").first());
    this.current = this.current < 0 ? 0 : this.current;
    this.visualIndex = this.current + 1;
    this.slides = [];
    this.tracks = {};
    this.lanes = {};
    this.laneFrameIndex = {};
    this.busy = false;
    this.autoplayTimer = null;
    this.interactionTimer = null;
    this.transitionTimers = [];
    this.pausedByUser = false;
    this.reducedMotion = supportsReducedMotion(options.reducedMotion);

    this.init();
  }

  TripleSlider.prototype.init = function () {
    var self = this;
    if (!this.$sourceScenes.length) {
      return;
    }

    this.$root.attr("role", "region");
    this.$root.attr("aria-roledescription", "carousel");
    this.$root.attr("aria-live", "polite");
    this.$root.attr("tabindex", "0");

    this.applyRatios();
    this.collectSlides();
    this.buildFrameCarousels();
    this.bindEvents();
    this.preloadNeighborSlides();

    if (this.options.autoplay) {
      this.scheduleAutoplay();
    }

    if (window.matchMedia) {
      var media = window.matchMedia("(prefers-reduced-motion: reduce)");
      media.addEventListener("change", function () {
        self.reducedMotion = supportsReducedMotion(self.options.reducedMotion);
      });
    }
  };

  TripleSlider.prototype.applyRatios = function () {
    this.$root[0].style.setProperty("--ts-ratio-desktop", this.options.ratioDesktop);
    this.$root[0].style.setProperty("--ts-ratio-tablet", this.options.ratioTablet);
    this.$root[0].style.setProperty("--ts-ratio-mobile", this.options.ratioMobile);
  };

  TripleSlider.prototype.collectSlides = function () {
    var self = this;
    this.$sourceScenes.each(function () {
      self.slides.push(extractSlideData($(this)));
    });
  };

  TripleSlider.prototype.buildFrameCarousels = function () {
    var self = this;
    var total = this.slides.length;
    var $scenesHost = this.$root.find(".ts-scenes").first();
    var $lanes = $('<div class="ts-lanes"></div>');

    this.$sourceScenes.remove();

    SLOT_ORDER_NEXT.forEach(function (slot) {
      var $lane = $('<div class="ts-panel ts-lane" data-slot="' + slot + '"></div>');
      var $track = $('<div class="ts-track"></div>');
      var first = self.slides[0].slots[slot];
      var last = self.slides[total - 1].slots[slot];

      $track.append(createFrame(last, self.slides[total - 1], true));
      self.slides.forEach(function (slide, idx) {
        $track.append(createFrame(slide.slots[slot], slide, idx !== self.current));
      });
      $track.append(createFrame(first, self.slides[0], true));

      $lane.append($track);
      $lanes.append($lane);
      self.tracks[slot] = $track;
      self.lanes[slot] = $lane;
      self.laneFrameIndex[slot] = self.visualIndex;
    });

    $scenesHost.empty().append($lanes);
    this.setAllTracksPosition(this.visualIndex, true);
    this.updateAllCurrentFrames(this.visualIndex);
    this.setAllLaneContentVisible(true);
  };

  TripleSlider.prototype.setTrackPosition = function (slot, visualIndex, immediate) {
    var $track = this.tracks[slot];
    if (!$track || !$track.length) {
      return;
    }
    var dur = this.reducedMotion ? 1 : this.options.duration;
    $track.css({
      transition: immediate ? "none" : "transform " + dur + "ms " + this.options.easing,
      transform: "translate3d(" + (-visualIndex * 100) + "%,0,0)"
    });
  };

  TripleSlider.prototype.setAllTracksPosition = function (visualIndex, immediate) {
    var self = this;
    SLOT_ORDER_NEXT.forEach(function (slot) {
      self.setTrackPosition(slot, visualIndex, immediate);
    });
  };

  TripleSlider.prototype.updateCurrentFrameForSlot = function (slot, visualIndex, mirrorIndex) {
    var $track = this.tracks[slot];
    if (!$track || !$track.length) {
      return;
    }
    $track.find(".ts-frame").removeClass("is-current");
    $track.find(".ts-frame").eq(visualIndex).addClass("is-current");
    if (typeof mirrorIndex === "number") {
      $track.find(".ts-frame").eq(mirrorIndex).addClass("is-current");
      this.laneFrameIndex[slot] = mirrorIndex;
      return;
    }
    this.laneFrameIndex[slot] = visualIndex;
  };

  TripleSlider.prototype.updateAllCurrentFrames = function (visualIndex) {
    var self = this;
    SLOT_ORDER_NEXT.forEach(function (slot) {
      self.updateCurrentFrameForSlot(slot, visualIndex);
    });
  };

  TripleSlider.prototype.rebaseCurrentFrames = function (realIndex) {
    var self = this;
    this.$root.addClass("is-rebasing");
    SLOT_ORDER_NEXT.forEach(function (slot) {
      var $track = self.tracks[slot];
      if (!$track || !$track.length) {
        return;
      }
      $track.find(".ts-frame").removeClass("is-current");
      $track.find(".ts-frame").eq(realIndex).addClass("is-current");
      self.laneFrameIndex[slot] = realIndex;
    });
    window.setTimeout(function () {
      self.$root.removeClass("is-rebasing");
    }, 0);
  };

  TripleSlider.prototype.setAllLaneContentVisible = function (visible) {
    var self = this;
    SLOT_ORDER_NEXT.forEach(function (slot) {
      var $lane = self.lanes[slot];
      if (!$lane || !$lane.length) {
        return;
      }
      if (visible) {
        $lane.addClass("is-content-visible");
      } else {
        $lane.removeClass("is-content-visible");
      }
    });
  };

  TripleSlider.prototype.showLaneContent = function (slot) {
    var $lane = this.lanes[slot];
    if (!$lane || !$lane.length) {
      return;
    }
    $lane.addClass("is-content-visible");
  };

  TripleSlider.prototype.hideLaneContent = function (slot) {
    var $lane = this.lanes[slot];
    if (!$lane || !$lane.length) {
      return;
    }
    $lane.removeClass("is-content-visible");
  };

  TripleSlider.prototype.preloadNeighborSlides = function () {
    var next = nextIndex(this.current, this.slides.length, true);
    var prev = prevIndex(this.current, this.slides.length, true);
    [this.slides[next], this.slides[prev]].forEach(function (slide) {
      SLOT_ORDER_NEXT.forEach(function (slot) {
        if (slide && slide.slots[slot] && slide.slots[slot].src) {
          var img = new Image();
          img.src = slide.slots[slot].src;
        }
      });
    });
  };

  TripleSlider.prototype.bindEvents = function () {
    var self = this;
    var startX = 0;
    var startY = 0;
    var dragging = false;

    this.$next.on("click", function () {
      self.userInteracted();
      self.go("next");
    });

    this.$prev.on("click", function () {
      self.userInteracted();
      self.go("prev");
    });

    this.$autoplayToggle.on("click", function () {
      self.pausedByUser = !self.pausedByUser;
      self.$autoplayToggle.attr("aria-pressed", String(self.pausedByUser));
      self.$autoplayToggle.text(self.pausedByUser ? "Wznów" : "Pauza");
      self.$autoplayToggle.attr("aria-label", self.pausedByUser ? "Wznów autoplay" : "Wstrzymaj autoplay");
      if (self.pausedByUser) {
        self.stopAutoplay();
      } else {
        self.scheduleAutoplay();
      }
    });

    this.$root.on("keydown", function (event) {
      if (event.key === "ArrowRight") {
        event.preventDefault();
        self.userInteracted();
        self.go("next");
      } else if (event.key === "ArrowLeft") {
        event.preventDefault();
        self.userInteracted();
        self.go("prev");
      }
    });

    this.$root.on("pointerdown", function (event) {
      dragging = true;
      startX = event.clientX;
      startY = event.clientY;
    });

    this.$root.on("pointerup", function (event) {
      if (!dragging) {
        return;
      }
      dragging = false;
      var dx = event.clientX - startX;
      var dy = event.clientY - startY;
      var absX = Math.abs(dx);
      var absY = Math.abs(dy);
      if (absX < self.options.swipeThreshold || absX <= absY) {
        return;
      }
      self.userInteracted();
      self.go(dx < 0 ? "next" : "prev");
    });

    this.$root.on("pointercancel pointerleave", function () {
      dragging = false;
    });
  };

  TripleSlider.prototype.userInteracted = function () {
    if (!this.options.autoplay) {
      return;
    }
    this.stopAutoplay();
    if (this.pausedByUser) {
      return;
    }
    window.clearTimeout(this.interactionTimer);
    this.interactionTimer = window.setTimeout(
      this.scheduleAutoplay.bind(this),
      this.options.autoplayResumeDelay
    );
  };

  TripleSlider.prototype.getTargetIndex = function (direction) {
    if (direction === "next") {
      return nextIndex(this.current, this.slides.length, this.options.loop);
    }
    return prevIndex(this.current, this.slides.length, this.options.loop);
  };

  TripleSlider.prototype.scheduleAutoplay = function () {
    var self = this;
    if (!this.options.autoplay || this.pausedByUser) {
      return;
    }
    this.stopAutoplay();
    this.autoplayTimer = window.setTimeout(function () {
      self.go("next");
    }, this.options.autoplayDelay);
  };

  TripleSlider.prototype.stopAutoplay = function () {
    window.clearTimeout(this.autoplayTimer);
    this.autoplayTimer = null;
  };

  TripleSlider.prototype.queueTransitionTimer = function (fn, delay) {
    var self = this;
    var id = window.setTimeout(function () {
      self.transitionTimers = self.transitionTimers.filter(function (timerId) {
        return timerId !== id;
      });
      fn();
    }, delay);
    this.transitionTimers.push(id);
    return id;
  };

  TripleSlider.prototype.clearTransitionTimers = function () {
    this.transitionTimers.forEach(function (id) {
      window.clearTimeout(id);
    });
    this.transitionTimers = [];
  };

  TripleSlider.prototype.startLaneStep = function (slot, direction) {
    var delta = direction === "next" ? 1 : -1;
    var targetVisualIndex = this.visualIndex + delta;
    var mirrorIndex = null;
    if (targetVisualIndex > this.slides.length) {
      mirrorIndex = 1;
    } else if (targetVisualIndex < 1) {
      mirrorIndex = this.slides.length;
    }
    this.setTrackPosition(slot, targetVisualIndex, false);
    var self = this;
    var dur = this.reducedMotion ? 1 : this.options.duration;
    this.queueTransitionTimer(function () {
      self.updateCurrentFrameForSlot(slot, targetVisualIndex, mirrorIndex);
    }, dur);
  };

  TripleSlider.prototype.normalizeTrackLoopPosition = function () {
    if (this.visualIndex === this.slides.length + 1) {
      this.visualIndex = 1;
      this.setAllTracksPosition(this.visualIndex, true);
      this.updateAllCurrentFrames(this.visualIndex);
    } else if (this.visualIndex === 0) {
      this.visualIndex = this.slides.length;
      this.setAllTracksPosition(this.visualIndex, true);
      this.updateAllCurrentFrames(this.visualIndex);
    }
  };

  TripleSlider.prototype.go = function (direction) {
    var self = this;
    if (this.busy || this.slides.length < 2) {
      return;
    }

    var target = this.getTargetIndex(direction);
    if (target === this.current) {
      return;
    }

    var order = direction === "next" ? SLOT_ORDER_NEXT : SLOT_ORDER_PREV;
    var delayStep = this.reducedMotion ? 0 : this.options.panelDelay;
    var hideLead = this.reducedMotion ? 0 : this.options.contentHideLead;
    var delta = direction === "next" ? 1 : -1;
    var rawTargetVisualIndex = this.visualIndex + delta;
    var totalSlideBase = this.reducedMotion
      ? 10
      : (order.length - 1) * delayStep + hideLead + this.options.duration;
    var totalSlideTime = totalSlideBase + this.options.contentStagger + 20;

    this.busy = true;
    this.$root.addClass("is-busy");
    this.stopAutoplay();
    this.clearTransitionTimers();

    order.forEach(function (slot, idx) {
      self.queueTransitionTimer(function () {
        self.hideLaneContent(slot);
      }, idx * delayStep);

      self.queueTransitionTimer(function () {
        self.startLaneStep(slot, direction);
      }, idx * delayStep + hideLead);

      self.queueTransitionTimer(function () {
        self.showLaneContent(slot);
      }, idx * delayStep + hideLead + self.options.duration + self.options.contentStagger);
    });

    this.queueTransitionTimer(function () {
      self.visualIndex += direction === "next" ? 1 : -1;
      if (self.visualIndex === self.slides.length + 1) {
        self.visualIndex = 1;
        self.setAllTracksPosition(self.visualIndex, true);
      } else if (self.visualIndex === 0) {
        self.visualIndex = self.slides.length;
        self.setAllTracksPosition(self.visualIndex, true);
      } else {
        self.normalizeTrackLoopPosition();
      }
      self.current = target;
      self.preloadNeighborSlides();
      self.busy = false;
      self.$root.removeClass("is-busy");
      self.scheduleAutoplay();
    }, totalSlideTime);
  };

  function buildOptions($el, userOptions) {
    var data = $el.data();

    return $.extend({}, {
      ratioDesktop: data.ratioDesktop || "16/9",
      ratioTablet: data.ratioTablet || "4/3",
      ratioMobile: data.ratioMobile || "1/1",
      duration: parseNumber(data.duration, 900),
      panelDelay: parseNumber(data.panelDelay, 1000),
      contentStagger: parseNumber(data.contentStagger, 220),
      contentHideLead: parseNumber(data.contentHideLead, 180),
      easing: data.easing || "cubic-bezier(0.22, 1, 0.36, 1)",
      autoplay: parseBoolean(data.autoplay, true),
      autoplayDelay: parseNumber(data.autoplayDelay, 3000),
      autoplayResumeDelay: parseNumber(data.autoplayResumeDelay, 6000),
      loop: parseBoolean(data.loop, true),
      swipeThreshold: parseNumber(data.swipeThreshold, 50),
      reducedMotion: data.reducedMotion || "auto"
    }, userOptions || {});
  }

  $.fn.tripleSlider = function (options) {
    return this.each(function () {
      var $el = $(this);
      var instance = $el.data(DATA_PREFIX);
      if (instance) {
        return;
      }
      $el.data(DATA_PREFIX, new TripleSlider($el, buildOptions($el, options)));
    });
  };
})(jQuery);
