// #region Imports
import { render } from 'lit';
// #endregion
/**
 * @private
 */
const NAMESPACE_URIS = {
    svg: 'http://www.w3.org/2000/svg',
    xhtml: 'http://www.w3.org/1999/xhtml',
    xlink: 'http://www.w3.org/1999/xlink',
    xml: 'http://www.w3.org/XML/1998/namespace',
    xmlns: 'http://www.w3.org/2000/xmlns/',
    math: 'http://www.w3.org/1998/MathML/'
};
/**
 * The `Renderer` class.
 *
 * @public
 */
export class Renderer {
    // #region Fields
    static _document = document;
    // #endregion
    // #region Ctor
    /**
     * Constructs a new instance of the `Renderer` class.
     *
     * @public
     */
    constructor() {
    }
    // #endregion
    // #region Methods
    /**
     * @public
     */
    createElement(name) {
        return Renderer._document.createElement(name);
    }
    /**
     * @public
     */
    createComment(value) {
        return Renderer._document.createComment(value);
    }
    /**
     * @public
    */
    createText(value) {
        return Renderer._document.createTextNode(value);
    }
    /**
     * @public
     */
    appendChild(parent, newChild) {
        if (newChild instanceof Node) {
            return parent.appendChild(newChild);
        }
        const part = render(newChild, parent, {
            host: parent,
            isConnected: true
        });
        return part.parentNode;
    }
    /**
     * @public
     */
    insertBefore(parent, newChild, refChild, isMove) {
        if (isMove) {
            parent.removeChild(newChild);
        }
        parent.insertBefore(newChild, refChild);
    }
    /**
     * @public
     */
    insertAfter(newChild, refChild) {
        const parent = refChild.parentNode;
        if (parent) {
            const nextSibling = refChild.nextSibling;
            if (nextSibling) {
                parent.insertBefore(newChild, nextSibling);
            }
            else {
                parent.appendChild(newChild);
            }
        }
    }
    /**
     * @public
     */
    clear(parent) {
        while (parent.firstChild) {
            parent.removeChild(parent.firstChild);
        }
    }
    /**
     * @public
     */
    removeChild(parent, oldChild) {
        parent.removeChild(oldChild);
    }
    /**
    * @public
    */
    remove(node, parent) {
        if (parent) {
            parent.removeChild(node);
        }
        else {
            node.parentNode?.removeChild(node);
        }
    }
    /**
     * @public
     */
    selectRootElement(selectorOrNode, preserveContent) {
        let rootNode = null;
        if (typeof selectorOrNode === 'string') {
            rootNode = Renderer._document.querySelector(selectorOrNode);
            if (!rootNode) {
                throw new Error(`Unable to find root element with selector: "${selectorOrNode}"`);
            }
        }
        else {
            rootNode = selectorOrNode;
        }
        if (!preserveContent) {
            while (rootNode.firstChild) {
                rootNode.removeChild(rootNode.firstChild);
            }
        }
        return rootNode;
    }
    /**
     * @public
     */
    parentNode(node) {
        return node.parentNode;
    }
    /**
     * @public
     */
    nextSibling(node) {
        return node.nextSibling;
    }
    /**
     * @public
     */
    // Public setAttribute(el: Element, name: KebabCase<keyof ARIAMixin>, value: string | null): void;
    setAttribute(el, name, value, namespace) {
        if (namespace) {
            name = `${namespace}:${name}`;
            const namespaceUri = NAMESPACE_URIS[namespace];
            if (namespaceUri) {
                el.setAttributeNS(namespaceUri, name, value ?? '');
            }
            else {
                el.setAttribute(name, value ?? '');
            }
        }
        else {
            el.setAttribute(name, value ?? '');
        }
    }
    /**
     * @public
     */
    removeAttribute(el, name, namespace) {
        if (namespace) {
            const namespaceUri = NAMESPACE_URIS[namespace];
            if (namespaceUri) {
                el.removeAttributeNS(namespaceUri, name);
            }
            else {
                el.removeAttribute(`${namespace}:${name}`);
            }
        }
        else {
            el.removeAttribute(name);
        }
    }
    /**
     * Adds a class to the element event the class not exist.
     *
     * @public
     */
    addClass(e, name) {
        if (!e.classList.contains(name)) {
            e.classList.add(name);
        }
    }
    removeClass(e, name) {
        if (e.classList.contains(name)) {
            e.classList.remove(name);
        }
    }
    setStyle(e, style, value) {
        // eslint-disable-next-line no-restricted-syntax
        e.style.setProperty(style, String(value));
    }
    removeStyle(e, style) {
        // eslint-disable-next-line no-restricted-syntax
        e.style.removeProperty(style);
    }
    setProperty(el, name, value) {
        el.setAttribute(name, value);
    }
    setValue(node, value) {
        if (node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement || node instanceof HTMLSelectElement) {
            node.value = value;
        }
        else {
            throw new Error('The provided node is not an input, textarea, or select element.');
        }
    }
}
/**
 * @public
 */
export class RendererServiceLocator {
    // #region Fields
    static _current = null;
    // #endregion
    // #region Properties
    static get current() {
        if (!RendererServiceLocator.isSet()) {
            throw new Error('\'Renderer\' not set.');
        }
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        return RendererServiceLocator._current;
    }
    // #endregion
    // #region Methods
    static isSet() {
        return RendererServiceLocator._current !== null;
    }
    static set(current) {
        RendererServiceLocator._current = current;
    }
}
/**
 * @public
 */
RendererServiceLocator.set(new Renderer());
//# sourceMappingURL=Renderer.js.map