/*
** Copyright (C) 2021-2026 initMAX s.r.o.
**
** This program is free software: you can redistribute it and/or modify it under the terms of
** the GNU Affero General Public License as published by the Free Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
** without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
** See the GNU Affero General Public License for more details.
**
** You should have received a copy of the GNU Affero General Public License along with this program.
** If not, see <https://www.gnu.org/licenses/>.
**/

/**
 * Colour tags on Zabbix 6.0 - 6.4.
 *
 * From 7.0 a tag carries its full text in `data-hintbox-contents`, and the
 * colour rules are pure CSS attribute selectors matching on that - no
 * JavaScript at all. Before 7.0, CTag::setHint() nested a
 * `<div class="hint-box">` instead and set NO attribute, so those selectors
 * match nothing and the feature is silently dead.
 *
 * This script exists only to close that gap: it copies the tag's full text into
 * `data-uxmax-tag`, which the generated stylesheet also matches on. The module
 * loads it ONLY when the frontend was probed as lacking the attribute, so 7.x
 * keeps working with no client-side code and no MutationObserver running on
 * every page.
 *
 * The text is taken from the hint box when there is one: the visible label is
 * truncated ("web: prod…") while the hint holds the whole "tag: value" string,
 * and a rule written against the whole string has to match the whole string.
 */
(function () {
    var ATTRIBUTE = 'data-uxmax-tag';

    function stamp(element) {
        var hint = element.querySelector('.hint-box');
        var text = (hint !== null ? hint.textContent : element.textContent) || '';

        text = text.trim();

        if (text !== '' && element.getAttribute(ATTRIBUTE) !== text) {
            element.setAttribute(ATTRIBUTE, text);
        }
    }

    function stampAll(root) {
        if (!root || typeof root.querySelectorAll !== 'function') {
            return;
        }

        if (typeof root.matches === 'function' && root.matches('.tag')) {
            stamp(root);
        }

        Array.prototype.forEach.call(root.querySelectorAll('.tag'), stamp);
    }

    function start() {
        stampAll(document.body);

        // Tags arrive with every table refresh, hint box and popup, so a single
        // pass at load time would colour the first render and nothing after it.
        new MutationObserver(function (mutations) {
            for (var i = 0; i < mutations.length; i++) {
                var added = mutations[i].addedNodes;

                for (var j = 0; j < added.length; j++) {
                    if (added[j].nodeType === 1) {
                        stampAll(added[j]);
                    }
                }
            }
        }).observe(document.body, {childList: true, subtree: true});
    }

    // The v1 (6.0/6.2) package injects its scripts from the page footer, by
    // which time DOMContentLoaded may already have fired - and a listener added
    // after the event never runs. Checking readyState is what makes the same
    // file work in both delivery models.
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', start);
    }
    else {
        start();
    }
})();
