<?php

namespace GriffinForms\Admin\App\Html\Widgets\LeftSidebar;

final class FormTree extends \GriffinForms\Admin\App\Html\Widgets\LeftSidebar\Format
{
    protected $form_id;

    protected function setFormId()
    {
        $this->form_id = isset($_GET['form_id']) ? absint(wp_unslash($_GET['form_id'])) : 0;
    }

    public function getHtml()
    {
        echo '<div id="griffinforms-app-leftsidebar-formtree" class="gf-leftsidebar-formtree d-flex flex-column h-100">';

        echo '<div id="griffinforms-app-leftsidebar-formtree-header" class="gf-leftsidebar-panel-header px-3 py-2 d-flex align-items-center justify-content-between">';
        echo '<span class="small fw-semibold text-uppercase" style="font-size: 10px; letter-spacing: 0.5px; color: #1e1e1e;">';
        esc_html_e('Structure', 'griffinforms-form-builder');
        echo '</span>';
        echo '<div id="griffinforms-app-leftsidebar-formtree-spinner" class="spinner-border spinner-border-sm text-secondary" style="display:none;" role="status">';
        echo '<span class="visually-hidden">' . esc_html__('Loading...', 'griffinforms-form-builder') . '</span>';
        echo '</div>';
        echo '</div>';

        echo '<div id="griffinforms-app-leftsidebar-formtree-content" class="gf-leftsidebar-formtree-content flex-fill overflow-y-auto">';
        echo '</div>';

        echo '</div>';
    }

    public function getFormTreeContent()
    {
        $nonce_status = isset($_POST['nonce']) ? wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'form_tree') : false;

        if ($nonce_status === false) {
            $this->nonceError();
        }

        $form_id = isset($_POST['form_id']) ? absint(wp_unslash($_POST['form_id'])) : 0;

        if (empty($form_id)) {
            echo '<div class="gf-notice gf-notice-danger">';
            echo esc_html(__('Invalid form ID.', 'griffinforms-form-builder'));
            echo '</div>';
            wp_die();
        }

        $form_tree = \GriffinForms\Admin\App\Html\Elements\FormTree::getInstance();
        $form_tree->setFormId($form_id);
        $form_tree->getHtml();

