import { createElement, updateCSSText } from '@syncfusion/ej2-base';
import { ContentType } from '../../models/enums';
/**
 * Finds the closest parent element that matches the specified selector.
 *
 * @param {Node | HTMLElement} element - The starting element
 * @param {string} selector - The CSS selector to match
 * @returns {HTMLElement | null} The closest matching parent element or null if not found
 */
export function findClosestParent(element, selector) {
    if (element.nodeType === Node.TEXT_NODE) {
        return element.parentElement.closest(selector) || null;
    }
    return element.closest(selector);
}
/**
 * Gets the computed absolute position of an element relative to the document.
 *
 * @param {HTMLElement} element - The element to get the position for
 * @returns {DOMRect} The element's position and dimensions
 */
export function getElementRect(element) {
    return element.getBoundingClientRect();
}
/**
 * Checks if a node is contained within a container element.
 *
 * @param {Node} node - The node to check
 * @param {HTMLElement} container - The container element
 * @returns {boolean} True if the node is inside the container, false otherwise
 */
export function isNodeInsideElement(node, container) {
    while (node) {
        if (node === container) {
            return true;
        }
        node = node.parentNode;
    }
    return false;
}
/**
 * Renders the given string in a temp element and returns the Dom text node.
 *
 * @param {string} content - The content to render
 * @returns {Node} - Rendered dom text node
 */
export function getDomTextNode(content) {
    var temp = document.createElement('div');
    temp.innerHTML = content;
    return temp.childNodes[0];
}
/**
 * Creates formatting element based on the content model.
 *
 * @param {ContentModel} content - Content model.
 * @param {string | LinkData} value - Value to be set for the content.
 * @returns {HTMLElement} - Returns the formatted element.
 *
 */
export function createFormattingElement(content, value) {
    var isInlineCode = content.properties.styles.inlineCode;
    var textNode = document.createTextNode(content.content);
    var isLinkType = content.contentType === ContentType.Link;
    var styles = content.properties.styles || {};
    var keys = Object.keys(styles);
    // For code: preserve raw entities (&lt;, &gt;, &nbsp;, etc.)
    // For normal text: decode entities (allow &nbsp; → space)
    var formattedElement = isInlineCode ? (textNode) : (getDomTextNode(content.content) || textNode);
    if (keys.length > 0) {
        for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
            var styleType = keys_1[_i];
            switch (styleType.toLowerCase()) {
                case 'bold':
                    formattedElement = wrapNodeWithTag(formattedElement, 'strong');
                    break;
                case 'italic':
                    formattedElement = wrapNodeWithTag(formattedElement, 'em');
                    break;
                case 'underline':
                    formattedElement = wrapNodeWithTag(formattedElement, 'u');
                    break;
                case 'strikethrough':
                    formattedElement = wrapNodeWithTag(formattedElement, 's');
                    break;
                case 'subscript':
                    formattedElement = wrapNodeWithTag(formattedElement, 'sub');
                    break;
                case 'superscript':
                    formattedElement = wrapNodeWithTag(formattedElement, 'sup');
                    break;
                case 'inlinecode':
                    formattedElement = wrapNodeWithTag(formattedElement, 'code');
                    formattedElement.className = 'e-be-inline-code';
                    break;
                case 'color':
                case 'backgroundcolor':
                case 'uppercase':
                case 'lowercase':
                    {
                        var val = styles[styleType];
                        formattedElement = wrapNodeWithSpan(formattedElement, styleType, val);
                    }
                    break;
            }
        }
    }
    else if (!isLinkType) {
        // No style applied, wrap in <span>
        formattedElement = wrapNodeWithSpan(formattedElement, '', '');
    }
    if (isLinkType) {
        var linkData = value;
        var props = content.properties;
        formattedElement = wrapNodeWithTag(formattedElement, (linkData && linkData.shouldRemoveLink) ? 'span' : 'a');
        if (linkData && !linkData.shouldRemoveLink) {
            formattedElement.href = props.url;
            formattedElement.target = '_blank';
            formattedElement.title = linkData.title
                ? linkData.title
                : props.url;
        }
    }
    formattedElement.id = content.id;
    return formattedElement;
}
/**
 * Wraps a node with a specified HTML tag.
 *
 * @param {Node} node - The node to wrap
 * @param {string} tagName - The HTML tag to wrap with
 * @returns {HTMLElement} The created wrapper element
 */
export function wrapNodeWithTag(node, tagName) {
    var el = createElement(tagName);
    el.appendChild(node);
    return el;
}
/**
 * Wraps a node with a span and applies the specified style.
 *
 * @param {Node} node - The node to wrap
 * @param {string} styleType - The type of style to apply
 * @param {string | boolean} value - The style value
 * @returns {HTMLElement} The created span element
 */
export function wrapNodeWithSpan(node, styleType, value) {
    var span = createElement('span');
    switch (styleType.toLowerCase()) {
        case 'color':
            updateCSSText(span, "color: " + value + ";");
            break;
        case 'backgroundcolor':
            updateCSSText(span, "background-color: " + value + ";");
            break;
        case 'uppercase':
            updateCSSText(span, "text-transform: " + (value ? 'uppercase' : 'none') + ";");
            break;
        case 'lowercase':
            updateCSSText(span, "text-transform: " + (value ? 'lowercase' : 'none') + ";");
            break;
    }
    span.appendChild(node);
    return span;
}
/**
 * Removes all break tags from an HTML element.
 *
 * @param {HTMLElement} element - The element to clean
 * @returns {void}
 */
export function clearBreakTags(element) {
    element.innerHTML = element.innerHTML.replace(/<br>/g, '').trim();
}
/**
 * Checks if an element is empty (contains only whitespace or a single <br> tag).
 *
 * @param {HTMLElement} element - The element to check
 * @returns {boolean} True if the element is empty, false otherwise
 */
export function isElementEmpty(element) {
    return element.innerText.trim() === '' || element.innerHTML === '<br>';
}
