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

/** @var $block \Magento\Catalog\Block\Adminhtml\Category\Tree */
/** @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer */
?>
<?php $root = $block->getRoot(); ?>

<div class="categories-side-col">
    <div class="sidebar-actions">
        <?php if ($root):?>
            <?= $block->getAddRootButtonHtml() ?><br/>
            <?= $block->getAddSubButtonHtml() ?>
        <?php endif; ?>
    </div>
    <div class="tree-actions">
        <?php if ($root):?>
            <a id="colapseAll" href="#"><?= $block->escapeHtml(__('Collapse All')) ?></a>
            <span class="separator">|</span>
            <a id="expandAll" href="#"><?= $block->escapeHtml(__('Expand All')) ?></a>
        <?php endif; ?>
    </div>
    <?php if ($root):?>
        <?= /* @noEscape */ $secureRenderer->renderEventListenerAsTag(
            'onclick',
            'TreeConfig.collapseAll(); event.preventDefault();',
            '#colapseAll'
        ) ?>
        <?= /* @noEscape */ $secureRenderer->renderEventListenerAsTag(
            'onclick',
            'TreeConfig.expandAll();event.preventDefault();',
            '#expandAll'
        ) ?>
    <div class="tree-holder" >
        <div id="tree-div" class="tree-wrapper x-tree"></div>
    </div>
</div>

<div data-id="information-dialog-tree" class="messages">
    <div class="message message-notice">
        <div><?= $block->escapeHtml(__('This operation can take a long time')) ?></div>
    </div>
