/*!
 * STONK iconography - bo SVG noi bo, khong phu thuoc icon-font hoac emoji cua he dieu hanh.
 * Tu nang cap ca markup tinh va noi dung duoc dung dong sau khi trang da khoi dong.
 */
(function installStonkIcons(global) {
  "use strict";

  const ICONS = Object.freeze({
    "alarm": '<circle cx="12" cy="13" r="7"/><path d="M12 10v4l2.5 1.5M5 3 2.5 5.5M19 3l2.5 2.5M8 21h8"/>',
    "announcement": '<path d="M4 13V9l14-5v14L4 13Zm0 0 2 6h4l-2-5.3M18 9a3 3 0 0 1 0 4"/>',
    "arrow-down": '<path d="M12 4v16m-6-6 6 6 6-6"/>',
    "arrow-left": '<path d="M19 12H5m6-6-6 6 6 6"/>',
    "arrow-right": '<path d="M5 12h14m-6-6 6 6-6 6"/>',
    "arrow-up": '<path d="M12 20V4m-6 6 6-6 6 6"/>',
    "arrows-horizontal": '<path d="M8 7 3 12l5 5M16 7l5 5-5 5M3 12h18"/>',
    "arrows-vertical": '<path d="m7 8 5-5 5 5m-10 8 5 5 5-5M12 3v18"/>',
    "bell": '<path d="M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9M10 21h4"/>',
    "block": '<circle cx="12" cy="12" r="9"/><path d="m5.7 5.7 12.6 12.6"/>',
    "bolt": '<path d="m13 2-9 12h7l-1 8 9-12h-7l1-8Z"/>',
    "book": '<path d="M4 4.5A2.5 2.5 0 0 1 6.5 2H11v18H6.5A2.5 2.5 0 0 0 4 22V4.5ZM20 4.5A2.5 2.5 0 0 0 17.5 2H13v18h4.5A2.5 2.5 0 0 1 20 22V4.5Z"/>',
    "bookmark": '<path d="M6 3h12v18l-6-4-6 4V3Z"/>',
    "briefcase": '<rect x="3" y="7" width="18" height="13" rx="2"/><path d="M8 7V4h8v3M3 12h18M10 12v2h4v-2"/>',
    "building": '<path d="M4 21V5l8-3 8 3v16M8 8h1m6 0h1M8 12h1m6 0h1M8 16h1m6 0h1M10 21v-3h4v3"/>',
    "calendar": '<rect x="3" y="5" width="18" height="16" rx="2"/><path d="M16 3v4M8 3v4M3 10h18M8 14h.01M12 14h.01M16 14h.01M8 18h.01M12 18h.01"/>',
    "camera": '<path d="M4 7h3l1.5-2h7L17 7h3a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2Z"/><circle cx="12" cy="13" r="4"/>',
    "card": '<rect x="2" y="5" width="20" height="14" rx="2"/><path d="M2 10h20M6 15h4"/>',
    "celebration": '<path d="m4 20 5-13 8 8-13 5Zm5-13 3 8M14 4l1-2M18 7l3-1M18 12l3 1"/>',
    "chat": '<path d="M21 15a4 4 0 0 1-4 4H8l-5 3 1.7-5.1A7 7 0 0 1 3 12V8a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4v7Z"/><path d="M8 11h.01M12 11h.01M16 11h.01"/>',
    "check": '<circle cx="12" cy="12" r="9"/><path d="m8 12 2.7 2.7L16.5 9"/>',
    "chevron-down": '<path d="m6 9 6 6 6-6"/>',
    "chevron-right": '<path d="m9 6 6 6-6 6"/>',
    "chevron-up": '<path d="m6 15 6-6 6 6"/>',
    "clock": '<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',
    "close": '<path d="M6 6l12 12M18 6 6 18"/>',
    "contacts": '<rect x="5" y="3" width="15" height="18" rx="2"/><path d="M5 7H3m2 5H3m2 5H3"/><circle cx="12.5" cy="9" r="2.2"/><path d="M9 17a3.5 3.5 0 0 1 7 0"/>',
    "diamond": '<path d="m12 3 8 7-8 11-8-11 8-7Zm-8 7h16M9 3l-2 7 5 11 5-11-2-7"/>',
    "download": '<path d="M12 3v12m-5-5 5 5 5-5M4 19h16"/>',
    "edit": '<path d="M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L8 18l-4 1 1-4L16.5 3.5Z"/>',
    "external": '<path d="M14 4h6v6M20 4 11 13M20 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h5"/>',
    "file": '<path d="M6 2h8l5 5v15H6V2Z"/><path d="M14 2v6h5M9 13h6M9 17h6"/>',
    "files": '<path d="M8 2h8l4 4v13H8V2Z"/><path d="M16 2v5h4M5 6H4v16h12v-1"/>',
    "fire": '<path d="M13 22c4 0 7-3 7-7 0-5-4-7-5-11-2 1-3 3-3 5-2-1-3-2-3-4-3 2-5 5-5 9 0 5 4 8 9 8Z"/><path d="M9 18c0-2 1-3 3-5 2 2 3 3 3 5a3 3 0 0 1-6 0Z"/>',
    "gift": '<rect x="3" y="9" width="18" height="12" rx="2"/><path d="M12 9v12M3 13h18M7.5 9C5 9 4 7.8 4 6.5S5.1 4 6.5 4C9 4 12 9 12 9M16.5 9C19 9 20 7.8 20 6.5S18.9 4 17.5 4C15 4 12 9 12 9"/>',
    "globe": '<circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a15 15 0 0 1 0 18M12 3a15 15 0 0 0 0 18"/>',
    "handshake": '<path d="m8 12 3-3a2 2 0 0 1 3 0l2 2M3 8l4-4 4 3M21 8l-4-4-3 3M7 15l4 4a2 2 0 0 0 3 0l4-4M9 13l4 4M12 11l4 4"/>',
    "heart": '<path d="M20.8 5.8a5.5 5.5 0 0 0-7.8 0L12 6.8l-1-1a5.5 5.5 0 0 0-7.8 7.8L12 22l8.8-8.4a5.5 5.5 0 0 0 0-7.8Z"/>',
    "id": '<rect x="3" y="5" width="18" height="14" rx="2"/><circle cx="8" cy="11" r="2"/><path d="M5.5 16a3 3 0 0 1 5 0M13 10h5M13 14h5"/>',
    "inbox": '<path d="M4 4h16v16H4V4Zm0 11h5l2 3h2l2-3h5"/>',
    "infinite": '<path d="M8.5 8c-3 0-5 1.8-5 4s2 4 5 4c3.5 0 5.5-8 9-8 2 0 3.5 1.8 3.5 4s-1.5 4-3.5 4c-3.5 0-5.5-8-9-8Z"/>',
    "info": '<circle cx="12" cy="12" r="9"/><path d="M12 11v6M12 7h.01"/>',
    "key": '<circle cx="8" cy="15" r="4"/><path d="m11 12 9-9M16 4l4 4M14 6l2 2"/>',
    "lightbulb": '<path d="M9 18h6M10 22h4M8.5 16a7 7 0 1 1 7 0c-.8.6-1 1.1-1 2h-5c0-.9-.2-1.4-1-2Z"/>',
    "live": '<circle cx="12" cy="12" r="3"/><path d="M6.3 6.3a8 8 0 0 0 0 11.4M17.7 6.3a8 8 0 0 1 0 11.4M3.5 3.5a12 12 0 0 0 0 17M20.5 3.5a12 12 0 0 1 0 17"/>',
    "lock": '<rect x="5" y="10" width="14" height="10" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3M12 14v2"/>',
    "mail": '<rect x="3" y="5" width="18" height="14" rx="2"/><path d="m4 7 8 6 8-6"/>',
    "medal": '<circle cx="12" cy="14" r="6"/><path d="m8 2 4 6 4-6M9.5 14l1.5 1.5 3-3"/>',
    "money": '<circle cx="12" cy="12" r="9"/><path d="M16 8h-6a2 2 0 0 0 0 4h4a2 2 0 0 1 0 4H8M12 6v12"/>',
    "package": '<path d="m12 2 9 5-9 5-9-5 9-5Z"/><path d="m3 7 9 5 9-5M3 7v10l9 5 9-5V7M12 12v10"/>',
    "palette": '<path d="M12 3a9 9 0 0 0 0 18h1.5a2 2 0 0 0 0-4H12a1.5 1.5 0 0 1 0-3h3a6 6 0 0 0 6-6c0-3-4-5-9-5Z"/><path d="M7 9h.01M10 6h.01M15 6h.01M18 9h.01"/>',
    "pause": '<path d="M8 5v14M16 5v14"/>',
    "phone": '<path d="M7 3H4a2 2 0 0 0-2 2c0 9.4 7.6 17 17 17a2 2 0 0 0 2-2v-3l-5-1-1.2 3a15 15 0 0 1-9.8-9.8L8 8 7 3Z"/>',
    "pin": '<path d="M20 10c0 5-8 12-8 12S4 15 4 10a8 8 0 1 1 16 0Z"/><circle cx="12" cy="10" r="2.5"/>',
    "plane": '<path d="m21 3-9 9M21 3l-7 18-2-8-8-2 17-8Z"/>',
    "play": '<circle cx="12" cy="12" r="9"/><path d="m10 8 6 4-6 4V8Z"/>',
    "refresh": '<path d="M20 11a8 8 0 1 0 2 5.3M20 4v7h-7"/>',
    "rocket": '<path d="M14 4c3-2 5-2 6-2 0 1 0 3-2 6l-6 6-4-4 6-6Z"/><path d="m8 10-4 1-2 3 6 1m6-1 1 6 3-2 1-4M7 17l-3 3M9 19l-2 3"/><circle cx="15.5" cy="6.5" r="1.5"/>',
    "scissors": '<circle cx="6" cy="7" r="3"/><circle cx="6" cy="17" r="3"/><path d="m8.5 8.5 11 7.5M8.5 15.5 19.5 8"/>',
    "search": '<circle cx="11" cy="11" r="7"/><path d="m20 20-4-4"/>',
    "settings": '<circle cx="12" cy="12" r="3"/><path d="M12 3v2M12 19v2M5.6 5.6 7 7M17 17l1.4 1.4M3 12h2M19 12h2M5.6 18.4 7 17M17 7l1.4-1.4"/>',
    "shield": '<path d="M12 2 20 5v6c0 5-3.4 9-8 11-4.6-2-8-6-8-11V5l8-3Z"/><path d="m8.5 12 2.2 2.2 4.8-5"/>',
    "shopping-bag": '<path d="M5 8h14l1 13H4L5 8Z"/><path d="M9 9V6a3 3 0 0 1 6 0v3"/>',
    "sleep": '<path d="M5 7h6l-6 6h6M13 11h6l-6 6h6"/>',
    "sparkle": '<path d="M12 2c.7 5 2 6.3 7 7-5 .7-6.3 2-7 7-.7-5-2-6.3-7-7 5-.7 6.3-2 7-7ZM19 16c.3 2.2.8 2.7 3 3-2.2.3-2.7.8-3 3-.3-2.2-.8-2.7-3-3 2.2-.3 2.7-.8 3-3Z"/>',
    "star": '<path d="m12 3 2.8 5.7 6.2.9-4.5 4.4 1.1 6.2-5.6-3-5.6 3 1.1-6.2L3 9.6l6.2-.9L12 3Z"/>',
    "stop": '<rect x="5" y="5" width="14" height="14" rx="2"/>',
    "store": '<path d="M3.5 9.5 5 4.5h14l1.5 5"/><path d="M3.5 9.5a2.6 2.6 0 0 0 5.2 0 2.6 2.6 0 0 0 5.2 0 2.6 2.6 0 0 0 5.2 0M5 12v8h14v-8M9.5 20v-5h5v5"/>',
    "tag": '<path d="M20 13 12 21 3 12V3h9l8 8a1.4 1.4 0 0 1 0 2Z"/><circle cx="8" cy="8" r="1.3"/>',
    "target": '<circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="5"/><circle cx="12" cy="12" r="1"/>',
    "thumb-up": '<path d="M7 10v11H3V10h4Zm0 9h9a3 3 0 0 0 3-2.5l1-6A2 2 0 0 0 18 8h-5l1-4c.3-1.4-1.5-2.2-2.3-1L7 10"/>',
    "timer": '<circle cx="12" cy="13" r="8"/><path d="M12 13V9M9 2h6M17.5 6.5 19 5"/>',
    "trash": '<path d="M4 7h16M9 7V4h6v3m-9 0 1 14h10l1-14M10 11v6m4-6v6"/>',
    "tools": '<path d="m14 7 3-3a4 4 0 0 1-5 5L5 16l3 3 7-7a4 4 0 0 1 5-5l-3 3-3-3Z"/><path d="m4 4 4 4"/>',
    "trend": '<path d="M3 18 9 12l4 4 8-10M15 6h6v6"/>',
    "upload": '<path d="M12 16V4m-5 5 5-5 5 5M4 20h16"/>',
    "user": '<circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/>',
    "users": '<circle cx="8" cy="8" r="3"/><circle cx="17" cy="9" r="2.5"/><path d="M3 20a5 5 0 0 1 10 0M14 20a4 4 0 0 1 7 0"/>',
    "video": '<rect x="3" y="5" width="14" height="14" rx="2"/><path d="m17 10 4-3v10l-4-3"/>',
    "warning": '<path d="M12 3 2.5 20h19L12 3Z"/><path d="M12 9v5M12 17h.01"/>',
    "wave": '<path d="M7 11V6a2 2 0 0 1 4 0v3-5a2 2 0 0 1 4 0v5-3a2 2 0 0 1 4 0v8c0 5-3 8-8 8-3 0-5-1-7-4l-2-3a2 2 0 0 1 3-2l2 2v-4Z"/>',
  });

  const GLYPHS = Object.freeze({
    "✅":"check", "✓":"check", "✔":"check", "❌":"close", "✕":"close", "✖":"close", "×":"close", "🚫":"block",
    "⚠️":"warning", "⚠":"warning", "🚨":"warning", "⛔":"block", "⏳":"clock", "⌛":"clock", "🕗":"clock", "🕒":"clock", "🕐":"clock",
    "▶":"play", "◀":"arrow-left", "⏹":"stop", "⏹️":"stop", "⏸️":"pause", "▾":"chevron-down", "⌄":"chevron-down", "▼":"chevron-down", "⌃":"chevron-up", "▲":"chevron-up",
    "✦":"sparkle", "✨":"sparkle", "◆":"diamond", "💎":"diamond", "ⓘ":"info", "ℹ️":"info",
    "↻":"refresh", "⟳":"refresh", "🔄":"refresh", "→":"arrow-right", "←":"arrow-left", "↗":"external", "↔":"arrows-horizontal", "↕":"arrows-vertical", "↑":"arrow-up", "↓":"arrow-down", "⬆️":"upload", "⬇":"download", "📥":"download", "🔎":"search", "👈":"arrow-left", "👉":"arrow-right",
    "👥":"users", "👤":"user", "🧑":"user", "🏪":"store", "🏢":"building", "📦":"package", "🛍":"shopping-bag", "🛍️":"shopping-bag", "🏷️":"tag",
    "📇":"contacts", "💬":"chat", "✉️":"mail", "📞":"phone", "📨":"inbox", "💌":"inbox", "🔔":"bell",
    "📄":"file", "📑":"files", "📋":"file", "📝":"edit", "📘":"book", "📖":"book", "🔖":"bookmark", "🆔":"id", "🔗":"external",
    "📅":"calendar", "📆":"calendar", "⏰":"alarm", "⏱":"timer", "⏱️":"timer", "📍":"pin", "🔑":"key", "🔒":"lock", "🛡️":"shield",
    "💰":"money", "💵":"money", "💳":"card", "🎁":"gift", "📣":"announcement", "📢":"announcement", "💡":"lightbulb",
    "🎯":"target", "👍":"thumb-up", "⭐":"star", "🔥":"fire", "🤝":"handshake", "🎬":"video", "🔴":"live", "📈":"trend", "📷":"camera", "🏅":"medal",
    "🚀":"rocket", "✈":"plane", "🗑️":"trash", "✂️":"scissors", "⚡":"bolt", "⚙":"settings", "⚙️":"settings", "🔧":"tools", "🎨":"palette", "🌐":"globe", "🪐":"globe",
    "🎉":"celebration", "👋":"wave", "💤":"sleep", "♾":"infinite", "❤":"heart", "💜":"heart",
  });

  // Mot so glyph la ky hieu ngon ngu hop le. Chi thay khi no dung nhu icon trong control
  // hoac dung tach rieng; khong bien doi dau mui ten trong cac cau huong dan.
  const CONTEXTUAL = new Set(["×", "→", "←", "↔", "↕", "↑", "↓"]);
  const SKIP_TAGS = new Set(["SCRIPT", "STYLE", "TEXTAREA", "OPTION", "CODE", "PRE", "SVG", "TITLE"]);
  const graphemes = typeof Intl?.Segmenter === "function"
    ? value => Array.from(new Intl.Segmenter("vi", { granularity: "grapheme" }).segment(value), item => item.segment)
    : value => Array.from(value);

  function markup(name, className = "") {
    const body = ICONS[name] || ICONS.info;
    const classes = `stonk-icon${className ? ` ${String(className).replace(/[^a-z0-9_-]/gi, "")}` : ""}`;
    return `<svg class="${classes}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${body}</svg>`;
  }

  function create(name, glyph = "") {
    const template = document.createElement("template");
    template.innerHTML = markup(name);
    const icon = template.content.firstElementChild;
    if (glyph) icon.dataset.stonkGlyph = glyph;
    return icon;
  }

  function isControl(parent) {
    return !!parent?.closest?.("button,a,summary,label,[role='button'],[role='tab'],[role='menuitem']");
  }

  function shouldReplaceGlyph(glyph, text, parent) {
    if (!GLYPHS[glyph]) return false;
    if (!CONTEXTUAL.has(glyph)) return true;
    const trimmed = String(text || "").trim();
    return trimmed === glyph || trimmed.startsWith(`${glyph} `) || trimmed.endsWith(` ${glyph}`) || isControl(parent);
  }

  function upgradeTextNode(node) {
    const parent = node?.parentElement;
    if (!parent || SKIP_TAGS.has(parent.tagName) || parent.closest("[data-stonk-icons='off'],.avatar-preset-btn")) return;
    const parts = graphemes(node.data || "");
    if (!parts.some(part => shouldReplaceGlyph(part, node.data, parent))) return;
    const fragment = document.createDocumentFragment();
    let buffer = "";
    const flush = () => { if (buffer) { fragment.append(document.createTextNode(buffer)); buffer = ""; } };
    for (const part of parts) {
      if (!shouldReplaceGlyph(part, node.data, parent)) { buffer += part; continue; }
      flush();
      fragment.append(create(GLYPHS[part], part));
    }
    flush();
    node.replaceWith(fragment);
  }

  function stripLeadingGlyph(value) {
    const parts = graphemes(String(value || ""));
    let changed = false;
    while (parts.length && (!parts[0].trim() || GLYPHS[parts[0]])) {
      if (GLYPHS[parts[0]]) changed = true;
      parts.shift();
    }
    return changed ? parts.join("").trimStart() : String(value || "");
  }

  function sanitizeNativeElement(element) {
    if (!(element instanceof Element)) return;
    if (element.tagName === "OPTION") {
      const clean = stripLeadingGlyph(element.textContent);
      if (clean !== element.textContent) element.textContent = clean;
    }
    if (element instanceof HTMLInputElement && element.placeholder) {
      const first = graphemes(element.placeholder.trimStart())[0];
      const iconName = GLYPHS[first];
      const clean = stripLeadingGlyph(element.placeholder);
      if (clean !== element.placeholder) {
        element.placeholder = clean;
        if (iconName === "search") element.dataset.stonkInputIcon = "search";
      }
    }
  }

  function hydratePlaceholders(root) {
    const nodes = [];
    if (root instanceof Element && root.hasAttribute("data-stonk-icon")) nodes.push(root);
    if (root.querySelectorAll) nodes.push(...root.querySelectorAll("[data-stonk-icon]"));
    for (const element of nodes) {
      if (element.querySelector(":scope > svg.stonk-icon")) continue;
      element.prepend(create(String(element.dataset.stonkIcon || "info")));
    }
  }

  function hydrate(root = document) {
    if (!root) return;
    hydratePlaceholders(root);
    const nativeNodes = [];
    if (root instanceof Element && (root.tagName === "OPTION" || root instanceof HTMLInputElement)) nativeNodes.push(root);
    if (root.querySelectorAll) nativeNodes.push(...root.querySelectorAll("option,input[placeholder]"));
    nativeNodes.forEach(sanitizeNativeElement);
    if (root.nodeType === Node.TEXT_NODE) { upgradeTextNode(root); return; }
    const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
    const textNodes = [];
    while (walker.nextNode()) textNodes.push(walker.currentNode);
    textNodes.forEach(upgradeTextNode);
  }

  let pendingRoots = new Set();
  let scheduled = false;
  function schedule(root) {
    pendingRoots.add(root?.nodeType === Node.TEXT_NODE ? root : (root || document));
    if (scheduled) return;
    scheduled = true;
    queueMicrotask(() => {
      scheduled = false;
      const batch = Array.from(pendingRoots);
      pendingRoots = new Set();
      batch.forEach(hydrate);
    });
  }

  function start() {
    hydrate(document);
    const observer = new MutationObserver(records => {
      for (const record of records) {
        if (record.type === "characterData") {
          sanitizeNativeElement(record.target.parentElement);
          schedule(record.target);
        }
        else if (record.type === "attributes") sanitizeNativeElement(record.target);
        else {
          sanitizeNativeElement(record.target);
          record.addedNodes.forEach(schedule);
        }
      }
    });
    observer.observe(document.documentElement, {
      subtree: true,
      childList: true,
      characterData: true,
      attributes: true,
      attributeFilter: ["placeholder"],
    });
  }

  global.StonkIcons = Object.freeze({ ICONS, GLYPHS, create, hydrate, markup });
  if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start, { once: true });
  else start();
})(globalThis);
