const CLIP_KEY = "__shwfed_clip";
const CLIP_VERSION = "v1";
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
function freshId() {
  if (typeof crypto !== "undefined" && "randomUUID" in crypto) return crypto.randomUUID();
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
    const r = Math.random() * 16 | 0;
    return (c === "x" ? r : r & 3 | 8).toString(16);
  });
}
function collectIds(node, into) {
  if (Array.isArray(node)) {
    for (const v of node) collectIds(v, into);
    return;
  }
  if (node === null || typeof node !== "object") return;
  for (const [k, v] of Object.entries(node)) {
    if (k === "id" && typeof v === "string" && UUID_RE.test(v)) into.add(v);
    collectIds(v, into);
  }
}
function remap(node, map) {
  if (Array.isArray(node)) return node.map((v) => remap(v, map));
  if (node === null || typeof node !== "object") {
    return typeof node === "string" ? map.get(node) ?? node : node;
  }
  const out = {};
  for (const [k, v] of Object.entries(node)) {
    out[map.get(k) ?? k] = remap(v, map);
  }
  return out;
}
function buildIdMap(items) {
  const ids = /* @__PURE__ */ new Set();
  collectIds(items, ids);
  const map = /* @__PURE__ */ new Map();
  for (const id of ids) map.set(id, freshId());
  return map;
}
export function reidItems(items) {
  return remap(items, buildIdMap(items));
}
export function reidFragment(items, placements) {
  const map = buildIdMap(items);
  return {
    items: remap(items, map),
    placements: placements ? remap(placements, map) : void 0
  };
}
export function serializeClip(surface, items, placements) {
  return JSON.stringify({ [CLIP_KEY]: CLIP_VERSION, surface, items, placements });
}
function isPlainObject(v) {
  return v !== null && typeof v === "object" && !Array.isArray(v);
}
export function parseClip(text) {
  try {
    const o = JSON.parse(text);
    if (!o || o[CLIP_KEY] !== CLIP_VERSION) return null;
    if (o.surface !== "form" && o.surface !== "block") return null;
    if (!Array.isArray(o.items)) return null;
    const placements = isPlainObject(o.placements) ? o.placements : void 0;
    return { surface: o.surface, items: o.items, placements };
  } catch {
    return null;
  }
}
export async function writeClip(surface, items, placements) {
  try {
    await navigator.clipboard.writeText(serializeClip(surface, items, placements));
    return true;
  } catch {
    return false;
  }
}
export async function readClip() {
  try {
    return parseClip(await navigator.clipboard.readText());
  } catch {
    return null;
  }
}
