import Sortable from 'sortablejs';
import $ from 'jquery';

(function ($) {
    $.fn.serializeFormJSON = function () {
        var o = {};
        var a = this.serializeArray();
        $.each(a, function () {
            if (o[this.name]) {
                if (!o[this.name].push) {
                    o[this.name] = [o[this.name]];
                }
                o[this.name].push(this.value || '');
            } else {
                o[this.name] = this.value || '';
            }
        });
        return o;
    };
})(jQuery);

$(document).ready(function () {
    if (document.body.dataset.loader) {
        var loaderDiv = document.querySelector('.main-loader > div')
        if (loaderDiv) {
            loaderDiv.innerHTML = document.body.dataset.loader
        }
    }

    var treeWrap = $('.menu-tree-wrap');
    var tree = $('.menu-tree');
    var formWrap = $('.menu-item-form');
    initTree(treeWrap, tree, formWrap);
    // open/close behavior
    treeWrap.on('click', '.menu-tree .item-container', function (e) {
        toggleChildrenShow.apply(this);
        e.preventDefault();
        return false;
    });
    treeWrap.on('click', '[data-action="update"],[data-action="add-child"],[data-global-action="create"]', function (e) {
        handleCreateUpdate.apply(this, [treeWrap, treeWrap.find('.menu-tree'), treeWrap.find('.menu-item-form')]);
        e.preventDefault();
        return false;
    });
    treeWrap.on('click', '[data-action="move-up"],[data-action="move-down"]', function (e) {
        handleMove.apply(this, [treeWrap.find('.menu-tree')]);
        e.preventDefault();
        return false;
    });
    treeWrap.on('click', '[data-action="delete"]', function (e) {
        handleDelete.apply(this, [treeWrap.find('.menu-tree'), treeWrap.find('.menu-item-form')]);
        e.preventDefault();
        return false;
    });
    treeWrap.on('click', '.menu-expand-all', function (e) {
        expandAll.apply(this, [treeWrap.find('.menu-tree')]);
        e.preventDefault();
        return false;
    });
    treeWrap.on('click', '.menu-compress-all', function (e) {
        compressAll.apply(this, [treeWrap.find('.menu-tree')]);
        e.preventDefault();
        return false;
    });
});

function initTree(treeWrap) {
    var tree = treeWrap.find('.menu-tree');
    var formWrap = treeWrap.find('.menu-item-form');
    if (treeWrap.length === 0 || tree.length === 0 || formWrap.length === 0) {
        return;
    }

    // possible replacement: https://frontend-collective.github.io/react-sortable-tree/
    var sortables = document.querySelectorAll('.menu-tree li > ul.children');
    var sortableOptions = {
        group: 'nested',
        animation: 0,
        fallbackOnBody: false,
        emptyInsertThreshold: 0,
        handle: '.drag-handle',
        onMove: function (/**Event*/evt) {
            resetItemForm(formWrap, tree);
        },
        onStart: function (/**Event*/evt) {
            resetItemForm(formWrap, tree);
            tree.addClass('dragging');
            tree.css({minHeight: (tree.height() + 50) + 'px'});
        },
        onEnd: function (/**Event*/evt) {
            resetItemForm(formWrap, tree);
            tree.removeClass('dragging');
            tree.css({minHeight: 'auto'});

            var li = $(evt.from).closest('li');
            li.toggleClass('has-children', $(evt.from).children().length > 0);
            var li = $(evt.to).closest('li');
            li.toggleClass('has-children', $(evt.to).children().length > 0);

            // todo js update menu item positions
            syncTree(tree, $(evt.item));
        },
    };
    for (var i = 0; i < sortables.length; i++) {
        Sortable.create(sortables[i], sortableOptions);
    }
    Sortable.create(document.querySelector('.menu-tree'), sortableOptions);
}

