import { SERVER_ISLAND_START } from "../runtime/server/render/server-islands-shared.js";
const PERSIST_ATTR = "data-astro-transition-persist";
const NON_OVERRIDABLE_ASTRO_ATTRS = ["data-astro-transition", "data-astro-transition-fallback"];
const knownVueScopedStyles = /* @__PURE__ */ new Map();
const scriptsAlreadyRan = /* @__PURE__ */ new Set();
function detectScriptExecuted(script) {
  const key = script.src ? new URL(script.src, location.href).href : script.textContent;
  if (scriptsAlreadyRan.has(key)) return true;
  scriptsAlreadyRan.add(key);
  return false;
}
function deselectScripts(doc) {
  for (const s2 of doc.scripts) {
    if (
      // Check if the script should be rerun regardless of it being the same
      !s2.hasAttribute("data-astro-rerun") && // Check if the script has already been executed
      detectScriptExecuted(s2)
    ) {
      s2.dataset.astroExec = "";
    }
  }
}
function swapRootAttributes(newDoc) {
  const currentRoot = document.documentElement;
  const nonOverridableAstroAttributes = [...currentRoot.attributes].filter(
    ({ name }) => (currentRoot.removeAttribute(name), NON_OVERRIDABLE_ASTRO_ATTRS.includes(name))
  );
  [...newDoc.documentElement.attributes, ...nonOverridableAstroAttributes].forEach(
    ({ name, value }) => currentRoot.setAttribute(name, value)
  );
}
function swapHeadElements(doc) {
  const relevantNodes = (parent, what = "both") => [
    ...[...parent.childNodes].filter(
      (child) => child.nodeType === 8 && child.textContent === SERVER_ISLAND_START || what === "both" && child.nodeType === 1
    )
  ];
  for (const el of Array.from(document.head.children)) {
    const newEl = persistedHeadElement(el, doc);
    if (newEl) {
      newEl.remove();
    } else {
      if (import.meta.env.DEV && el instanceof HTMLStyleElement) {
        const viteDevId = vueScopedStyleId(el);
        viteDevId && knownVueScopedStyles.set(viteDevId, el);
      }
      el.remove();
    }
  }
  relevantNodes(document.head, "commentsOnly").forEach((node) => node.remove());
  if (import.meta.env.DEV) {
    relevantNodes(doc.head).forEach((child) => {
      document.head.append(knownVueScopedStyles.get(child.dataset?.viteDevId) || child);
    });
  } else {
    document.head.append(...relevantNodes(doc.head));
  }
}
function swapBodyElement(newElement, oldElement) {
  const persistPairs = [];
  const docEl = oldElement.ownerDocument.documentElement;
  const moveBefore = typeof docEl.moveBefore === "function" ? (parent, node, child) => parent.moveBefore(node, child) : null;
  for (const el of oldElement.querySelectorAll(`[${PERSIST_ATTR}]`)) {
    const id = el.getAttribute(PERSIST_ATTR);
    const newEl = newElement.querySelector(`[${PERSIST_ATTR}="${id}"]`);
    if (!newEl) continue;
    persistPairs.push({ old: el, newTarget: newEl });
    if (moveBefore) {
      moveBefore(docEl, el, null);
    } else {
      docEl.appendChild(el);
    }
  }
  oldElement.replaceWith(newElement);
  for (const { old: el, newTarget } of persistPairs) {
    if (moveBefore) {
      moveBefore(newTarget.parentNode, el, newTarget);
      newTarget.remove();
    } else {
      newTarget.replaceWith(el);
    }
    if (newTarget.localName === "astro-island" && shouldCopyProps(el) && !isSameProps(el, newTarget)) {
      el.setAttribute("ssr", "");
      el.setAttribute("props", newTarget.getAttribute("props"));
    }
  }
  attachShadowRoots(newElement);
}
function attachShadowRoots(root) {
  root.querySelectorAll("template[shadowrootmode]").forEach((template) => {
    const mode = template.getAttribute("shadowrootmode");
    const parent = template.parentNode;
    if ((mode === "closed" || mode === "open") && parent instanceof HTMLElement) {
      if (parent.shadowRoot) {
        template.remove();
        return;
      }
      const shadowRoot = parent.attachShadow({ mode });
      shadowRoot.appendChild(template.content);
      template.remove();
      attachShadowRoots(shadowRoot);
    }
  });
}
const saveFocus = () => {
  const activeElement = document.activeElement;
  if (activeElement?.closest(`[${PERSIST_ATTR}]`)) {
    if (activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement) {
      const start = activeElement.selectionStart;
      const end = activeElement.selectionEnd;
      return () => restoreFocus({ activeElement, start, end });
    }
    return () => restoreFocus({ activeElement });
  } else {
    return () => restoreFocus({ activeElement: null });
  }
};
const restoreFocus = ({ activeElement, start, end }) => {
  if (activeElement) {
    activeElement.focus();
    if (activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement) {
      if (typeof start === "number") activeElement.selectionStart = start;
      if (typeof end === "number") activeElement.selectionEnd = end;
    }
  }
};
const vueScopedStyleId = (el) => {
  const viteDevId = el.dataset.viteDevId || "";
  const url = new URL(viteDevId, location.href);
  return url.searchParams.get("vue") !== null && url.searchParams.get("type") === "style" && url.searchParams.has("scoped") ? viteDevId : "";
};
const persistedHeadElement = (el, newDoc) => {
  const id = el.getAttribute(PERSIST_ATTR);
  const newEl = id && newDoc.head.querySelector(`[${PERSIST_ATTR}="${id}"]`);
  if (newEl) {
    return newEl;
  }
  if (el.matches("link[rel=stylesheet]")) {
    const href = el.getAttribute("href");
    return newDoc.head.querySelector(`link[rel=stylesheet][href="${href}"]`);
  }
  if (import.meta.env.DEV && el instanceof HTMLStyleElement) {
    const viteDevId = vueScopedStyleId(el);
    if (viteDevId) {
      return newDoc.head.querySelector(`style[data-vite-dev-id="${viteDevId}"]`);
    }
  }
  if (el.tagName === "STYLE" && el.textContent) {
    const styles = newDoc.head.querySelectorAll("style");
    for (const s of styles) {
      if (s.textContent === el.textContent) {
        return s;
      }
    }
  }
  if (el.matches("link[rel=preload][as=font]")) {
    const href = el.getAttribute("href");
    return newDoc.head.querySelector(`link[rel=preload][as=font][href="${href}"]`);
  }
  return null;
};
const shouldCopyProps = (el) => {
  const persistProps = el.dataset.astroTransitionPersistProps;
  return persistProps == null || persistProps === "false";
};
const isSameProps = (oldEl, newEl) => {
  return oldEl.getAttribute("props") === newEl.getAttribute("props");
};
const swapFunctions = {
  deselectScripts,
  swapRootAttributes,
  swapHeadElements,
  swapBodyElement,
  saveFocus
};
const swap = (doc) => {
  deselectScripts(doc);
  swapRootAttributes(doc);
  swapHeadElements(doc);
  const restoreFocusFunction = saveFocus();
  swapBodyElement(doc.body, document.body);
  restoreFocusFunction();
};
export {
  deselectScripts,
  detectScriptExecuted,
  restoreFocus,
  saveFocus,
  swap,
  swapBodyElement,
  swapFunctions,
  swapHeadElements,
  swapRootAttributes,
  vueScopedStyleId
};
