/**
 * Check if page has been loaded inside an iframe.
 *
 * @returns {boolean}
 */
function isInIframe() {
  try {
    return window.self !== window.top;
  } catch (e) {
    return true;
  }
}

var ResponsiveIframe = (function () {
  var _iframeOffsetTop = 0;

  /**
   * Include other elements to calculate iframe height.
   *
   * @return {number}
   */
  function getAdditionalHeight() {
    var height = 0;

    document.querySelectorAll(".dropdown-menu.show", ".smartbanner").forEach(el => {
      height += el.offsetHeight;
    });

    return height;
  }

  function getDocHeight() {
    var h = document.body.offsetHeight + getAdditionalHeight();
    return h;
  }

  /**
   * Update AM iframe size.
   *
   * @param {boolean} scrollTop True for scrolling to the top of the page.
   */
  function messageParent(scrollTop) {
    if (typeof scrollTop != "boolean") {
      scrollTop = false;
    }
    var h = getDocHeight();
    var message = {
      height: h,
      scrollTop: scrollTop,
    };
    top.postMessage(message, "*");
  }

  function sendParentMessage(type, data) {
    var message = {};
    data = data || {};

    switch (type) {
      case "CONFIG":
        message = {
          type: "CONFIG",
          manual_offset: Skubacz.configuration.manual_offset,
          offset_elements: Skubacz.configuration.offset_elements,
          fullscreen_modal_fix: Skubacz.configuration.fullscreen_modal_fix,
        };
        break;
      case "SIZE_STRETCH":
        message = {
          type: "SIZE_STRETCH",
          applyLayoutFix: data.hasOwnProperty("applyLayoutFix")
            ? data.applyLayoutFix
            : false,
          fullscreenModalFix: data.hasOwnProperty("fullscreenModalFix")
            ? data.fullscreenModalFix
            : false,
        };
        break;
      case "SIZE_DEFAULT":
        message = {
          type: "SIZE_DEFAULT",
        };
        break;
      case "SCROLL_TO_IFRAME":
        message = {
          type: "SCROLL_TO_IFRAME",
          extraOffsetTop: data.hasOwnProperty("extraOffsetTop")
            ? parseInt(data.extraOffsetTop)
            : 0,
        };
        break;
      case "HISTORY_PUSH":
        message = {
          type: "HISTORY_PUSH",
          path: data.path,
        };
        break;
    }
    top.postMessage(message, "*");
  }

  function setModalDialogOffset(iframeFixedOffsetTop) {
    document.querySelectorAll(".modal-dialog").forEach(el => {
      el.style.marginTop = iframeFixedOffsetTop ? iframeFixedOffsetTop + "px" : "";
    });
  }

  function onMessage(e) {
    switch (e.data.type) {
      case "PARENT_SCROLL":
        _iframeOffsetTop = e.data.iframeOffsetTop;
        break;
      case "INIT_DYNAMIC_IFRAME":
        document.body.classList.remove("l-am-regular-iframe");
        document.body.classList.add("l-am-dynamic-iframe"); // add class for AM with dynamically adjusted iframe height
        document.dispatchEvent(
          new CustomEvent("dynamic-iframe.skubacz.active-menu", {
            detail: {
              contentWrapper: "#wrapper",
              activeMenu: {
                adjustSize: function () {
                  ResponsiveIframe.messageParent(false);
                },
              },
            },
          })
        );

        fixIframeModal();
        break;
      case "HIDE_MODAL":
        // Bootstrap modal
        const openModal = document.querySelector(".modal.show");
        if (openModal) {
          const openBSModal = window.Modal.getOrCreateInstance(".modal.show");
          openBSModal.hide();
        }

        // CC modal
        const isCcSettingsModalOpen = document.documentElement.classList.contains("show--preferences");
        if (isCcSettingsModalOpen) {
          window.CC.hidePreferences();
        }
        break;
      case "SET_FULLSCREEN_OFFSET":
        var iframeOffsetTop = parseInt(e.data.iframeOffsetTop);
        var iframeFixedOffsetTop = parseInt(e.data.iframeFixedOffsetTop);

        // Set offset to wrapper element in order to mask content displacement due iframe fixed position (fullscreen mode).
        document.getElementById("wrapper").style.top =
          iframeOffsetTop !== 0 ? iframeOffsetTop + "px" : ""; // If offset top is equal to 0 at this point then it means `#wrapper` doesn't need it (in this context "" means disabled).
        document.body.classList.remove("l-am-fullscreen-loading-fix");
        setModalDialogOffset(iframeFixedOffsetTop);
        break;
      case "SET_FULLSCREEN_MODAL_OFFSET":
        setModalDialogOffset(parseInt(e.data.iframeFixedOffsetTop));
        break;
      case "DISABLE_FULLSCREEN_OFFSET":
        document.getElementById("wrapper").style.top = "";
        break;
      case "TRACK_EVENT":
        ahoy.track(e.data.name, e.data.params);
        break;
      case "INIT_ANALYTICS":
        Skubacz.tracking({ tag: "InitActiveMenu", clientId: e.data.clientId });
        break;
    }
  }

  /**
   * Update iframe size on layout change (e.g adding or removing content, lazy-loading etc.).
   */
  function updateOnSizeChange() {
    try {
      // Update when layout size changes.
      new ResizeObserver(function () {
        ResponsiveIframe.messageParent(false);
      }).observe(document.getElementsByTagName("main")[0]);
    } catch (e) {
      // Fallback: update iframe size on image lazy-loading.
      [].forEach.call(
        document.querySelectorAll('[loading="lazy"]'),
        function (img) {
          img.onload = function () {
            ResponsiveIframe.messageParent(false);
          };
        }
      );
    }
  }

  function onLoad() {
    messageParent(false);
    updateOnSizeChange();
  }

  /**
   * Set of fixes for responsive fullscreen modals within iframe with dynamically adjusted iframe height.
   */
  function fixIframeModal() {
    if (!isInIframe() || Skubacz.configuration.editing) {
      return;
    }

    var iframe = ResponsiveIframe;
    document.getElementById("wrapper").style.top = ""; // make sure `#wrapper` doesn't have any `top` value which is used to determine fullscreen offset fix presence

    /**
     * Remove "mask" class used to hide "jumping effect" which is added while showing a modal (iframe fullscreen mode).
     *
     * - fixes sequential modals when events order can be as follows: hide, show, hidden, shown (bug occurs with JS modal api in creator>cart communication)
     * - ensures removal of the "mask" class with iframe async communication
     */
    function removeModalMaskOnHidden() {
      var counter = 0;
      var counterLimit = 50; // define the number of attempts (make sure function will not run forever - just in case)

      (function removeModalMask() {
        counter++;

        if (
          document.getElementById("wrapper").style.top === "" ||
          counter > counterLimit
        ) {
          document.body.classList.remove("l-am-fullscreen-loading-fix");
        } else if (document.body.classList.contains("modal-open")) {
          // `.modal-open` presence means that another modal is open so "mask" class is not required
          setTimeout(function () {
            document.body.classList.remove("l-am-fullscreen-loading-fix");
          }, 5);
        } else {
          setTimeout(function () {
            return removeModalMask();
          }, 5);
        }
      })();
    }

    document.addEventListener("show.bs.modal", function (e) {
      var modal = e.target;
      var iframeOffsetTop = iframe.getIframeOffsetTop();
      var isDistanceFromTop;

      if (Skubacz.configuration.fullscreen_modal_fix === true) {
        isDistanceFromTop = iframeOffsetTop - window.pageYOffset > 0;

        if (isDistanceFromTop) {
          iframe.sendParentMessage("SCROLL_TO_IFRAME");
        }
      }

      // If there is no offset top at this point then it means fullscreen loading fix is not needed.
      if (iframeOffsetTop !== 0) {
        document.body.classList.add("l-am-fullscreen-loading-fix");
      }

      iframe.sendParentMessage("SIZE_STRETCH");
      modal.classList.add("fade"); // enable smooth transition for modal entrance to avoid "jumping" effect
    });

    document.addEventListener("shown.bs.modal", function (e) {
      var modal = e.target;
      var modalBackdrop = document.querySelector(".modal-backdrop");

      // Remove fade out animation to match visibility with AM parent site (also required for sequential modals with custom backdrop).
      modal.classList.remove("fade");
      if (modalBackdrop) {
        modalBackdrop.classList.remove("fade");
      }
      iframe.sendParentMessage("SIZE_STRETCH", {
        applyLayoutFix: true,
        fullscreenModalFix: Skubacz.configuration.fullscreen_modal_fix,
      });
      document.body.classList.remove("l-am-fullscreen-loading-fix");
    });

    document.addEventListener("hide.bs.modal", function (e) {
      // If `#wrapper` doesn't have offset enabled at this point then it means fullscreen loading fix is not needed.
      if (document.getElementById("wrapper").style.top !== "") {
        document.body.classList.add("l-am-fullscreen-loading-fix");
      }
      iframe.sendParentMessage("SIZE_DEFAULT");
    });

    document.addEventListener("hidden.bs.modal", function (e) {
      removeModalMaskOnHidden();
    });

    window.addEventListener("cc:onModalShow", (e) => {
      if (e.detail.modalName === "preferencesModal") {
        iframe.sendParentMessage("SIZE_STRETCH");
      }
    });

    window.addEventListener("cc:onModalHide", (e) => {
      if (e.detail.modalName === "preferencesModal") {
        iframe.sendParentMessage("SIZE_DEFAULT");
      }
    });
  }

  function init() {
    window.addEventListener("load", onLoad, false);
    window.addEventListener("resize", messageParent, false);
    window.addEventListener("message", onMessage, false);
  }

  return {
    init: init,
    getIframeOffsetTop: function () {
      return _iframeOffsetTop;
    },
    messageParent: messageParent,
    sendParentMessage: sendParentMessage,
  };
})();