function handleCreateUpdate(treeWrap, tree, formWrap) {
    var btn = $(this);//TODO, keep THIS when using callback function
    var id = null;
    var li = null;
    var data = {};// first req
    var postData = {};// form post req
    var loader = treeWrap.find('.main-loader');

    // first reset editing class (used when switching between edit and create)
    tree.find('.update-form-displayed').removeClass('update-form-displayed');

    if (typeof btn.attr('data-global-action') !== 'undefined') {
        // global create
        postData.parentMenuItemId = tree.attr('data-menu-item-id');
    } else if (btn.attr('data-action') === 'add-child') {
        // local create
        li = btn.closest('li');
        postData.parentMenuItemId = li.attr('data-menu-item-id');

        // var tmpLi = $('<li class="created-element update-form-displayed">' +
        //     '    <div class="item-container">' +
        //     '        <span class="label">Création en cours</span>' +
        //     '    </div>' +
        //     '</li>');
        // li.find('.children:first').append(tmpLi);
        if (!li.hasClass('has-children')) {
            li.addClass('has-children');
        }
        if (!li.hasClass('opened')) {
            li.addClass('opened');
        }
        setTimeout(function () {
            li.removeClass('created-element');
        }, 600/* flash animation duration is .5s */)

        // todo: get children node, create tmp element, and replace by real element when created
        // todo: grab parent item ID
        // li = btn.closest('li');
        // tree.find('li.update-form-displayed').removeClass('update-form-displayed');
        // li.addClass('update-form-displayed');
    } else {
        // update
        li = btn.closest('li');
        tree.find('li.update-form-displayed').removeClass('update-form-displayed');
        li.addClass('update-form-displayed');
        id = li.attr('data-menu-item-id');
    }
    var currentUrl = new URL(document.location.href);
    var urls = {
        create: location.protocol + '//' + window.location.hostname + tree.attr('data-create-url'),
        update: location.protocol + '//' + window.location.hostname + tree.attr('data-update-url'),
    };
    var url = new URL(urls.create);
    if (id) {
        url = new URL(urls.update);
        url.searchParams.set('menuItemId', parseInt(id));
    }
    if (postData.parentMenuItemId) {
        url.searchParams.set('parentMenuItemId', parseInt(postData.parentMenuItemId))
    }
    url.searchParams.set('menuId', currentUrl.searchParams.get('menuId'));


    loader.show();
    $.ajax({
        method: 'GET',
        dataType: 'json',
        url: url,
        data: data,
        success: function (response) {
            loader.hide();
            var formHtml = response.form;
            formWrap.html(formHtml);
            // todo: init input field js
            var form = $(formWrap.find('form:first'));
            initFormFields(form);
            form.on('submit', function (e) {
                loader.show();
                postData = $.extend({}, postData, $(this).serializeFormJSON());
                $.ajax({
                    method: 'POST',
                    dataType: 'json',
                    url: url,
                    data: postData,
                    success: function (postResponse) {
                        loader.hide();
                        if (!postResponse.errors || (postResponse.errors && postResponse.errors.length === 0)) {
                            formWrap.html('Enregistrement OK');
                            if (postResponse.tree) {
                                var newTree = $(postResponse.tree);
                                newTree.insertAfter(tree);
                                tree.remove();
                                initTree(treeWrap);
                            }
                            if (
                                postResponse.saved
                                && postResponse.saved.currentTranslation
                                && postResponse.saved.currentTranslation.label
                            ) {
                                // li.find('.label:first').html(postResponse.saved.currentTranslation.label);

                            }
                            // if(tree)
                            // if(li) {
                            //     li.removeClass('update-form-displayed');
                            // }
                        } else {
                            formWrap.html(JSON.stringify(postResponse));
                        }
                    }
                });
                e.preventDefault();
                return false;
            })
        }
    })
}

function handleMove(tree) {
    var btn = $(this);
    var li = btn.closest('li');
    var direction = btn.attr('data-action');

    if (direction === 'move-up') {
        var prev = li.prev();
        li.insertBefore(prev);
    } else if (direction === 'move-down') {
        var next = li.next();
        li.insertAfter(next);
    } else {
        return;
    }

    li.addClass('sorted-element');
    syncTree(tree, li, function () {
        setTimeout(function () {
            li.removeClass('sorted-element');
        }, 600/* flash animation duration is .5s */)
    });
}

function handleDelete(tree, formWrap) {
    var btn = $(this);
    var li = btn.closest('li');
    var loader = $('.main-loader');
    if (confirm('Confirmer la suppression de cet élément ?')) {
        loader.show();
        var id = li.attr('data-menu-item-id');
        var url = tree.attr('data-delete-url') + '?id=' + parseInt(id);
        $.ajax({
            method: 'POST',
            dataType: 'json',
            url: url,
            data: {},
            success: function (postResponse) {
                loader.hide();
                if (!postResponse.errors || (postResponse.errors && postResponse.errors.length === 0)) {
                    if (postResponse.successes && postResponse.successes.length > 0) {
                        formWrap.html(postResponse.successes.join('<br/>'));
                    }
                    li.remove();
                } else {
                    formWrap.html(JSON.stringify(postResponse));
                }
            }
        });
    }
}

function expandAll(tree) {
    tree.find('li.has-children').addClass('opened');
}

function compressAll(tree) {
    tree.find('li.has-children').removeClass('opened');
}

function initFormFields(form) {
    if (AAForm) {
        AAForm.initialize(form.get(0));
    }

    var inputs = form.find(':input');
    var typeSelector = form.find('[data-menu-item-type-selector]');
    var handleTypeChange = function (form) {
        var impactedInputs = form.find('[data-menu-item-types]');
        var currentType = typeSelector.val();
        impactedInputs.parent().hide();
        impactedInputs.each(function () {
            var input = $(this);
            if (input.attr('data-menu-item-types').split(',').indexOf(currentType) !== -1) {
                input.parent().show();
            } else {
                input.parent().hide();
            }
        });
    };
    typeSelector.on('change', function () {
        handleTypeChange(form);
    });
    handleTypeChange(form)
}

function resetItemForm(formWrap, tree) {
    formWrap.html(formWrap.attr('data-default-html'));
    tree.find('li.update-form-displayed').removeClass('update-form-displayed');
}

function serializeTree(list, serialized) {
    if (typeof serialized === 'undefined') {
        serialized = [];
    }

    list.find('> li').each(function () {
        var el = $(this);
        var parsed = {
            id: el.attr('data-menu-item-id'),
            children: [],
        };
        var childrenEl = el.find('> .children');
        if (childrenEl.length > 0) {
            var currentChild = $(this);
            parsed.children = serializeTree(childrenEl);
        }
        serialized.push(parsed);
    });
    return serialized;
}

function syncTree(treeEl, sortedEl, callback) {
    var serializedTree = serializeTree(treeEl);
    var sortedItemId = sortedEl.attr('data-menu-item-id');
    var rootItemId = treeEl.attr('data-menu-item-id');
    var loader = $('.main-loader');
    loader.show();
    $.ajax({
        method: 'POST',
        dataType: 'json',
        url: treeEl.attr('data-reorder-url'),
        data: {
            id: sortedItemId,
            rootId: rootItemId,
            serialized: serializedTree,
        },
        success: function (response) {
            loader.hide();
            if (callback && typeof callback === 'function') {
                callback(response)
            }
        }
    })
}

function toggleChildrenShow() {
    $(this).closest('li').toggleClass('opened');
}
