// #region Imports
// #endregion
/**
 * Abstract class RichTextCommand that provides common functionality for text commands.
 *
 * @public
 */
export class RichTextCommand {
    // #region Fields
    _contentEditable;
    // #endregion
    // #region Ctor
    /**
     * Constructs a new instance of the `RichTextCommand` class.
     *
     * @protected
     */
    constructor() {
        this._contentEditable = null;
    }
    // #endregion
    // #region Properties
    /**
     * Gets the content editable element.
     *
     * @protected
     */
    get contentEditable() {
        return this._contentEditable;
    }
    // #endregion
    // #region Methods
    /**
     * Attaches the command to a content editable.
     *
     * @public
     * @param contentEditable - The HTMLTextAreaElement to attach the command to.
     */
    attach(contentEditable) {
        this._contentEditable = contentEditable;
    }
    /**
     * Toggles the selected text with the specified tag and delimiter.
     *
     * @protected
     * @param tagName - The tag name to wrap the text.
     * @param delimiter - The delimiter to wrap the text.
     */
    toggleFormatting(tagName, delimiter) {
        const selection = window.getSelection();
        if (!selection || selection.rangeCount === 0) {
            console.warn('No selection or range count is zero.');
            return false;
        }
        const range = selection.getRangeAt(0);
        console.log('Range start:', range.startContainer, 'Range end:', range.endContainer);
        if (range.collapsed) {
            console.warn('The range is collapsed.');
            return false;
        }
        const selectedText = range.toString();
        if (this.isRangeEnclosedBy(tagName, delimiter)) {
            this.unwrapSelection(tagName, delimiter);
        }
        else {
            this.wrapSelection(tagName, delimiter, selectedText);
        }
        return true;
    }
    /**
     * Checks if the selected range is fully enclosed within a specific tag and delimiter.
     *
     * @protected
     * @param tagName - The tag name to check.
     * @param delimiter - The delimiter to check.
     */
    isRangeEnclosedBy(tagName, delimiter) {
        const selection = window.getSelection();
        if (!selection || selection.rangeCount === 0) {
            return false;
        }
        const range = selection.getRangeAt(0);
        if (range.collapsed) {
            return false;
        }
        const container = range.commonAncestorContainer;
        const parent = container.nodeType === Node.TEXT_NODE ? container.parentNode : container;
        const textContent = parent.textContent || '';
        return parent.tagName.toLowerCase() === tagName && textContent.startsWith(delimiter) && textContent.endsWith(delimiter);
    }
    /**
     * Wraps the selected text with the specified tag and delimiter.
     *
     * @protected
     * @param tagName - The tag name to wrap the text with.
     * @param delimiter - The delimiter to wrap the text with.
     * @param text - The selected text to wrap.
     */
    wrapSelection(tagName, delimiter, text) {
        const selection = window.getSelection();
        const range = selection?.getRangeAt(0);
        if (!range) {
            return;
        }
        const wrapper = document.createElement(tagName);
        const startDelimiter = document.createElement('span');
        startDelimiter.style.color = 'red'; // TODO: fix color
        startDelimiter.textContent = delimiter;
        const endDelimiter = document.createElement('span');
        endDelimiter.style.color = 'red'; // TODO: fix color
        endDelimiter.textContent = delimiter;
        wrapper.appendChild(document.createTextNode(text));
        range.deleteContents();
        range.insertNode(wrapper);
        wrapper.insertAdjacentElement('beforebegin', startDelimiter);
        wrapper.insertAdjacentElement('afterend', endDelimiter);
        // Adjust the selection to surround the new element
        selection?.removeAllRanges();
        const newRange = document.createRange();
        newRange.selectNodeContents(wrapper);
        selection?.addRange(newRange);
    }
    /**
     * Unwraps the selected text from the specified tag and delimiter.
     *
     * @protected
     * @param tagName - The tag name to unwrap the text from.
     * @param delimiter - The delimiter to unwrap the text from.
     */
    unwrapSelection(tagName, delimiter) {
        const selection = window.getSelection();
        const range = selection?.getRangeAt(0);
        if (!range) {
            return;
        }
        const container = range.commonAncestorContainer;
        const parent = container.nodeType === Node.TEXT_NODE ? container.parentNode : container;
        if (parent.tagName.toLowerCase() === tagName) {
            const textContent = parent.textContent || '';
            if (textContent.startsWith(delimiter) && textContent.endsWith(delimiter)) {
                const innerText = textContent.slice(delimiter.length, -delimiter.length);
                range.deleteContents();
                range.insertNode(document.createTextNode(innerText));
                parent.parentNode?.removeChild(parent.previousSibling);
                parent.parentNode?.removeChild(parent.nextSibling);
                parent.parentNode?.removeChild(parent);
                // Adjust the selection to surround the unwrapped contents
                selection?.removeAllRanges();
                const newRange = document.createRange();
                newRange.selectNodeContents(range.commonAncestorContainer);
                selection?.addRange(newRange);
            }
        }
    }
}
//# sourceMappingURL=RichTextCommand.js.map