(function ($) {
  "use strict";

  /**
   * Card Oracle JS code for the public pages
   */

  $(document).ready(function () {
    var cardID;
    var shuffleUtils =
      window.CardOracleShuffle ||
      (function () {
        function fallbackCreateState(totalPositions) {
          var parsed = parseInt(totalPositions, 10);
          var positions = isNaN(parsed) ? 0 : parsed;
          return {
            positions: positions > 0 ? positions : 0,
            count: 0,
            clicked: [],
            reverse: [],
          };
        }

        function fallbackResult(state, wasRecorded, hideShuffle) {
          var isComplete =
            state.positions > 0 && state.count >= state.positions;
          return {
            wasRecorded: wasRecorded,
            hideShuffleButton: hideShuffle,
            isComplete: isComplete,
            clicked: state.clicked.slice(),
            reverse: state.reverse.slice(),
          };
        }

        function fallbackRecord(state, cardId, options) {
          if (
            !state ||
            cardId === undefined ||
            cardId === null ||
            cardId === ""
          ) {
            return fallbackResult(
              state || fallbackCreateState(0),
              false,
              false,
            );
          }

          if (
            state.clicked.indexOf(cardId) !== -1 ||
            (state.positions > 0 && state.count >= state.positions)
          ) {
            return fallbackResult(state, false, false);
          }

          state.clicked.push(cardId);
          if (options && options.reversed) {
            state.reverse.push(cardId);
          }

          state.count += 1;
          var hideShuffle = state.count === 1;
          return fallbackResult(state, true, hideShuffle);
        }

        return {
          createState: fallbackCreateState,
          recordSelection: fallbackRecord,
          shuffleIndices: function (length) {
            return Array.from({ length: length || 0 }, function (_, index) {
              return index;
            });
          },
          reorderByIndices: function (elements) {
            return Array.prototype.slice.call(elements || []);
          },
          applyOrder: function () {},
        };
      })();

    var scheduleAnimation = (function createFrameScheduler() {
      if (
        typeof window !== "undefined" &&
        typeof window.requestAnimationFrame === "function"
      ) {
        var raf = window.requestAnimationFrame.bind(window);
        var perf =
          window.performance && typeof window.performance.now === "function"
            ? window.performance
            : {
                now: function () {
                  return Date.now();
                },
              };
        var tasks = [];
        var rafId = null;

        function flush(now) {
          for (var i = 0; i < tasks.length; ) {
            if (now >= tasks[i].time) {
              var task = tasks.splice(i, 1)[0];
              try {
                task.fn();
              } catch (error) {
                console.error("Card Oracle animation task failed", error);
              }
            } else {
              i += 1;
            }
          }

          if (tasks.length) {
            rafId = raf(flush);
          } else {
            rafId = null;
          }
        }

        return function schedule(fn, delay) {
          var due = perf.now() + (delay || 0);
          tasks.push({ fn: fn, time: due });
          if (!rafId) {
            rafId = raf(flush);
          }
        };
      }

      return function scheduleFallback(fn, delay) {
        setTimeout(fn, delay || 0);
      };
    })();

    function createStatusAnnouncer($statusEl) {
      if (!$statusEl || !$statusEl.length) {
        return { set: function () {} };
      }

      return {
        set: function (state) {
          var key = state || "ready";
          var message = $statusEl.data("status-" + key);
          if (typeof message === "undefined") {
            message = $statusEl.data("status-ready");
          }
          if (typeof message === "string") {
            $statusEl.text(message);
          }
        },
      };
    }

    if ($(".card-oracle-ecabala").length) {
      console.log("E-Cabala");

      var cards = $(".card-oracle-card");
      var cardSelected = false;
      var positions = $("div.data").data("positions");
      var shuffleState = shuffleUtils.createState(positions);

      $("#card-oracle-cardsubmit").prop("disabled", true);
      $("#readingsubmit").prop("hidden", true);

      $("button.clicked").click(function () {
        if (!cardSelected) {
          var selectedId = String(this.value);
          var selection = shuffleUtils.recordSelection(
            shuffleState,
            selectedId,
            {},
          );
          if (!selection.wasRecorded) {
            return;
          }

          cardID = selectedId;
          console.log("Postions:" + positions);
          $(".card-oracle-card-body").css("transition", "transform 0s");
          $(".card-oracle-card-body").css("-webkit-transition", "transform 0s");

          // Get desired elements
          var element = document.getElementsByClassName("card-oracle-back");

          // Iterate through the retrieved elements and add the necessary class names.
          for (var i = 0; i < element.length; i++) {
            element[i].classList.add("card-oracle-nohover");
            console.log(element[i].className);
          }

          $(this).closest(".card-oracle-card-body").toggleClass("is-flipped");
          $(this).fadeOut(0);

          $("#card-oracle-picks").val(selection.clicked.join());

          // Hide shuffle button after first card selection
          if (selection.hideShuffleButton) {
            $(".card-oracle-shuffle-container").addClass("hidden");
          }

          cardSelected = true;
          $("#card-oracle-cardsubmit").prop("disabled", false);
        }
      });

      $("#card-oracle-cardsubmit").click(function () {
        console.log("Count: " + shuffleState.count);
        console.log("ID: " + cardID);
        $(".card-oracle-card-body").css("transition", "transform 0s");
        $(".card-oracle-cards").children().prop("disabled", false);

        $("#btn" + cardID).prop("disabled", false);
        $("#btn" + cardID).toggle();
        $("#card-body" + cardID).toggleClass("is-flipped");
        $("#card-oracle-cardsubmit").prop("disabled", true);

        if (
          shuffleState.count < shuffleState.positions ||
          shuffleState.positions === 0
        ) {
          cardSelected = false;

          // Get desired elements
          var element = document.getElementsByClassName("card-oracle-back");

          // Iterate through the retrieved elements and add the necessary class names.
          for (var i = 0; i < element.length; i++) {
            element[i].classList.remove("card-oracle-nohover");
          }

          var shuffleOrder = shuffleUtils.shuffleIndices(cards.length);
          var shuffledCards = shuffleUtils.reorderByIndices(
            cards,
            shuffleOrder,
          );
          var cardContainer = cards.length ? cards.eq(0).parent() : null;
          shuffleUtils.applyOrder(cardContainer, shuffledCards);
        } else {
          $("#readingsubmit").prop("hidden", false);
          $("#card-oracle-cardsubmit").prop("hidden", true);
          $(".card-oracle-cards").toggle();
          if ($("#submitbuttondiv").hasClass("hiddenreadingsubmit")) {
            $("#readingsubmit").trigger("click");
          }
        }
      });
    } else {
      console.log("Standard");
      var positions = $("div.data").data("positions");
      var shuffleState = shuffleUtils.createState(positions);

      $("#readingsubmit").prop("disabled", true);

      $("li img").click(function () {
        var rawId = $(this).data("value");
        if (rawId === undefined) {
          return;
        }

        var cardKey = String(rawId);
        var selection = shuffleUtils.recordSelection(shuffleState, cardKey, {
          reversed: Boolean($(this).attr("data-reversed")),
        });

        if (!selection.wasRecorded) {
          return;
        }

        console.log("Card ID: " + cardKey);
        $(this).toggleClass("card-oracle-image-hidden");
        $("#card" + cardKey).toggleClass("card-oracle-image-hidden");

        // Add card-selected class to li for overlapping layout styling
        $(this).closest("li").toggleClass("card-selected");

        if (selection.hideShuffleButton) {
          $(".card-oracle-shuffle-container").addClass("hidden");
        }

        $("#card-oracle-picks").val(selection.clicked.join());
        $("#reverse").val(selection.reverse.join());

        if (selection.isComplete) {
          $(".btn-block").show();
          $(".btn-block").css("opacity", "1");
          $("#readingsubmit").click();
          $("#readingsubmit").prop("disabled", false);
          if ($("#submitbuttondiv").hasClass("hiddenreadingsubmit")) {
            $("#readingsubmit").trigger("click");
          }
        }
      });

      $("button.clicked").click(function () {
        $(".card-oracle-card-body").css("transition", "transform .5s");
        $(".card-oracle-card-body").css("-webkit-transition", "transform .5s");

        var cardValue = String(this.value);
        var selection = shuffleUtils.recordSelection(shuffleState, cardValue, {
          reversed: Boolean($(this).attr("data-value")),
        });

        if (!selection.wasRecorded) {
          return;
        }

        $(this).closest(".card-oracle-card-body").toggleClass("is-flipped");
        $(this).fadeOut(80);

        if (selection.hideShuffleButton) {
          $(".card-oracle-shuffle-container").addClass("hidden");
        }

        $("#card-oracle-picks").val(selection.clicked.join());
        $("#reverse").val(selection.reverse.join());

        if (selection.isComplete) {
          $(".btn-block").show();
          $(".btn-block").css("opacity", "1");
          $("#readingsubmit").prop("disabled", false);
          if ($("#submitbuttondiv").hasClass("hiddenreadingsubmit")) {
            $("#readingsubmit").trigger("click");
          }
        }
      });

      $("#card-oracle-question").on("submit", function (e) {
        console.log("Submit button clicked");
      });

      // Delegated binding: the email form lives inside .card-oracle-reading,
      // which the progressive-enhancement reveal replaces via innerHTML. A
      // direct binding would be lost after that swap, so delegate from document.
      $(document).on("click", "#reading-send", function (e) {
        e.preventDefault(); // if the clicked element is a link

        $.post(
          $("#ajax_url").val(),
          {
            action: "send_reading_email",
            email: $("#emailaddress").val(),
            emailtoken: $("#emailtoken").val(),
            subscribe: $("#card-oracle-subscribe").is(":checked")
              ? "true"
              : "false",
            security: $("#_wpnonce").val(),
            readingid: $("#readingid").val(),
          },
          function (response) {
            // handle a successful response
            $(".card-oracle-response").text(response.data);
            $("#emailaddress").val("");
            console.log(response);
          },
        );
      });
    }

    // Enhanced Shuffle Functionality with Error Handling
    $(document).on("click", "[data-shuffle-button]", function () {
      var $shuffleBtn = $(this);
      var shuffleId = $shuffleBtn.data("shuffle-id");
      var $root = shuffleId
        ? $('[data-shuffle-root="' + shuffleId + '"]')
        : $shuffleBtn.closest("[data-shuffle-root]");
      var $status = $root.find("[data-shuffle-status]");
      var announcer = createStatusAnnouncer($status);

      // Early exit if animation is already in progress
      if ($shuffleBtn.prop("disabled")) {
        announcer.set("ready");
        return false;
      }

      // Determine layout type and get appropriate elements - scoped to this shortcode instance
      // Find the closest card container to the shuffle button
      var $cardContainer = $shuffleBtn.closest(".card-oracle-container");
      if (!$cardContainer.length) {
        $cardContainer = $root.length ? $root : $(document);
      }

      var $standardCards = $cardContainer.find(".card-oracle-card");
      var $circularCards = $cardContainer.find(".tarot-spread-circle li");
      var $overlapCards = $cardContainer.find(".tarot-deck-overlap li");

      // Enhanced layout detection - check for specific containers first (scoped)
      var isStandardLayout =
        $cardContainer.find(".card-oracle-cards").length > 0 &&
        $standardCards.length > 0;
      var isCircularLayout =
        $cardContainer.find(".tarot-deck-circle").length > 0 &&
        $circularCards.length > 0;
      var isOverlapLayout =
        $cardContainer.find(".tarot-deck-overlap").length > 0 &&
        $overlapCards.length > 0;

      // Fallback to card count if containers are ambiguous
      if (!isStandardLayout && !isCircularLayout && !isOverlapLayout) {
        isStandardLayout = $standardCards.length > 0;
        isCircularLayout = $circularCards.length > 0 && !isStandardLayout;
        isOverlapLayout =
          $overlapCards.length > 0 && !isStandardLayout && !isCircularLayout;
      }

      var $cards = isStandardLayout
        ? $standardCards
        : isCircularLayout
          ? $circularCards
          : $overlapCards;

      // Enhanced validation with user feedback
      if ($cards.length === 0) {
        console.warn("Card Oracle: No cards found for shuffle animation");
        announcer.set("ready");
        return false;
      }

      // Validate layout detection
      if (!isStandardLayout && !isCircularLayout && !isOverlapLayout) {
        console.warn(
          "Card Oracle: Unable to determine layout type for shuffle",
        );
        announcer.set("ready");
        return false;
      }

      try {
        // Disable button during shuffle
        $shuffleBtn
          .prop("disabled", true)
          .attr({ "aria-pressed": "true", "aria-busy": "true" });
        announcer.set("busy");

        // Perform enhanced shuffle animation
        performPokerWash(
          $cards,
          $shuffleBtn,
          isStandardLayout,
          isCircularLayout,
          isOverlapLayout,
          announcer,
        );
      } catch (error) {
        console.error("Card Oracle: Shuffle animation error:", error);
        // Re-enable button on error
        $shuffleBtn
          .prop("disabled", false)
          .attr({ "aria-pressed": "false", "aria-busy": "false" });
        announcer.set("ready");
      }
    });

    function performPokerWash(
      $cards,
      $shuffleBtn,
      isStandardLayout,
      isCircularLayout,
      isOverlapLayout,
      announcer,
    ) {
      // Performance optimization: Cache DOM queries and calculations
      var startTime = performance.now();
      var originalPositions = [];
      var originalOrder = [];
      var $container, $parentContainer;

      // Find containers relative to the cards (scoped to this shortcode instance)
      var $firstCard = $cards.first();
      if (isStandardLayout) {
        $container = $firstCard.closest(".card-oracle-cards");
        $parentContainer = $container;
      } else if (isCircularLayout) {
        $container = $firstCard.closest(".tarot-spread-circle");
        var $circleContainer = $firstCard.closest(
          ".tarot-deck-circle-container",
        );
        $parentContainer =
          $circleContainer.length > 0
            ? $circleContainer
            : $firstCard.closest(".tarot-deck-circle");
      } else {
        $container = $firstCard.closest("ul");
        $parentContainer = $firstCard.closest(".tarot-deck-overlap");
      }

      // Calculate container center
      // For circular layout, use $container (ul) since cards are positioned relative to it
      var centerReference = isCircularLayout
        ? $container[0]
        : $parentContainer[0];
      var containerRect = centerReference.getBoundingClientRect();
      var centerX = containerRect.width / 2;
      var centerY = containerRect.height / 2;

      // Store original positions and properties BEFORE adding washing class
      $cards.each(function (index) {
        var $card = $(this);
        originalOrder[index] = $card[0];

        var rect = $card[0].getBoundingClientRect();
        // For circular layout, use $container (ul) as reference since that's where cards are absolutely positioned
        // For other layouts, use $parentContainer
        var positionReference = isCircularLayout
          ? $container[0]
          : $parentContainer[0];
        var parentRect = positionReference.getBoundingClientRect();

        originalPositions[index] = {
          element: $card,
          left: rect.left - parentRect.left,
          top: rect.top - parentRect.top,
          width: rect.width,
          height: rect.height,
          transform: $card.css("transform"),
          zIndex: $card.css("z-index"),
          position: $card.css("position"),
          // Store additional properties for circular layout
          isCircular: isCircularLayout,
          circularAngle: isCircularLayout ? index * (360 / $cards.length) : 0,
          originalStyle: $card.attr("style") || "",
        };
      });

      // Lock container height BEFORE adding washing class
      var originalHeight = $parentContainer.height();
      var containerHeight = Math.max(originalHeight, 400);
      $parentContainer.css({
        "min-height": containerHeight + "px",
        height: containerHeight + "px",
      });

      // Add washing class BEFORE setting absolute positioning
      // This ensures container has position:relative so cards position correctly
      $container.addClass("washing");
      if ($parentContainer !== $container) {
        $parentContainer.addClass("washing");
      }

      // NOW set cards to absolute positioning (after container has position:relative)
      $cards.each(function (index) {
        var $card = $(this);

        var animationSetupCss = {
          position: "absolute",
          left: originalPositions[index].left + "px",
          top: originalPositions[index].top + "px",
          width: originalPositions[index].width + "px",
          height: originalPositions[index].height + "px",
          zIndex: 100 + index,
          transition: "none",
        };

        // For circular layout, use centered transform-origin and no rotation
        if (isCircularLayout) {
          animationSetupCss.transform = "none";
          animationSetupCss.transformOrigin = "50% 50% 0";
        } else {
          animationSetupCss.transform =
            originalPositions[index].transform !== "none"
              ? originalPositions[index].transform
              : "";
        }

        $card.css(animationSetupCss);
      });

      // Phase 1: Move all cards toward center with staggered timing (like CodeSandbox)
      scheduleAnimation(function () {
        moveCardsToCenter($cards, centerX, centerY, $parentContainer);
      }, 100);

      // Phase 2: Shuffle and return to positions
      scheduleAnimation(function () {
        shuffleAndReturnCards(
          $cards,
          originalPositions,
          originalOrder,
          $container,
          $parentContainer,
          $shuffleBtn,
          isStandardLayout,
          isCircularLayout,
          isOverlapLayout,
          announcer,
        );
      }, 2500);
    }

    function moveCardsToCenter($cards, centerX, centerY, $parentContainer) {
      var totalCards = $cards.length;
      var animationDuration = 1500; // Total animation time like CodeSandbox

      $cards.each(function (index) {
        var $card = $(this);

        // Get card dimensions to properly center it
        var cardWidth = $card.outerWidth();
        var cardHeight = $card.outerHeight();

        // Calculate staggered delay like CodeSandbox: (index * totalDuration) / totalCards
        var delay = (index * animationDuration) / totalCards;

        scheduleAnimation(function () {
          // Add slight random offset to center position for natural look
          var offsetX = (Math.random() - 0.5) * 60; // ±30px offset
          var offsetY = (Math.random() - 0.5) * 60; // ±30px offset

          // Center the card by accounting for its dimensions
          var targetX = centerX - cardWidth / 2 + offsetX;
          var targetY = centerY - cardHeight / 2 + offsetY;

          // Add slight rotation for dynamic effect
          var rotation = (Math.random() - 0.5) * 30; // ±15 degrees

          $card.addClass("shuffle-moving").css({
            left: targetX + "px",
            top: targetY + "px",
            transform: "rotate(" + rotation + "deg)",
            transition: "all 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94)", // Smooth easing like CodeSandbox
            zIndex: 200 + index, // Higher z-index during animation
          });
        }, delay);
      });
    }

    function shuffleAndReturnCards(
      $cards,
      originalPositions,
      originalOrder,
      $container,
      $parentContainer,
      $shuffleBtn,
      isStandardLayout,
      isCircularLayout,
      isOverlapLayout,
      announcer,
    ) {
      // Fisher-Yates shuffle to randomize which cards go to which positions
      var shuffledIndices = [];
      for (var i = 0; i < $cards.length; i++) {
        shuffledIndices[i] = i;
      }

      for (var i = shuffledIndices.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = shuffledIndices[i];
        shuffledIndices[i] = shuffledIndices[j];
        shuffledIndices[j] = temp;
      }

      // Return cards to shuffled positions with staggered timing
      var totalCards = $cards.length;
      var angleStep = 360 / totalCards;

      // Get the circular diameter from CSS variable for proper transform-origin
      var circularDiameter = "235%"; // Default fallback
      if (isCircularLayout) {
        var circleContainer = $container.closest(".tarot-deck-circle")[0];
        if (circleContainer) {
          var computedDiameter = getComputedStyle(
            circleContainer,
          ).getPropertyValue("--circular-diameter");
          if (computedDiameter && computedDiameter.trim()) {
            circularDiameter = computedDiameter.trim();
          }
        }
      }

      var returnAnimationDuration = 600; // Must match the CSS transition duration below
      var cardReturnDelay = 60; // Delay between each card starting its return

      $cards.each(function (cardIndex) {
        var $card = $(this);
        var targetPositionIndex = shuffledIndices[cardIndex];
        var targetPos = originalPositions[targetPositionIndex];
        var delay = cardIndex * cardReturnDelay;

        scheduleAnimation(function () {
          if (isCircularLayout) {
            // Circular layout: animate to left:0, top:0 with rotation
            // Restore the correct transform-origin for circular fan positioning
            var newAngle = targetPositionIndex * angleStep;
            $card
              .removeClass("shuffle-moving")
              .addClass("shuffle-returning")
              .css({
                left: "0",
                top: "0",
                transform: "translate(0px) rotate(" + newAngle + "deg)",
                transformOrigin: "50% " + circularDiameter + " 0",
                transition: "all 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94)",
                zIndex: targetPos.zIndex,
              });
          } else {
            // Standard/Overlap layouts: animate to bounding rect positions
            $card
              .removeClass("shuffle-moving")
              .addClass("shuffle-returning")
              .css({
                left: targetPos.left + "px",
                top: targetPos.top + "px",
                transform: targetPos.transform || "none",
                transition: "all 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94)",
                zIndex: targetPos.zIndex,
              });
          }
        }, delay);
      });

      // Clean up and restore original state
      // Wait for all cards to finish: (lastCardIndex * delay) + animationDuration + buffer
      var cleanupDelay =
        (totalCards - 1) * cardReturnDelay + returnAnimationDuration + 100;
      scheduleAnimation(function () {
        // Remove animation classes from containers
        $container.removeClass("washing");
        if ($parentContainer !== $container) {
          $parentContainer.removeClass("washing");
        }

        // Restore container height
        $parentContainer.css({
          height: "",
          "min-height": "",
        });

        // Create new DOM order array based on shuffle
        var newDOMOrder = new Array($cards.length);
        $cards.each(function (cardIndex) {
          var targetPositionIndex = shuffledIndices[cardIndex];
          newDOMOrder[targetPositionIndex] = this;
        });

        if (isStandardLayout) {
          // Standard layout: reorder DOM elements
          $cards.detach();
          for (var i = 0; i < newDOMOrder.length; i++) {
            $container.append(newDOMOrder[i]);
          }

          // Restore original CSS properties
          $cards
            .removeClass("shuffle-moving shuffle-returning")
            .each(function (index) {
              var $card = $(this);
              var originalPos = originalPositions[index];
              $card.removeAttr("style").css({
                position: originalPos.position,
                transform: originalPos.transform || "",
                zIndex: originalPos.zIndex,
              });
            });
        } else if (isCircularLayout) {
          // Enhanced circular layout restoration with improved transform handling
          var totalCards = $cards.length;
          var angle = 360 / totalCards;

          $cards.detach();
          for (var i = 0; i < newDOMOrder.length; i++) {
            $container.append(newDOMOrder[i]);
          }

          // Apply correct transforms for circular positions with error handling
          $(newDOMOrder).each(function (index) {
            var $card = $(this);
            var originalPos = originalPositions[index];

            try {
              // Calculate new circular angle for this position
              var circularAngle = index * angle;

              $card
                .removeClass("shuffle-moving shuffle-returning")
                .removeAttr("style");

              // Apply enhanced circular positioning with fallback values
              var zIndexValue =
                originalPos.zIndex && originalPos.zIndex !== "auto"
                  ? originalPos.zIndex
                  : index + 10;

              $card.css({
                position: "absolute",
                left: "0",
                top: "0",
                transform: "translate(0px) rotate(" + circularAngle + "deg)",
                zIndex: zIndexValue,
              });
            } catch (error) {
              console.warn("Error restoring circular card position:", error);
              // Fallback: restore original style
              $card.attr("style", originalPos.originalStyle || "");
            }
          });
        } else {
          // Overlapping/Spread layouts: reorder DOM and restore original styles
          $cards.detach();
          for (var i = 0; i < newDOMOrder.length; i++) {
            $container.append(newDOMOrder[i]);
          }

          // Restore original CSS properties
          $cards
            .removeClass("shuffle-moving shuffle-returning")
            .each(function (index) {
              var $card = $(this);
              var originalPos = originalPositions[index];
              $card.removeAttr("style").css({
                position: originalPos.position,
                transform: originalPos.transform || "",
                zIndex: originalPos.zIndex,
              });
            });
        }

        // Re-enable button and add completion effect
        $shuffleBtn
          .prop("disabled", false)
          .attr({ "aria-pressed": "false", "aria-busy": "false" });
        announcer.set("complete");

        // Performance logging
        var endTime = performance.now();
        console.log(
          "Card Oracle: Shuffle animation completed in " +
            (endTime - startTime).toFixed(2) +
            "ms",
        );

        // Brief completion flash with optimized opacity animation
        $cards.css("opacity", "0.9");
        scheduleAnimation(function () {
          $cards.css("opacity", "1");
        }, 200);
      }, cleanupDelay);
    }
  });
})(jQuery);

