document.addEventListener( "DOMContentLoaded", function( event ) {

    const menu_sec = document.querySelector( `#menu` );
    const main_el  = menu_sec.querySelector( `:scope > .main` );

    function __( str ) {
        return _( str, "menu.mod.php" );
    }

    // Закрытие выпадающих списков при кликах вне их
    document.body.addEventListener( "click", function( event ) {
        menu_sec.querySelectorAll( `.select.widget` ).forEach( function( select ) {
            select.classList.remove( "open" );
        } );
    } );

    // Сбросить поиски страниц поскольку какая-то страница изменилась
    document.body.addEventListener( "page_updated", function() {
        main_el.querySelectorAll( ".pages.select.widget input[data-clicked]" ).forEach( function( input ) {
            input.dispatchEvent( new Event( "input" ) );
        } );
    } );

    api( { fn: "get_menu_items" }, set_menu_items, function( answer ) {
        console.log( "mod menu: get_menu_items error" );
    } );

    // Установка родителей для каждого пункта меню
    function set_menu_parents( answer, init = null ) {
        main_el.querySelectorAll( `.parents.select.widget` ).forEach( function( select ) {
            const selected = select.querySelector( `.selected` );
            const input = select.querySelector( `input` );
            const options = select.querySelector( `.options .scrollable` );

            options.innerHTML = answer.result.parents;
            
            if ( init ) {
                const parent_id = selected.getAttribute( "data-parent" );
                const parent = options.querySelector( `[value="${parent_id}"]` ).innerText.trim();
                selected.querySelector( ".value" ).innerText = parent;
            }
            
            // Удалить себя из опций
            const self_id = select.closest( "[data-item]" ).getAttribute( "data-item" );
            const self = options.querySelector( `[value="${self_id}"]` );
            if ( self ) {
                self.remove();
            }

            // Применить поиск, потому что установка может быть после изменения названия
            input.dispatchEvent( new Event( "input" ) );
        } );
    }

    function set_menu_items( answer ) {
        main_el.innerHTML = answer.result.list;

        set_menu_parents( answer, "init" );

        // Селектор с поиском страниц
        main_el.querySelectorAll( ".pages.select.widget" ).forEach( function( select ) {
            const item_el = select.closest( `.item` );
            const selected = select.querySelector( `.selected` );
            const input = select.querySelector( `input` );
            // Событие input поступит только при изменении поля. Движение курсора не создаст его.
            // Кроме того input вызывается программно при изменении url страницы, чтобы произошел
            // новый запрос и перезагрузка списка страниц
            input.addEventListener( "input", function( event ) {
                const data = { fn: "get_search_pages_list", search: event.currentTarget.value };
                api( data, function( answer ) {
                    if ( answer.result ) {
                        const scrollable = select.querySelector( ".scrollable" );
                        scrollable.innerHTML = answer.result.html;
                        scrollable.querySelectorAll( ".option" ).forEach( function( option ) {
                            option.addEventListener( "click", function( event ) {
                                const id       = option.getAttribute( "data-page-id" );
                                const url      = option.getAttribute( "data-url" );
                                const title    = option.innerText;
                                const old_id   = selected.getAttribute( "data-old-page-id" );
                                selected.querySelector( ".value" ).innerText = title;
                                selected.setAttribute( "data-page-id", id );
                                // поменять url в поле ввода
                                const input_url = item_el.querySelector( "input[name='url']" );
                                input_url.value = url;
                                
                                
                                const unpublished = option.classList.contains( "unpublished" );
                                if ( unpublished ) {
                                    item_el.classList.add( "unpublished" );
                                } else {
                                    item_el.classList.remove( "unpublished" );
                                }

                                if ( id === "0" ) {
                                    // Разблокировать поле ввода адреса
                                    input_url.removeAttribute( "disabled" );
                                    // Скопировать предыдущий url
                                    input_url.value = selected.getAttribute( "data-old-item-url" );
                                } else {
                                    // Заблокировать поле ввода адреса
                                    input_url.setAttribute( "disabled", true );
                                }
                                // close dropdown list
                                selected.click();
                                // изменение
                                if ( old_id != id ) {
                                    selected.dispatchEvent( new Event( "input" ) );
                                }
                            } );
                        } );
                    }
                } );
            } );
            // Предотвратить закрытие списка при клике в input
            input.addEventListener( "click", function( event ) {
                event.stopPropagation();
            } );
            // Показать/скрыть выпадающий список
            selected.addEventListener( "click", function ( event ) {
                event.stopPropagation();
                select.classList.toggle( "open" );
                
                // Первоначальное заполнение
                if ( input.getAttribute( "data-clicked" ) === null ) {
                    input.dispatchEvent( new Event( "input" ) );
                    input.setAttribute( "data-clicked", "1" );
                }
                input.focus();
            } );
        } );

        // Селекторы выбора области меню
        main_el.querySelectorAll( `.areas.select.widget` ).forEach( function( select ) {
            select.addEventListener( "click", function( event ) {
                event.stopPropagation(); // Чтобы сразу не закрывалось
                select.classList.toggle( "open" );
            } );
            // Клики по пунктам областей вывода
            select.querySelectorAll( `.option` ).forEach( function( option ) {
                option.addEventListener( "click", function( event ) {
                    const selected = select.querySelector( `.selected` );
                    
                    const old_val = selected.getAttribute( "data-menu-area" );
                    const new_val = option.getAttribute( "value" );
    
                    if ( old_val === new_val ) return;
    
                    selected.querySelector( ".value" ).innerText = option.innerText;
                    selected.setAttribute( "data-menu-area", new_val );
                    
                    // Событие изменения. Чтобы подсветить оранжевым пунктиром
                    const input_event = new Event( "input" );
                    selected.dispatchEvent( input_event );
                } );
            } );
        } );

        // Селекторы выбора родителя
        main_el.querySelectorAll( `.parents.select.widget` ).forEach( function( select ) {
            const input = select.querySelector( `input` );
            select.addEventListener( "click", function( event ) {
                event.stopPropagation(); // Чтобы сразу не закрывалось
                select.classList.toggle( "open" );
                input.focus();
            } );
            // Предотвратить закрытие списка при клике в input
            input.addEventListener( "click", function( event ) {
                event.stopPropagation();
            } );
            // Фильтрация при поиске
            input.addEventListener( "input", function( event ) {
                // Каждый раз искать .option потому что могут быть заменены снаружи
                select.querySelectorAll( `.options .scrollable .option` ).forEach( function( option ) {
                    const pattern = ".*" + input.value.split( "" ).map( char => RegExp.escape( char ) ).join( ".*" );
                    const regex = new RegExp( pattern, "i" );
                    if ( regex.test( option.innerText ) ) {
                        option.classList.remove( "hidden" );
                    } else {
                        option.classList.add( "hidden" );
                    }
                } );
            } );
            // Клики по опциям
            // Не объединять с поиском .option выше, потому что там поиск каждый раз
            select.querySelectorAll( `.options .scrollable .option` ).forEach( function( option ) {
                option.addEventListener( "click", parent_option_click );
            } );
        } );

        // Вынесена в отдельную функцию - цепляется в двух местах
        function parent_option_click( event ) {
            const option = event.currentTarget;
            const select = option.closest( `.select.widget` );
            const selected = select.querySelector( `.selected` );

            const old_val = selected.getAttribute( "data-old-parent" );
            const new_val = option.getAttribute( "value" );

            if ( old_val === new_val ) return;

            selected.querySelector( `.value` ).innerText = option.innerText;
            selected.setAttribute( "data-parent", new_val );
            
            // Событие изменения. Чтобы подсветить оранжевым пунктиром
            const input_event = new Event( "input" );
            selected.dispatchEvent( input_event );
        }

        // Показать/скрыть свойства
        const prop_buttons = main_el.querySelectorAll( `.buttons .prop` );
        prop_buttons.forEach( function( button ) {
            button.addEventListener( "click", function( event ) {
                event.stopPropagation();
                button.closest( `[data-item]` ).classList.toggle( "open" );
            } );
        } );

        // Отлавливать изменения полей в меню или пунктах чтобы подсветить изменения
        main_el.querySelectorAll( `.menu,.item` ).forEach( function( elem ) {
            elem.querySelectorAll( `input[type=text], .selected` ).forEach( function( input ) {
                input.addEventListener( "input", function( event ) {
                    elem.classList.add( "changed" );
                } );
            } );
        } );

        // Сохранить свойства у меню или пункта меню
        menu_sec.querySelectorAll( `.buttons .button.save` ).forEach( function( button ) {
            button.addEventListener( "click", function( e ) {
                // e.stopPropagation(); // Так можнно не закрывать выпадающие списки

                const item_el = button.closest( "[data-item]" );
                const type    = item_el.getAttribute( "data-type" );
                const id      = item_el.getAttribute( "data-item" );
                const parent_el = item_el.querySelector( `[data-parent]` );

                const data = {
                    fn:             "save_menu_item",
                    type:           type,
                    id:             id,
                    title:          item_el.querySelector( `[name="title"]` ).value,
                    classes:        item_el.querySelector( `[name="classes"]` ).value,
                    sort:           item_el.querySelector( `[name="sort"]` ).value,
                    parent_id:      parent_el.getAttribute( "data-parent" ),
                    old_parent_id:  parent_el.getAttribute( "data-old-parent" ),
                }

                if ( type === "menu" ) {
                    data["area"] = item_el.querySelector( `[data-menu-area]` ).getAttribute( "data-menu-area" );
                } else if ( type === "item" ) {
                    data["tag_title"] = item_el.querySelector( `[name=tag_title]` ).value;
                    data["url"] = item_el.querySelector( `[name=url]` ).value;
                    data["page_id"] = item_el.querySelector( `[name=page_id]` ).getAttribute( "data-page-id" );
                    data["target_blank"] = item_el.querySelector( `[name=target_blank]` ).checked;
                }

                api( data, function( answer ) {
                    notify_answer( answer );

                    if ( answer.result ) {

                        set_menu_parents( answer );

                        if ( answer.result.list ) {
                            // Необходимо обновить все
                            set_menu_items( answer );
                        } else {
                            
                            // Если сортирока изменилась - перемещаем элемент прямо в дереве
                            const sort_el = item_el.querySelector( `[name="sort"]` );
                            const old_sort = sort_el.getAttribute( "data-old-sort" );
                            if ( old_sort != data.sort ) {
                                // обновить сортировку для сравнения
                                sort_el.setAttribute( "data-old-sort", data.sort );
                                
                                // Перемещаемый контейнер элемента
                                const container = item_el.parentElement;

                                // Внутри чего перемещаем
                                const resort = item_el.closest( `.resort` );

                                // Ищем перед кем вставлять
                                let before = null;
                                for ( let n = 0; n < resort.children.length; n++ ) {
                                    const node = resort.children[n];
                                    // Исключаем сравнение с собой
                                    if ( node != container ) {
                                        const sort = node.querySelector( `[data-item] [name="sort"]` ).value;
                                        if ( Number( data.sort ) < Number( sort ) ) {
                                            before = node;
                                            break;
                                        }
                                    }
                                };
                                if ( before ) {
                                    resort.insertBefore( container, before );
                                } else {
                                    resort.appendChild( container );
                                }
                                // Элемент виден, если его верхняя часть выше нижней границы окна,
                                // и нижняя часть ниже верхней границы окна.
                                const rect = container.getBoundingClientRect();
                                const isVisible = rect.top < window.innerHeight && rect.bottom > 0;

                                // Докрутить только если не виден
                                if ( ! isVisible ) {
                                    container.scrollIntoView( { behavior: "smooth", block: "center" } );
                                }
                            }

                            // Ссылка есть только у пунктов, у меню нет.
                            const a = item_el.querySelector( `.header > a` );
                            if ( a ) {
                                a.innerText = answer.result.title;
                                const url = answer.result.url;
                                if ( url.startsWith( "//" ) || url.includes( "://" ) ) {
                                    a.setAttribute( "href", url );
                                } else {
                                    a.setAttribute( "href", cms.base_path + url );
                                }
                            }
                            
                            set_menu_parents( answer );
                        }
                        
                        // Подсветить последний сохраненный
                        setTimeout( function() {
                            // Убрать маркер
                            main_el.querySelectorAll( `[data-item].last` ).forEach( function( el ) {
                                el.classList.remove( "last" );
                            } );
                            item_el.classList.remove( "changed" );
                            item_el.classList.add( "last" );
                        }, 200 );
                    }
                } );
            } );
        } );

        // Delete Menu or Item
        main_el.querySelectorAll( `.buttons .button.del` ).forEach( function( button ) {
            button.addEventListener( "click", function( e ) {
                // e.stopPropagation();
                const item_el = button.closest( `[data-item]` );
                const parent = item_el.parentNode;
                parent.classList.add( "delete" );
                // Чтобы сработала подкраска
                setTimeout( function() {
                    if ( ! confirm( __( "confirm_delete" ) ) ) {
                        parent.classList.remove( "delete" );
                        return;
                    }
                    const data = {
                        fn: "del_menu_item",
                        id: item_el.getAttribute( "data-item" )
                    };
                    api( data, function( answer ) {
                        notify_answer( answer );
                        set_menu_items( answer );
                    } );
                }, 20 );
            } );
        } );

        // Create Item
        menu_sec.querySelectorAll( `.main .button.add` ).forEach( function( button ) {
            button.addEventListener( "click", item_create );
        } );
    }

    // Создание меню или пункта меню
    function item_create( event ) {
        //e.stopPropagation();
        const btn        = event.currentTarget;
        const item_el    = btn.closest( `[data-item]` );
        let parent_el    = item_el.closest( `.items` );
        if ( parent_el ) {
            parent_el = parent_el.previousElementSibling;
        }
        const sort_input = item_el.querySelector( `input[name="sort"]` );
        
        // Три кнопки добавления: Дочерним, выше, ниже. .sub .prev .next
        let parent_id, sort;
        if ( btn.classList.contains( "create" ) ) {
            parent_id = 0;
            sort = 0;
        } else if ( btn.classList.contains( "sub" ) ) {
            parent_id = item_el.getAttribute( "data-item" );
            sort = 1_000_000; // Переместить в конец. Все равно пересортируется.
        } else if ( btn.classList.contains( "prev" ) ) {
            parent_id = parent_el.getAttribute( "data-item" );
            sort = parseInt( sort_input.value ) - 1;
        } else if ( btn.classList.contains( "next" ) ) {
            parent_id = parent_el.getAttribute( "data-item" );
            sort = parseInt( sort_input.value ) + 1;
        }

        api( { fn : "create_menu_item", parent_id : parent_id, sort: sort }, function( answer ) {
            notify_answer( answer );
            if ( answer.result ) {
                set_menu_items( answer );
                const item = menu_sec.querySelector( `[data-item="${answer.result.id}"]` );
                item.classList.add( "open" );
                item.classList.add( "last" );
                // Докрутить к новому элементу
                item.scrollIntoView( { behavior: "smooth", block: "center" } );
            }
        } );
    }
    
    // Create Menu
    menu_sec.querySelector( `.create.button` ).addEventListener( "click", item_create );
    
    // Модуль страниц вызвал событие чтобы обновить меню
    document.body.addEventListener( "update_menu", function( event ) {
        api( { fn: "get_menu_items" }, set_menu_items );
    } );

} );
