(function() {
  const docEl = document.getElementById('doc');
  const tocEl = document.getElementById('toc');
  const searchInput = document.getElementById('searchInput');

  // Gyldig regelmønster
  const ruleStartRe = /^(?<num>\d+\.\d+[a-z]?)\b/i;
  const ruleAnywhereRe = /\b(\d+\.\d+[a-z]?)\b/g;

  // Opprett ID for alle overskrifter som starter med regelnummer
  const headingSelector = 'h1, h2, h3, h4';
  const headings = Array.from(docEl.querySelectorAll(headingSelector));
  const ruleIndex = new Map();

  headings.forEach(h => {
    const text = h.textContent.trim();
    const m = text.match(ruleStartRe);
    if (m) {
      const ruleNum = m.groups.num.toLowerCase();
      const id = `r-${ruleNum}`;
      h.id = id;
      ruleIndex.set(ruleNum, h);
      const first = h.firstChild;
      if (first && first.nodeType === Node.TEXT_NODE) {
        const tn = first.textContent;
        const linked = tn.replace(ruleStartRe, (all, num) => {
          return `<a class="rule-link" href="#r-${num.toLowerCase()}">${num}</a>`;
        });
        const span = document.createElement('span');
        span.innerHTML = linked;
        h.replaceChild(span, first);
      }
    }
  });

  // Bygg TOC
  buildTOC(headings, tocEl);

  // Autolenk regelreferanser
  autoLinkRules(docEl, ruleIndex);

  // Søk + highlight + navigering
  setupSearch(searchInput, docEl);

  // --- helpers ---

  function buildTOC(headings, container) {
    const tree = [];
    headings.forEach(h => {
      const lvl = Number(h.tagName.substring(1));
      const text = h.textContent.trim();
      const id = h.id || '';
      const start = text.match(ruleStartRe);
      if (!start) return;
      const ruleNum = start.groups.num.toLowerCase();
      const hasLetter = /[a-z]$/.test(ruleNum);
      tree.push({ lvl, text, id, hasLetter });
    });

    container.innerHTML = '<h2>Table of Contents</h2>';
    const ul = document.createElement('ul');
    let stack = [{ ul, lvl: 1 }];

    tree.forEach(item => {
      const li = document.createElement('li');
      const a = document.createElement('a');
      a.href = `#${item.id}`;
      a.textContent = item.text;
      li.appendChild(a);
      li.classList.add(item.hasLetter ? 'toc-subletter' : 'toc-number');

      let current = stack[stack.length - 1];
      while (item.lvl > current.lvl + 1 && stack.length < 4) {
        const newUl = document.createElement('ul');
        current.ul.appendChild(newUl);
        stack.push({ ul: newUl, lvl: current.lvl + 1 });
        current = stack[stack.length - 1];
      }
      while (item.lvl < current.lvl) {
        stack.pop();
        current = stack[stack.length - 1];
      }
      current.ul.appendChild(li);
    });

    container.appendChild(ul);
  }

  function autoLinkRules(root, indexMap) {
    const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
      acceptNode(node) {
        const parent = node.parentNode;
        if (!parent) return NodeFilter.FILTER_REJECT;
        const tag = parent.tagName ? parent.tagName.toLowerCase() : '';
        if (['a','code','pre','script','style'].includes(tag)) {
          return NodeFilter.FILTER_REJECT;
        }
        const hasRule = ruleAnywhereRe.test(node.textContent);
        return hasRule ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
      }
    });

    const toProcess = [];
    while (walker.nextNode()) toProcess.push(walker.currentNode);

    toProcess.forEach(node => {
      const text = node.textContent;
      const replaced = text.replace(ruleAnywhereRe, (all, num) => {
        const key = num.toLowerCase();
        if (indexMap.has(key)) {
          return `<a class="rule-link" href="#r-${key}">${num}</a>`;
        }
        return num;
      });
      const span = document.createElement('span');
      span.innerHTML = replaced;
      node.parentNode.replaceChild(span, node);
    });
  }

  function setupSearch(input, root) {
    let lastQuery = '';
    let hits = [];
    let currentIndex = -1;

    // Opprett navigasjonsknapper
    const prevBtn = document.createElement('button');
    prevBtn.textContent = 'Previous';
    const nextBtn = document.createElement('button');
    nextBtn.textContent = 'Next';
    input.insertAdjacentElement('afterend', nextBtn);
    input.insertAdjacentElement('afterend', prevBtn);

    input.addEventListener('input', () => {
      const q = input.value.trim();
      if (q === lastQuery) return;
      lastQuery = q;
      clearHighlights(root);
      hits = [];
      currentIndex = -1;
      if (!q) return;

      const textNodes = textNodesIn(root);
      const needle = q.toLowerCase();

      textNodes.forEach(node => {
        const txt = node.textContent;
        const idx = txt.toLowerCase().indexOf(needle);
        if (idx >= 0) {
          const before = txt.slice(0, idx);
          const match = txt.slice(idx, idx + q.length);
          const after = txt.slice(idx + q.length);
          const frag = document.createElement('span');
          frag.innerHTML = `${escapeHtml(before)}<mark class="hit">${escapeHtml(match)}</mark>${escapeHtml(after)}`;
          node.parentNode.replaceChild(frag, node);
        }
      });

      hits = Array.from(root.querySelectorAll('mark.hit'));
      if (hits.length > 0) {
        currentIndex = 0;
        focusHit(hits[currentIndex]);
      }
    });

    nextBtn.addEventListener('click', () => {
      if (hits.length === 0) return;
      currentIndex = (currentIndex + 1) % hits.length;
      focusHit(hits[currentIndex]);
    });

    prevBtn.addEventListener('click', () => {
      if (hits.length === 0) return;
      currentIndex = (currentIndex - 1 + hits.length) % hits.length;
      focusHit(hits[currentIndex]);
    });

    function focusHit(el) {
      hits.forEach(h => h.classList.remove('active-hit'));
      el.classList.add('active-hit');
      el.scrollIntoView({behavior: 'smooth', block: 'center'});
    }
  }

  function textNodesIn(root) {
    const out = [];
    const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
      acceptNode(node) {
        const parent = node.parentNode;
        if (!parent) return NodeFilter.FILTER_REJECT;
        const tag = parent.tagName ? parent.tagName.toLowerCase() : '';
        if (['script','style'].includes(tag)) return NodeFilter.FILTER_REJECT;
        return NodeFilter.FILTER_ACCEPT;
      }
    });
    while (walker.nextNode()) out.push(walker.currentNode);
    return out;
  }

  function clearHighlights(root) {
    const marks = root.querySelectorAll('mark.hit');
    marks.forEach(mark => {
      const parent = mark.parentNode;
      parent.replaceChild(document.createTextNode(mark.textContent), mark);
      parent.normalize();
    });
  }

  function escapeHtml(s) {
    return s.replace(/[&<>"']/g, c => ({
      '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;'
    }[c]));
  }
})();