import { generateUniqueId } from '../../../common/utils/common';
import * as constants from '../../../common/constant';
/**
 * Responsible for splitting DOM nodes
 *
 * @hidden
 */
var NodeCutter = /** @class */ (function () {
    function NodeCutter() {
    }
    /**
     * Splits the content of a block at a specified node and offset.
     *
     * @param {HTMLElement} contentElement - The content element of the block.
     * @param {Node} splitNode - The node at which to split the content.
     * @param {number} splitOffset - The offset within the split node at which to split the content.
     * @returns {ISplitContentData} - An object containing the before and after fragments of the split content.
     * @hidden
     */
    NodeCutter.splitContent = function (contentElement, splitNode, splitOffset) {
        var beforeFragment = document.createDocumentFragment();
        var afterFragment = document.createDocumentFragment();
        var isSplitting = false;
        var processNode = function (node, container, parentChain, isAfter) {
            if (parentChain === void 0) { parentChain = []; }
            if (isAfter === void 0) { isAfter = false; }
            if (node.nodeType === Node.TEXT_NODE) {
                var textNode = node;
                var fullText = textNode.textContent;
                if (!isAfter && node === splitNode) {
                    var beforeText = fullText.slice(0, splitOffset);
                    var afterText = fullText.slice(splitOffset);
                    if (beforeText) {
                        container.appendChild(document.createTextNode(beforeText));
                    }
                    if (afterText) {
                        // Build after tree from deepest to root
                        var afterNode = document.createTextNode(afterText);
                        for (var i = parentChain.length - 1; i >= 0; i--) {
                            var cloned = parentChain[i]
                                .cloneNode(false);
                            // Only re-generate id for the root node
                            if (i === 0) {
                                cloned.id = generateUniqueId(constants.CONTENT_ID_PREFIX);
                            }
                            cloned.appendChild(afterNode);
                            afterNode = cloned;
                        }
                        afterFragment.appendChild(afterNode);
                    }
                    isSplitting = true;
                }
                else {
                    container.appendChild(document.createTextNode(fullText));
                }
            }
            else if (node.nodeType === Node.ELEMENT_NODE) {
                var element = node;
                var clone = element.cloneNode(false);
                var newParentChain = parentChain.concat([element]);
                if (!isAfter && (element.contains(splitNode) || element === splitNode)) {
                    for (var _i = 0, _a = Array.from(element.childNodes); _i < _a.length; _i++) {
                        var child = _a[_i];
                        if (!isSplitting && (child.contains(splitNode) || child === splitNode)) {
                            processNode(child, clone, newParentChain);
                        }
                        else {
                            processNode(child, clone, newParentChain, isSplitting);
                        }
                    }
                    container.appendChild(clone);
                }
                else {
                    if (isAfter) {
                        container.appendChild(element.cloneNode(true));
                    }
                    else {
                        container.appendChild(clone);
                        for (var _b = 0, _c = Array.from(element.childNodes); _b < _c.length; _b++) {
                            var child = _c[_b];
                            processNode(child, clone, newParentChain, isAfter);
                        }
                    }
                }
            }
        };
        for (var _i = 0, _a = Array.from(contentElement.childNodes); _i < _a.length; _i++) {
            var node = _a[_i];
            if (!isSplitting) {
                processNode(node, beforeFragment, []);
            }
            else {
                afterFragment.appendChild(node.cloneNode(true));
            }
        }
        return { beforeFragment: beforeFragment, afterFragment: afterFragment, splitOffset: splitOffset };
    };
    return NodeCutter;
}());
export { NodeCutter };