// Enable Scroll.js functionality for AM (required adjustments for iframe).
var scrollAM = (function () {
  var iframe = ResponsiveIframe;

  /**
   * Get the current coordinates of the element (relative to the document).
   *
   * @param {Element} el
   * @returns {object}
   */
  function offset(el) {
    box = el.getBoundingClientRect();
    docElem = document.documentElement;
    return {
      top: box.top + window.pageYOffset - docElem.clientTop,
      left: box.left + window.pageXOffset - docElem.clientLeft
    };
  }

  /**
   * Determines whether the argument represents a JavaScript number.
   *
   * @param num
   * @returns {boolean}
   */
  function isNumeric(num) {
    if (typeof num === 'number') return num - num === 0;
    if (typeof num === 'string' && num.trim() !== '')
      return Number.isFinite(+num);
    return false;
  }

  /**
   * Check for correct target element.
   *
   * @param target
   * @returns {boolean}
   */
  function isCorrectTarget(target) {
    if (target instanceof Element) {
      return true;
    } else {
      console.warn("Provide correct DOM element!");
      return false;
    }
  }

  /**
   * Scroll to specific position.
   *
   * @param scrollTop Position within iframe to scroll to along the y-axis in pixels.
   */
  function to(scrollTop) {
    if (!isNumeric(scrollTop)) {
      throw new Error("scrollTop needs to be a number!");
    }

    return iframe.sendParentMessage("SCROLL_TO_IFRAME", {
      extraOffsetTop: scrollTop,
    });
  }

  /**
   * Scroll to specific element.
   *
   * @param target
   */
  function toElement(target) {
    if (!isCorrectTarget(target)) {
      return;
    }

    return to(offset(target).top);
  }

  /**
   * Scroll to element if target is above our position.
   *
   * @param target
   */
  function scrollIfAbove(target) {
    if (!isCorrectTarget(target)) {
      return;
    }

    var targetOffsetTop = offset(target).top;
    var targetDistance = iframe.getIframeOffsetTop() + targetOffsetTop;

    if (targetDistance < 0) {
      return to(targetOffsetTop);
    }
  }

  return {
    to: to,
    toElement: toElement,
    scrollIfAbove: scrollIfAbove,
  };
})();

