// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { assert } from 'chrome://resources/js/assert.js';
import { loadTimeData } from 'chrome://resources/js/load_time_data.js';
import { createEmptySearchBubble, highlight, stripDiacritics } from 'chrome://resources/js/search_highlight_utils.js';
/**
 * @param element The element to update. Element should have a shadow root.
 * @param query The current search query
 * @param bubbles A map of bubbles created / results found so far.
 * @return The highlight wrappers that were created.
 */
export function updateHighlights(element, query, bubbles) {
    const highlights = [];
    if (!query) {
        return highlights;
    }
    assert(query.global);
    element.shadowRoot.querySelectorAll('.searchable').forEach(childElement => {
        childElement.childNodes.forEach(node => {
            if (node.nodeType !== Node.TEXT_NODE) {
                return;
            }
            const textContent = node.nodeValue;
            if (textContent.trim().length === 0) {
                return;
            }
            const strippedText = stripDiacritics(textContent);
            const ranges = [];
            for (let match; match = query.exec(strippedText);) {
                ranges.push({ start: match.index, length: match[0].length });
            }
            if (ranges.length > 0) {
                // Don't highlight <select> nodes, yellow rectangles can't be
                // displayed within an <option>.
                if (node.parentNode.nodeName === 'OPTION') {
                    // The bubble should be parented by the select node's parent.
                    // Note: The bubble's ::after element, a yellow arrow, will not
                    // appear correctly in print preview without SPv175 enabled. See
                    // https://crbug.com/40564920.
                    // TODO(crbug.com/40666299): turn on horizontallyCenter when we fix
                    // incorrect positioning caused by scrollbar width changing after
                    // search finishes.
                    assert(node.parentNode);
                    assert(node.parentNode.parentNode);
                    const bubble = createEmptySearchBubble(node.parentNode.parentNode, 
                    /* horizontallyCenter= */ false);
                    const numHits = ranges.length + (bubbles.get(bubble) || 0);
                    bubbles.set(bubble, numHits);
                    const msgName = numHits === 1 ? 'searchResultBubbleText' :
                        'searchResultsBubbleText';
                    bubble.firstChild.textContent =
                        loadTimeData.getStringF(msgName, numHits);
                }
                else {
                    highlights.push(highlight(node, ranges));
                }
            }
        });
    });
    return highlights;
}
