// AdBlockMaxxer — Element Zapper (ISOLATED world, all sites).
//
// Two jobs:
//   1. On every page, hide whatever you've previously zapped on this hostname
//      (a <style> injected at document_start, so no flash).
//   2. Pick mode: hover highlights the element under the cursor, click hides it and
//      remembers a CSS selector for it (per hostname). Trigger via the Alt+Shift+Z
//      command or the panel's "Zap element" button. Esc cancels. "Undo last zap" lives
//      in the panel.
//
// Storage: zapped = { "<hostname>": ["selector", ...] }

(function () {
  "use strict";

  const HOST = location.hostname;
  const STYLE_ID = "adblockmaxxer-zap";
  let selectors = [];

  function applyStyle() {
    let style = document.getElementById(STYLE_ID);
    if (!selectors.length) { if (style) style.remove(); return; }
    if (!style) {
      style = document.createElement("style");
      style.id = STYLE_ID;
      (document.head || document.documentElement).appendChild(style);
    }
    style.textContent = selectors.join(",") + "{display:none !important;}";
  }

  function load() {
    chrome.storage.local.get("zapped", (r) => {
      const map = (r && r.zapped) || {};
      selectors = Array.isArray(map[HOST]) ? map[HOST].slice() : [];
      applyStyle();
    });
  }
  chrome.storage.onChanged.addListener((c) => {
    if (c.zapped) {
      const map = c.zapped.newValue || {};
      selectors = Array.isArray(map[HOST]) ? map[HOST].slice() : [];
      applyStyle();
    }
  });
  load();

  function persist(next) {
    chrome.storage.local.get("zapped", (r) => {
      const map = (r && r.zapped) || {};
      if (next.length) map[HOST] = next; else delete map[HOST];
      chrome.storage.local.set({ zapped: map });
    });
  }

  // ---- selector generation -------------------------------------------------
  function cssEscape(s) {
    if (window.CSS && CSS.escape) return CSS.escape(s);
    return s.replace(/[^a-zA-Z0-9_-]/g, "\\$&");
  }
  function stableClasses(el) {
    return Array.from(el.classList || [])
      .filter((c) => c && !/\d{3,}/.test(c) && !/^(is-|has-|js-)/.test(c) && c.length < 40)
      .slice(0, 2);
  }
  function selectorFor(el) {
    if (el.id && document.querySelectorAll("#" + cssEscape(el.id)).length === 1) {
      return "#" + cssEscape(el.id);
    }
    const parts = [];
    let node = el;
    while (node && node.nodeType === 1 && node !== document.documentElement) {
      let part = node.tagName.toLowerCase();
      const cls = stableClasses(node);
      if (cls.length) part += "." + cls.map(cssEscape).join(".");
      // disambiguate among same-named siblings
      const parent = node.parentElement;
      if (parent) {
        const sameTag = Array.from(parent.children).filter((c) => c.tagName === node.tagName);
        if (sameTag.length > 1) part += ":nth-of-type(" + (sameTag.indexOf(node) + 1) + ")";
      }
      parts.unshift(part);
      // stop early if the path is already unique
      const candidate = parts.join(" > ");
      try { if (document.querySelectorAll(candidate).length === 1) return candidate; } catch (e) {}
      node = node.parentElement;
      if (parts.length >= 5) break;
    }
    return parts.join(" > ");
  }

  // ---- pick mode -----------------------------------------------------------
  let picking = false;
  let box = null;
  let current = null;

  function ensureBox() {
    if (box) return box;
    box = document.createElement("div");
    box.id = "adblockmaxxer-zap-box";
    Object.assign(box.style, {
      position: "fixed", zIndex: "2147483646", pointerEvents: "none",
      background: "rgba(177,76,255,0.22)", border: "2px solid #b14cff",
      borderRadius: "3px", transition: "all .03s linear", display: "none",
      boxShadow: "0 0 0 9999px rgba(0,0,0,0.06)",
    });
    const tag = document.createElement("div");
    tag.id = "adblockmaxxer-zap-tag";
    Object.assign(tag.style, {
      position: "fixed", zIndex: "2147483647", pointerEvents: "none",
      font: "11px/1.4 -apple-system,Segoe UI,Roboto,sans-serif", color: "#fff",
      background: "#b14cff", padding: "3px 7px", borderRadius: "5px",
      whiteSpace: "nowrap", display: "none", maxWidth: "70vw", overflow: "hidden",
      textOverflow: "ellipsis",
    });
    box._tag = tag;
    (document.body || document.documentElement).appendChild(box);
    (document.body || document.documentElement).appendChild(tag);
    return box;
  }

  function highlight(el) {
    if (!el) return;
    ensureBox();
    const r = el.getBoundingClientRect();
    Object.assign(box.style, {
      display: "block", left: r.left + "px", top: r.top + "px",
      width: r.width + "px", height: r.height + "px",
    });
    const t = box._tag;
    t.style.display = "block";
    t.textContent = el.tagName.toLowerCase() + (el.id ? "#" + el.id : "") +
      (el.className && typeof el.className === "string" ? "." + el.className.trim().split(/\s+/).slice(0, 2).join(".") : "");
    const top = Math.max(2, r.top - 22);
    t.style.left = r.left + "px";
    t.style.top = top + "px";
  }

  function onMove(e) {
    if (!picking) return;
    const el = document.elementFromPoint(e.clientX, e.clientY);
    if (!el || el === box || el === (box && box._tag)) return;
    current = el;
    highlight(el);
  }
  function onClick(e) {
    if (!picking) return;
    e.preventDefault();
    e.stopPropagation();
    const el = current || document.elementFromPoint(e.clientX, e.clientY);
    if (el && el !== document.body && el !== document.documentElement) {
      const sel = selectorFor(el);
      if (sel && !selectors.includes(sel)) {
        selectors.push(sel);
        persist(selectors.slice());
        applyStyle();
      }
    }
    stopPick();
  }
  function onKey(e) {
    if (picking && e.key === "Escape") { e.preventDefault(); stopPick(); }
  }

  function startPick() {
    if (picking) return;
    picking = true;
    ensureBox();
    document.documentElement.style.cursor = "crosshair";
    document.addEventListener("mousemove", onMove, true);
    document.addEventListener("click", onClick, true);
    document.addEventListener("keydown", onKey, true);
  }
  function stopPick() {
    picking = false;
    if (box) { box.style.display = "none"; box._tag.style.display = "none"; }
    document.documentElement.style.cursor = "";
    document.removeEventListener("mousemove", onMove, true);
    document.removeEventListener("click", onClick, true);
    document.removeEventListener("keydown", onKey, true);
  }

  function undoLast() {
    if (!selectors.length) return;
    selectors.pop();
    persist(selectors.slice());
    applyStyle();
  }

  // ---- triggers ------------------------------------------------------------
  // Keyboard command relayed by the background worker.
  chrome.runtime.onMessage.addListener((msg) => {
    if (!msg) return;
    if (msg.type === "cmd" && msg.cmd === "zap-mode") startPick();
  });
  // Buttons from the floating panel (same isolated world / frame).
  window.addEventListener("abm-zap-start", startPick);
  window.addEventListener("abm-zap-undo", undoLast);
})();