document.addEventListener('DOMContentLoaded', () => {
  var iframe = ResponsiveIframe;

  const getPath = () =>
    window.location.pathname + window.location.search + window.location.hash;

  iframe.init();
  iframe.messageParent(false);
  iframe.sendParentMessage("CONFIG");
  iframe.sendParentMessage("HISTORY_PUSH", { path: getPath() });

  if (document.querySelector(".js-checkout")) {
    iframe.sendParentMessage("SCROLL_TO_IFRAME");
  }

  if (document.querySelector(".js-payment")) {
    iframe.sendParentMessage("SCROLL_TO_IFRAME");
  }

  if (document.querySelector(".js-order-result")) {
    iframe.sendParentMessage("SCROLL_TO_IFRAME");
  }
  document.addEventListener("resize.skubacz.checkout", function () {
    iframe.messageParent(false);
  });
  document.addEventListener("resize.skubacz.orderInfo", function () {
    iframe.messageParent(false);
  });

  document.querySelectorAll("[data-resize-on]").forEach(function (el) {
    var e = el.getAttribute("data-resize-on");
    el.addEventListener(e, function () {
      setTimeout(function () {
        iframe.messageParent(false);
      }, 200);
    });
  });

  document.querySelectorAll("[data-toggle]").forEach(function (el) {
    el.addEventListener("click", function () {
      setTimeout(function () {
        iframe.messageParent(false);
      }, 100);
    });
  });

  document.addEventListener("shown.restaumatic.group-toggle", function (event) {
    iframe.messageParent(false);
    if (event.detail.mode === "list-all") {
      scrollAM.toElement(event.detail.el);
    } else {
      scrollAM.scrollIfAbove(event.detail.el);
    }
    iframe.sendParentMessage("HISTORY_PUSH", { path: getPath() });
  });

  document.addEventListener("hidden.restaumatic.group-toggle", function (event) {
    // Prevent double resize by checking for active group.
    if (typeof event.detail.relatedTarget === "undefined") {
      // There is no active group, so there won't be `shown` event, therefore we can resize iframe here.
      iframe.messageParent(false);
      iframe.sendParentMessage("HISTORY_PUSH", { path: getPath() });
    }
  });

  if (!isInIframe()) {
    console.log("Running outside of iframe, initialize analytics");
    Skubacz.tracking({ tag: "InitActiveMenu", clientId: null });

    document.body.classList.add("l-am-standalone"); // add class for standalone version
  } else {
    if (!document.body.classList.contains("l-am-dynamic-iframe")) {
      // Add class name for regular iframe (it's different than `l-am-dynamic-iframe` which stands for iframe with dynamically adjusted iframe height and can be set by AM parent).
      document.body.classList.add("l-am-regular-iframe");
    }

    // Fix img lazy loading issues in Safari: https://restaumatic.atlassian.net/browse/RS-5188
    if (Skubacz.Device.browser.isSafari()) {
      document.querySelectorAll('img[loading="lazy"]').forEach(function (img) {
        img.setAttribute("loading", "eager");
      });
    }
  }

  if (isInIframe() && !document.body.classList.contains("l-am-regular-iframe")) {
    window.addEventListener("scroll", function () {
      // Prevent unwanted scroll of the window and displacement of the content within iframe.
      //
      // Bug is related to hash change and it occurs when hash with target element is added to the URL,
      // e.g. `<a href="#example-hash">link</a><div id="example-hash">content</div>` on click.
      if (window.pageYOffset || document.documentElement.scrollTop) {
        window.scrollTo(0, 0);
      }
    });
  }
});