        wp_die();
    }

    public function getJs()
    {
        $this->addScrollToLayoutJs();
        $this->highlightTreeOnHoverJs();
        $this->highlightTreeOnSelectJs();
        $this->addTreeToggleJs();
        $this->treeRefreshJs();
    }

    private function addScrollToLayoutJs()
    {
        echo '
        $("#griffinforms-app-leftsidebar-formtree-content").on("click", "[data-gf-itemid]", function(e) {
            e.preventDefault();
            e.stopPropagation();
            const itemId = $(this).data("gf-itemid");
            const itemType = $(this).data("gf-itemtype");
            const layoutElement = $("#griffinforms-app-presentationarea").find("#griffinforms-app-" + itemType + "-" + itemId);
            const container = $("#griffinforms-app-presentationarea");

            if (layoutElement.length && container.length) {
                const offset = layoutElement.offset().top - container.offset().top + container.scrollTop() - 50;
                container.animate({ scrollTop: offset }, 700, "swing");
                $("[data-gf-itemtype][data-gf-itemid]").removeClass("gf-scroll-selected");
                layoutElement.addClass("gf-scroll-highlight gf-scroll-selected");
                setTimeout(() => layoutElement.removeClass("gf-scroll-highlight"), 2000);
            }
        });
        $("#griffinforms-app-leftsidebar-formtree-content").on("mouseleave", function() {
            $("[data-gf-itemtype][data-gf-itemid]").removeClass("gf-scroll-selected");
        });
        ' . PHP_EOL;
    }

    private function highlightTreeOnHoverJs()
    {
        echo '
        $("#griffinforms-app-presentationarea").on("mouseenter", "[data-gf-fe=true]", function() {
            const itemId = $(this).data("gf-itemid");
            const itemType = $(this).data("gf-itemtype");
            const scrollContainer = $("#griffinforms-app-leftsidebar-formtree-content");
            const treeRow = scrollContainer
                .find("li[data-gf-itemtype=\"" + itemType + "\"][data-gf-itemid=\"" + itemId + "\"]")
                .first()
                .find(".gf-form-tree-row")
                .first();
            if (treeRow.length) {
                treeRow.addClass("gf-form-tree-row--highlighted");
                const offset = treeRow.offset().top - scrollContainer.offset().top + scrollContainer.scrollTop() - 80;
                scrollContainer.stop().animate({ scrollTop: offset }, 300);
            }
        });

        $("#griffinforms-app-presentationarea").on("mouseleave", "[data-gf-fe=true]", function() {
            $("#griffinforms-app-leftsidebar-formtree-content").find(".gf-form-tree-row--highlighted")
                .removeClass("gf-form-tree-row--highlighted");
        });
        ' . PHP_EOL;
    }

    private function highlightTreeOnSelectJs()
    {
        echo '
        window.gfTreeSelectedItem = window.gfTreeSelectedItem || { itemId: null, itemType: null };

        window.gfApplyTreeSelection = function() {
            const { itemId, itemType } = window.gfTreeSelectedItem;
            const scrollContainer = $("#griffinforms-app-leftsidebar-formtree-content");
            scrollContainer.find(".gf-form-tree-row--selected").removeClass("gf-form-tree-row--selected");
            if (!itemId || !itemType) { return; }
            const li = scrollContainer.find("li[data-gf-itemtype=\"" + itemType + "\"][data-gf-itemid=\"" + itemId + "\"]").first();
            const treeRow = li.find(".gf-form-tree-row").first();
            if (treeRow.length) {
                treeRow.addClass("gf-form-tree-row--selected");
            }
        };

        document.addEventListener("item-selected", function(e) {
            window.gfTreeSelectedItem = {
                itemId: e && e.detail && e.detail.itemId != null ? String(e.detail.itemId) : null,
                itemType: e && e.detail && e.detail.itemType ? e.detail.itemType : null
            };
            window.gfApplyTreeSelection();
        });
        ' . PHP_EOL;
    }

    private function addTreeToggleJs()
    {
        echo '
        const gfLeftTreeRoot = $("#griffinforms-app-leftsidebar-formtree-content");
        const gfSetTreeChevronState = (chevron, expanded, children) => {
            chevron.attr("aria-expanded", expanded ? "true" : "false");
            chevron.find("img").toggleClass("gf-tree-chevron-rotated", !expanded);
            if (expanded) {
                children.stop(true, true).slideDown(200);
            } else {
                children.stop(true, true).slideUp(200);
            }
        };
        const gfToggleTreeNode = (chevron) => {
            if (chevron.hasClass("gf-tree-chevron-disabled")) {
                return;
            }
            const parent = chevron.closest("li");
            const children = parent.children("ul");
            if (!children.length) {
                return;
            }
            const isExpanded = chevron.attr("aria-expanded") !== "false";
            gfSetTreeChevronState(chevron, !isExpanded, children);
        };

        gfLeftTreeRoot.off("click.gfLeftFormTreeToggle", ".gf-tree-chevron");
        gfLeftTreeRoot.on("click.gfLeftFormTreeToggle", ".gf-tree-chevron", function(e) {
            e.preventDefault();
            e.stopPropagation();
            gfToggleTreeNode($(this));
        });

        gfLeftTreeRoot.off("keydown.gfLeftFormTreeToggle", ".gf-tree-chevron");
        gfLeftTreeRoot.on("keydown.gfLeftFormTreeToggle", ".gf-tree-chevron", function(e) {
            if (e.key === "Enter" || e.key === " ") {
                e.preventDefault();
                e.stopPropagation();
                gfToggleTreeNode($(this));
            }
        });
        ' . PHP_EOL;
    }

    private function treeRefreshJs()
    {
        $form_tree_nonce = wp_create_nonce('form_tree');

        echo '
        (function() {
            let gfStructurePanelHasBeenOpened = false;

            const refreshFormTreeContent = () => {
                $("#griffinforms-app-leftsidebar-formtree-spinner").show();

                const data = {
                    "action": "griffinforms_getFormTreeContent",
                    "form_id": ' . esc_js($this->form_id) . ',
                    "nonce": "' . esc_js($form_tree_nonce) . '"
                };

                $.post(ajaxurl, data, function(response) {
                    $("#griffinforms-app-leftsidebar-formtree-content").html(response);
                    $("#griffinforms-app-leftsidebar-formtree-spinner").hide();
                            if (typeof window.gfApplyTreeSelection === "function") {
                        window.gfApplyTreeSelection();
                    }
                }).fail(function() {
                    $("#griffinforms-app-leftsidebar-formtree-content").html("<div class=\"gf-notice gf-notice-danger\">' . esc_js(__('Network error. Please try again.', 'griffinforms-form-builder')) . '</div>");
                    $("#griffinforms-app-leftsidebar-formtree-spinner").hide();
                });
            };

            document.addEventListener("form-html-received", function() {
                if (gfStructurePanelHasBeenOpened) {
                    refreshFormTreeContent();
                }
            });

            document.addEventListener("form-updated", function(event) {
                if (!gfStructurePanelHasBeenOpened) { return; }
                const type = event && event.detail && event.detail.type ? event.detail.type : "";
                if (type === "heading" || type === "name" || type === "step_data") {
                    refreshFormTreeContent();
                }
            });

            document.addEventListener("gf-leftsidebar-panel", function(event) {
                const panel = event && event.detail && event.detail.panel ? event.detail.panel : "fields";
                if (panel === "structure") {
                    gfStructurePanelHasBeenOpened = true;
                    refreshFormTreeContent();
                }
            });
        })();
        ' . PHP_EOL;
    }

    public function __construct()
    {
        $this->setAll();
        add_action('wp_ajax_griffinforms_getFormTreeContent', array($this, 'getFormTreeContent'));
    }
}
