<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

/**
 * @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer
 * @var \Magento\Framework\Escaper $escaper
 */
?>

<?php $_divId = 'tree' . $block->getId() ?>
<div id="<?= $escaper->escapeHtmlAttr($_divId) ?>" class="tree"></div>
<?php
$isUseMassAction = $block->getUseMassaction() ? 1 : 0;
$isAnchorOnly = $block->getIsAnchorOnly() ? 1 : 0;
$scriptString = <<<script

require(['jquery', 'jquery/jstree/jquery.jstree'], function($) {

    let tree = $('#tree{$block->escapeJs($block->getId())}');
    let useMassAction = {$isUseMassAction};
    let isAnchorOnly = {$isAnchorOnly};
    let checkedNodes = [];

    function addLastNodeProperty(nodes) {
        return nodes.map(node => {
            return node.children
                ? { ...node, children: addLastNodeProperty(node.children) }
                : { ...node, lastNode: true };
        });
    }

    function actionBasedOnIsAnchorOnly() {
        tree.jstree().get_json('#', { flat: true }).each((node, value) => {
            const attrId = node.a_attr.id;
            const rootNode = tree.jstree().get_node("#");
            const rootId = rootNode.children[0];

            if (isAnchorOnly === 1 && node.id === rootId) {
                tree.jstree(true).disable_node(node);
            } else if (isAnchorOnly === 0 && node.id !== rootId) {
                tree.jstree(true).disable_node(node);
            }
        });
    }

    function handleLoadedTree(e, data) {
        const container = $(e.target).closest('div.chooser_container');
        checkedNodes = container.find('input[type="text"].entities').val().split(',').map(item => item.trim());

        data.instance.get_json('#', { flat: true }).forEach(nodeId => {
            const node = data.instance.get_node(nodeId);

            if (checkedNodes.includes(node.id)) {
                tree.jstree(true).select_node(node.id);
            }

            actionBasedOnIsAnchorOnly();
        });
    }

    function handleChange(e, data) {
        if (data.action === 'ready') {
            return;
        }

        if (useMassAction) {
            const clickedNodeID = data.node.id;
            const currentCheckedNodes = data.instance.get_checked();

            if (data.action === 'select_node' && !checkedNodes.includes(clickedNodeID)) {
                checkedNodes = currentCheckedNodes;
            } else if (data.action === 'deselect_node') {
                checkedNodes = currentCheckedNodes.filter(nodeID => nodeID !== clickedNodeID);
            }

            checkedNodes.sort((a, b) => a - b);

            const container = $(e.target).closest('div.chooser_container');
            container.find('input[type="text"].entities').val(checkedNodes.join(', '));
        } else {
            node = data.node;
            node.attributes = node.original;
            const nodeClickListener = {$block->getNodeClickListener()};
            nodeClickListener(node);
        }
    }

    function getCheckedNodeIds(tree, node) {
        if (node.children_d && node.children_d.length > 0) {
            const selectChildrenNodes = node.children_d.filter(item => checkedNodes.includes(item));

            if (selectChildrenNodes.length > 0) {
                tree.jstree(true).select_node(selectChildrenNodes);
            }
        }
    }

    function addLastNodeFlag(treeData) {
        if (treeData.children) {
            treeData.children.forEach(child => addLastNodeFlag(child));
        } else {
            treeData.lastNode = true;
        }
    }

    function handleSuccessResponse(response, childNode, data) {
        if (response.length > 0) {
            response.forEach(newNode => {
                addLastNodeFlag(newNode);

                // Create the new node and execute node callback
                data.instance.create_node(childNode, newNode, 'last', node => {
                    if (useMassAction) {
                        if (checkedNodes.includes(node.id)) {
                            tree.jstree(true).select_node(node.id);
                        }
                        getCheckedNodeIds(tree, node);
                        actionBasedOnIsAnchorOnly();
                    }
                });
            });
        }
    }

    function handleOpenNode(e, data) {
        let parentNode = data.node;
        if (parentNode && parentNode.children.length > 0) {
            parentNode.children.forEach(function(childId) {
                let childNode = data.instance.get_node(childId, false);
                // Check if the child node has no children (is not yet loaded)
                if (childNode.children && childNode.children.length === 0
                    && childNode.original && !childNode.original.lastNode) {
                    $.ajax({
                        url: '{$block->escapeJs($block->escapeUrl($block->getLoadTreeUrl()))}',
                        type: "POST",
                        data: {
                            id: childNode.original.id,
                            store: childNode.original.store,
                            form_key: FORM_KEY
                        },
                        dataType: 'json',
                        success: function (response) {
                            handleSuccessResponse(response, childNode, data);
                        },
                        error: function (jqXHR, status, error) {
                            console.log(status + ': ' + error + 'Response text:' + jqXHR.responseText);
                        }
                    });
                }
            })
        }
    }

    var jstreeConfig = {
        core: {
            data: addLastNodeProperty({$block->getTreeJson()}),
            check_callback: true
        },
        plugins: []
    };

    if (useMassAction) {
        jstreeConfig.plugins.push('checkbox');
        jstreeConfig.checkbox = {
            three_state: false
        };
    }

    tree.jstree(jstreeConfig);

    if (useMassAction) {
        tree.on('loaded.jstree', (e, data) => handleLoadedTree(e, data));
    }

    tree.on('changed.jstree', (e, data) => handleChange(e, data));
    tree.on('open_node.jstree', (e, data) => handleOpenNode(e, data));
});

script;
?>
<?= /* @noEscape */ $secureRenderer->renderStyleAsTag(
    'overflow-x: auto;',
    '#tree' . $escaper->escapeJs($block->getId())
);
?>
<?= /* @noEscape */ $secureRenderer->renderTag('script', [], $scriptString, false); ?>