/**
 * Progressive-enhancement AJAX reveal.
 *
 * Intercepts the reading form submit, posts the existing form data to the
 * same URL via fetch, parses the response, and swaps the .card-oracle-reading
 * wrapper's contents in place. Falls back to a normal form POST if fetch
 * isn't available or anything goes wrong.
 */
(function () {
  "use strict";

  if (typeof window === "undefined" || typeof document === "undefined") {
    return;
  }
  if (typeof window.fetch !== "function" || typeof DOMParser !== "function") {
    return;
  }

  var SELECTOR = 'form[name="card-oracle-question"]';

  function findReadingWrapper(form) {
    var el = form;
    while (el && el !== document.body) {
      if (el.classList && el.classList.contains("card-oracle-reading")) {
        return el;
      }
      el = el.parentElement;
    }
    return null;
  }

  function swapReadingContent(wrapper, htmlText) {
    var doc = new DOMParser().parseFromString(htmlText, "text/html");
    if (!doc) {
      return false;
    }

    var readingId = wrapper.getAttribute("data-reading-id") || "";
    var candidate = null;
    if (readingId) {
      var nodes = doc.querySelectorAll(
        '.card-oracle-reading[data-reading-id="' + readingId + '"]'
      );
      if (nodes.length) {
        candidate = nodes[nodes.length - 1];
      }
    }
    if (!candidate) {
      var fallback = doc.querySelectorAll(".card-oracle-reading");
      if (fallback.length) {
        candidate = fallback[fallback.length - 1];
      }
    }
    if (!candidate) {
      return false;
    }

    wrapper.innerHTML = candidate.innerHTML;

    // Scroll the wrapper into view so the user sees the result immediately.
    if (typeof wrapper.scrollIntoView === "function") {
      try {
        wrapper.scrollIntoView({ behavior: "smooth", block: "start" });
      } catch (e) {
        wrapper.scrollIntoView();
      }
    }

    return true;
  }

  function bindForm(form) {
    if (form.__cardOracleAjaxBound) {
      return;
    }
    form.__cardOracleAjaxBound = true;

    form.addEventListener("submit", function (event) {
      var wrapper = findReadingWrapper(form);
      if (!wrapper) {
        return; // Fall back to normal submit.
      }

      event.preventDefault();
      wrapper.classList.add("card-oracle-reading--loading");

      var formData = new FormData(form);
      formData.append("readingsubmit", "1");

      var url = form.getAttribute("action") || window.location.href;

      fetch(url, {
        method: "POST",
        credentials: "same-origin",
        body: formData,
      })
        .then(function (response) {
          if (!response.ok) {
            throw new Error("HTTP " + response.status);
          }
          return response.text();
        })
        .then(function (text) {
          var swapped = swapReadingContent(wrapper, text);
          if (!swapped) {
            throw new Error("Reveal markup not found in response");
          }
          wrapper.classList.remove("card-oracle-reading--loading");
        })
        .catch(function () {
          // On any failure, fall back to a normal form submit so the user
          // still gets their reading.
          wrapper.classList.remove("card-oracle-reading--loading");
          form.__cardOracleAjaxBound = false;
          form.submit();
        });
    });
  }

  function init() {
    var forms = document.querySelectorAll(SELECTOR);
    for (var i = 0; i < forms.length; i++) {
      bindForm(forms[i]);
    }
  }

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", init);
  } else {
    init();
  }
})();
