class PragmaMenu extends HTMLElement {

    constructor() {
        super();

        this.keyUpHandler = this.onKeyUp.bind(this);
        this.itemClickedHandler = this.onItemClicked.bind(this);
        this.shortcuts;
    }

    connectedCallback() {
        if (this.hidden) {
            this.setAttribute("aria-hidden", "true");
        }
        else {
            this.setAttribute("aria-hidden", "false");
        }

        const search = this.querySelector("#menu-search");
        const nav = this.querySelector("nav");

        if (search) {
            search.addEventListener("keyup", this.keyUpHandler);
        }

        if (nav) {
            nav.addEventListener("click", this.itemClickedHandler);
        }
    }

    disconnectedCallback() {
        this.removeEventListener("keyup", this.keyUpHandler);
        this.removeEventListener("click", this.itemClickedHandler);

        this.keyUpHandler = null;
        this.itemClickedHandler = null;
    }

    get hidden() {
        return this.hasAttribute("hidden");
    }

    set hidden(value) {
        this._hidden = value;

        if (this._hidden) {
            this.setAttribute("hidden", "");
            this.setAttribute("aria-hidden", "true");
        }
        else {
            this.removeAttribute("hidden");
            this.setAttribute("aria-hidden", "false");
        }
    }

    get items() {
        return this._items;
    }

    set items(items) {
        this._items = items;
        this.render();
    }

    static get observedAttributes() {
        return ["hidden"];
    }

    attributeChangedCallback(name, oldValue, newValue) {
        if (this.hidden) {
            this._hidden = true;
            this.setAttribute("aria-hidden", "true");
        }
        else {
            this._hidden = false;
            this.setAttribute("aria-hidden", "false");
        }
    }

    toggle() {
        if (this.hidden) {
            this.open();
        }
        else {
            this.close();
        }
    }

    open() {
        this.hidden = false;
        this.setAttribute("aria-hidden", "false");
        this.shortcuts.focusSearch();
    }

    render() {
        let nav = document.createElement("nav");
        let ul = document.createElement("ul");

        this._items.forEach(item => {
            let li = document.createElement("li");
            let a = document.createElement("a");

            a.text = item.text;

            if(item.resource)
                a.href = `#/${item.screen}?resource=${item.resource}`;
            else
                a.href = `#/${item.screen}`;

            li.appendChild(a);
            ul.appendChild(li);
        });

        nav.setAttribute("role", "navigation");
        nav.setAttribute("aria-label", "Main application navigation");
        nav.append(ul);

        this.appendChild(nav);

        if(!this.shortcuts) {
            this.shortcuts = new PragmaMenuShortcuts(this);
        }
    }

    onKeyUp(event) {
        const searchValue = event.target.value;
        const collection = this.querySelectorAll("a");
        const anchors = [].slice.call(collection);

        if (searchValue) {
            anchors.forEach(item => {
                if (item.text.toLowerCase().indexOf(searchValue.toLowerCase()) == -1) {
                    item.parentElement.setAttribute("aria-hidden", "true");
                }
                else {
                    item.parentElement.setAttribute("aria-hidden", "false");
                }
            });
        }
        else {
            anchors.forEach(item => {
                item.parentElement.setAttribute("aria-hidden", "false");
            });
        }
    }

    onItemClicked(event) {
        this.toggle();
    }

    close() {
        this.hidden = true;
        this.setAttribute("aria-hidden", "true");
    }
}

class PragmaMenuShortcuts {
    constructor(element) {
        this.element = element;
        this.children = element.querySelectorAll('a');
        this.first = this.children.length > 0 ? this.children[0] : null;
        this.last = this.children.length > 0 ? this.children[this.children.length - 1] : null;

        this.shortcuts = {
            "DOWNARROW": 40,
            "UPARROW": 38,
            "HOME": 36,
            "END": 35
        };

        this.keyUpHandler = this.keyup.bind(this);
        this.element.addEventListener("keyup", this.keyUpHandler);
    }

    keyup(event) {
        switch (event.keyCode) {
            case this.shortcuts.DOWNARROW:
                this.focusNextElement();
                break;
            case this.shortcuts.UPARROW:
                this.focusPreviousElement();
                break;
            case this.shortcuts.HOME:
                this.focusFirstElement();
                break;
            case this.shortcuts.END:
                this.focusLastElement();
                break;
            default:
                break;
        }
    }

    focusFirstElement() {
        this.first.focus();
    }

    focusSearch() {
        const input = this.element.querySelector("#menu-search");

        if(input)
            input.focus();
    }

    focusLastElement() {
        this.last.focus();
    }

    focusNextElement() {
        const anchors = [].slice.call(this.children);
        const currentIndex = this.currentIndex();
        const nextIndex = currentIndex + 1;

        if ((anchors.length > 0) && (nextIndex < anchors.length))
            anchors[nextIndex].focus();
        else
            this.first.focus();
    }

    focusPreviousElement() {
        const anchors = [].slice.call(this.children);
        const currentIndex = this.currentIndex();
        const previousIndex = currentIndex - 1;

        if ((anchors.length > 0) && (previousIndex >= 0))
            anchors[previousIndex].focus();
        else
            this.last.focus();
    }

    currentIndex() {
        const anchors = [].slice.call(this.children);
        const selected = document.activeElement;

        return anchors.indexOf(selected);
    }
}

customElements.define('pragma-menu', PragmaMenu);