</div>

        <?= /* @noEscape */ $secureRenderer->renderStyleAsTag(
            'display: none;',
            'div[data-id="information-dialog-tree"]'
        ) ?>
        <?php $divElement = '<div id="tree-div" class="tree-wrapper x-tree"></div>'; ?>

        <?php $scriptString = <<<script
            let TreeConfig, expandAll = false;
            require([
                'jquery',
                'jquery/jstree/jquery.jstree'
            ], function($) {
                let registry = {
                    data: [],

                    set: function (key, value) {
                        this.data[key] = value;
                    },

                    get: function (key) {
                        return this.data[key];
                    }
                };

                let treeDiv = $('#tree-div'),
                treeInstance,
script;
        $scriptString .= 'currentNodeId = ' . (int)$block->getCategoryId() . ',

         defaultParams = {
                text: ' . /* @noEscape */ json_encode(htmlentities($root->getName())) . ',
                allowDrop: ' . ($root->getIsVisible() ? 'true' : 'false') . ',
                id: ' . (int)$root->getId() . ',
                expanded: ' . (int)$block->getIsWasExpanded() . ',
                store_id: ' . (int)$block->getStore()->getId() . ',
                category_id: ' . (int)$block->getCategoryId() . ',
                parent: ' . (int)$block->getRequest()->getParam('parent') . '
        };' . PHP_EOL;

        $scriptString .= <<<script
        TreeConfig = function () {
            return {
                createTree: function () {
                    /**
                     * Initialize the jstree with tree root
                     */
                    treeDiv.jstree({
                        core: {
                            check_callback: function (operation, node) {
                               //Draggable false for root categories
                                return !(operation === 'move_node' &&
                                    node.original !== undefined && node.original.allowDrag === false);
                            }
                        },
                        plugins: ['dnd'],
                    }).bind('move_node.jstree', function (e, data) {
                        TreeConfig.categoryMove(data);
                    });

                    treeInstance = treeDiv.jstree(true);
                    let root = treeInstance.get_node('#');
                    this.buildCategoryTree(treeDiv, root, '{$block->getTreeJson()}', true);

                    let catId = treeInstance.get_node(defaultParams.category_id);
                    if (catId) {
                        currentNodeId = defaultParams.category_id;
                    } else if (defaultParams.parent > 0 && defaultParams.category_id === 0) {
                        currentNodeId = defaultParams.parent;
                    }

                    // select and open child node
                    if (defaultParams.expanded) {
                        treeInstance.open_all();
                    } else {
                        let selectedNode = treeInstance.get_node(currentNodeId);
                        treeInstance.select_node(selectedNode, true);

                        setTimeout(function () {
                            treeInstance.open_node(selectedNode);
                        }, 15);
                    }
                },

                buildCategoryTree: function(treeDiv, parent, config, firstLoad){
                    if (!config) return;

                    if(firstLoad){
                        config = $.parseJSON(config);
                    }

                    for (let i = 0; i < config.length; i++) {
                        let nodeConfig = config[i],
                        newNode = {
                            text: nodeConfig.text,
                            id: nodeConfig.id,
                            allowDrag: nodeConfig.allowDrag,
                            allowDrop: nodeConfig.allowDrop,
                            cls: nodeConfig.cls,
                            store: nodeConfig.store,
                            li_attr: { class: nodeConfig.cls}
                        };

                        const parentTree = treeInstance.create_node(parent, newNode, 'last');

                        if (nodeConfig.children) {
                            this.buildCategoryTree(treeDiv, parentTree, nodeConfig.children, false);
                        }
                    }
                },

                categoryMove : function (obj){
                    let data = {id: obj.node.id, form_key: FORM_KEY};

                    if(obj.node.parent === '#'){
                        data.pid = defaultParams.id;
                    }else{
                        data.pid = obj.node.parent;
                    }

                    data.paid = obj.old_parent;
                    data.aid = this.getSiblings(obj.node.parent,obj.position);

                    let pd = [];
                    for (let key in data) {
                        pd.push(encodeURIComponent(key), '=', encodeURIComponent(data[key]), '&');
                    }

                    pd.splice(pd.length - 1, 1);
                    registry.set('pd', pd.join(''));

                    $('[data-id="information-dialog-category"]').modal({
                        modalClass: 'confirm',
                        title:  $.mage.__('Warning message'),
                        buttons: [{
                            text: $.mage.__('Cancel'),
                            class: 'action-secondary',
                            click: function () {
                                TreeConfig.reRenderTree();
                                this.closeModal();
                            }
                        }, {
                            text: $.mage.__('Ok'),
                            class: 'action-primary',
                            click: function () {
                                (function ($) {
                                    $.ajax({
                                        url: '{$block->escapeJs($block->getMoveUrl())}',
                                        method: 'POST',
                                        data: registry.get('pd'),
                                        showLoader: true
                                    }).done(function (response) {
                                        if (response.error) {
                                            TreeConfig.reRenderTree();
                                        } else {
                                            treeInstance.trigger('TreeConfig.categoryMove');
                                        }
                                        $('.page-main-actions').next('.messages').remove();
                                        $('.page-main-actions').next('#messages').remove();
                                        $('.page-main-actions').after(response.messages);
                                    }).fail(function (jqXHR, textStatus) {
                                        if (window.console) {
                                            console.log(textStatus);
                                        }
                                        location.reload();
                                    });
                                })(jQuery);
                                this.closeModal();
                            }
                        }],
                        keyEventHandlers: {
                            enterKey: function (event) {
                                this.buttons[1].click();
                                event.preventDefault();
                            }
                        }
                    }).trigger('openModal');
                },

                getSiblings : function (parent,position) {
                    let parentNode = treeInstance.get_node(parent);
                    let sibling = treeInstance.get_node(parentNode.children[position - 1]);
                    return sibling.id;
                },

                reRenderTree : function(){
                     $('.tree-holder').empty().append('{$divElement}');
                     treeDiv = $('#tree-div');
                     TreeConfig.createTree();

                     treeDiv.on('changed.jstree', function (e, data) {
                        TreeConfig.categoryClick(data);
                     });

                     treeDiv.on("open_node.jstree", function (e, data) {
                       TreeConfig.handleOpenNode(data);
                     });
                },

                categoryClick : function(data){
                    let baseUrl = '{$block->escapeJs($block->getEditUrl())}';
                    if(data.node !== undefined && data.node.original !== undefined)
                    {
                        let storeId = data.node.original.store,
                            id = data.node.original.id;
                        if (storeId !== 0) {
                            baseUrl = baseUrl + 'store/' + storeId + '/';
                        }
                        let url = baseUrl + 'id/' + id + '/';
                        setLocation(url);
                    }
                },

                handleOpenNode : function(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) {
                                        TreeConfig.handleSuccessResponse(response, childNode, data);
                                    },
                                    error: function (jqXHR, status, error) {
                                        console.log(status + ': ' + error);
                                    }
                                });
                            }
                        });
                    }
                },

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

                            // Create the new node and execute node callback
                            data.instance.create_node(childNode, newNode, 'last');
                        });

                        // open all node if, expand all link clicked
                        if(expandAll === true){
                            data.instance.open_all();
                        }
                    }
                },

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

                expandAll : function(){
                    expandAll = true;
                    treeInstance.open_all();
                },

                collapseAll : function(){
                    treeInstance.close_all();
                    let selectedNode = treeDiv.jstree('get_selected');
                    if(selectedNode.length > 0){
                        let nodeObj = treeInstance.get_node(selectedNode),
                            parents = nodeObj.parents;
                        if(parents.indexOf('#') > -1){
                           parents.splice(parents.indexOf('#'), 1);
                        }

                        treeInstance.select_node(selectedNode, true);
                        treeInstance.open_node(parents);
                   }
                }
            };
        }();

        /**
         * jstree changed event i.e. when a node clicked
         */
        treeDiv.on('changed.jstree', function (e, data) {
             TreeConfig.categoryClick(data);
        });

        /**
         * jstree handle open node
         */
        treeDiv.on('open_node.jstree', function (e, data) {
             TreeConfig.handleOpenNode(data);
        });

        /**
         * create default tree
         */
        TreeConfig.createTree();

        function addNew(url, isRoot) {
            if (isRoot) {
                currentNodeId = defaultParams.id;
            }

            if (/store\/\d+/.test(url)) {
                url = url.replace(/store\/\d+/, 'store/' + defaultParams.store_id);
            }
            else {
                url += 'store/' + defaultParams.store_id + '/';
            }

            url += 'parent/' + currentNodeId;
            location.href = url;
        }
        window.addNew = addNew;
    });
script;
        ?>
        <?= /* @noEscape */ $secureRenderer->renderTag('script', [], $scriptString, false); ?>
<?php endif; ?>
