
(function() {
    const querySelector = function(selector, element) {
        if (element) {
            return element.querySelector(selector)
        }

        return document.querySelector(selector)
    }

    const querySelectorAll = function(selector, element) {
        if (element) {
            return element.querySelectorAll(selector)
        }

        return document.querySelectorAll(selector)
    }

    const createElement = function(tagName, attributes) {
        const element = document.createElement(tagName)

        if (typeof attributes === 'object') {
            for (let i in attributes) {
                element.setAttribute(i, attributes[i])
            }
        }

        return element
    }

    const sideMenuContainer = createElement('div', {id: 'side-menu-container'})
    const sideMenuOpener = createElement('button', {'class': 'side-menu-opener'})
    const sideMenu = createElement('div', {id: 'side-menu'})

    const body = querySelector('body')
    const html = querySelector('html')
    const nextcloud = querySelector('#nextcloud')

    const isTouchDevice = window.matchMedia("(pointer: coarse)").matches
    const targetBlankApps = ["external_index1"]
    
    querySelector('body').addEventListener('side-menu.apps', (e) => {
        const apps = e.detail.apps;

                    const sideMenu = querySelector('#side-menu')

            if (apps.length === 0) {
                sideMenu.classList.remove('open')
                sideMenu.classList.add('hide')
                sideMenuOpener.classList.add('hide')
            } else {
                sideMenu.classList.remove('hide')
                sideMenuOpener.classList.remove('hide')
            }

                        })

    body.addEventListener('side-menu.ready', () => {
        const sideMenu = querySelector('#side-menu')
        const headerMenuOpener = querySelector('#header .side-menu-opener')
        const sideMenuOpener = querySelectorAll('#side-menu .side-menu-opener')

        sideMenuFocus = () => {
            let a = querySelector('.side-menu-app.active a', sideMenu)

            if (!a) {
                return
            }

            if (a.length === 0) {
                a = querySelector('.side-menu-app:first-child a', sideMenu)
            }

            if (a.length > 0) {
                a.focus()
            }
        }

        
        headerMenuOpener.addEventListener('click', () => {
            sideMenu.classList.add('open')

            const a = querySelector('.side-menu-app.active a', sideMenu)

            if (a !== null) {
                a.focus()
            }
        })

        for (let opener of sideMenuOpener) {
            opener.addEventListener('click', () => {
                                    sideMenu.classList.remove('open')
                            })
        }

        document.addEventListener('keydown', (e) => {
            var key = e.key || e.keyCode

            if ((key === 'o' || key === 79) && e.ctrlKey === true) {
                e.preventDefault()

                sideMenu.classList.toggle('open')
                sideMenuFocus()
            }
        })

        const sideMenuObserver = new MutationObserver((e) => {
            if (body.getAttribute('id') !== 'body-settings') {
                return
            }

            body.classList.toggle('body-settings-side-menu', sideMenu.classList.contains('open'))
        })

        sideMenuObserver.observe(sideMenu, {
            attributes: true,
            attributeFilter: ['class'],
            childList: false,
            characterData: false
        })
    })

    body.appendChild(sideMenuContainer)
    sideMenuContainer.appendChild(sideMenu)

    
            nextcloud.parentNode.insertBefore(sideMenuOpener, nextcloud)
    
            const topMenuApps = ["passwords","dashboard","tasks","notes","calendar","deck","maps","contacts","spreed","circles","polls","mail","external_index1","activity","files","forms","photos"]
        const topSideMenuApps = ["tasks","notes","calendar","contacts","mail","external_index1","files"]
        let menuCache = null

const breakpointMobileWidth = 1024
const usePercentualAppMenuLimit = 0.8
const minAppsDesktop = 8

const handleMenuClick = (e, icon) => {
    let element = e.target

    while (element.tagName !== 'LI') {
        element = element.parentNode
    }

    const a = querySelector('a', element)

    if (a.getAttribute('target') !== '_blank' && e.which === 1 && !e.ctrlKey && !e.metaKey) {
        for (let tag of ['svg', 'div']) {
            let el = querySelector(tag, element)

            if (el) {
                el.remove()
            }
        }

        const loader = createElement('div', {'class': icon})

        a.insertBefore(loader, querySelector('span', a))
    }
}

const updateTopMenu = function() {
    const isMobile = window.innerWidth < breakpointMobileWidth
    const menu = querySelector('#appmenu')
    const moreApps = querySelector('#more-apps')
    const navigation = querySelector('#navigation')
    const navigationApps = querySelector('#apps ul')

    let apps = querySelectorAll('li', menu)
    let lastShownApp = null
    let appShown = []

    if ((menu.innerHTML + menu.nextSibling.innerHTML) === menuCache) {
        return
    }

    navigationAppsHtml = ''

    for (let app of apps) {
        const dataId = app.getAttribute('data-id')

        if (dataId === null) {
            continue
        }

        if (topMenuApps.indexOf(dataId) === -1 && topSideMenuApps.indexOf(dataId) === -1) {
            app.classList.add('hidden')
            app.classList.add('app-hidden')
        } else {
            app.classList.remove('hidden')
            app.classList.add('app-external-site')

            if (topSideMenuApps.indexOf(dataId) !== -1) {
                app.classList.add('app-top-side-menu')
            }

            appShown.push(app)

            navigationAppsHtml = navigationAppsHtml + app.outerHTML
        }

        if (targetBlankApps.indexOf(dataId) !== -1) {
            querySelector('a', app).setAttribute('target', '_blank')
        }
    }

    navigationApps.innerHTML = navigationAppsHtml

    const rightHeaderWidth = querySelector('.header-right').offsetWidth
    const headerWidth = querySelector('header').offsetWidth

    let availableWidth = headerWidth

    availableWidth -= nextcloud.offsetWidth
    availableWidth -= querySelector('#header .side-menu-opener').offsetWidth
    availableWidth -= rightHeaderWidth > 230 ? rightHeaderWidth : 230
    availableWidth *= isMobile ? usePercentualAppMenuLimit : 1

    let appCount = Math.floor(availableWidth / querySelector('#appmenu li:not(.hidden)').offsetWidth)

    if (isMobile && appCount > minAppsDesktop) {
        appCount = minAppsDesktop
    } else if (!isMobile && appCount < minAppsDesktop) {
        appCount = minAppsDesktop
    }

    menu.style.opacity = 1

    if (appShown.length - 1 - appCount >= 1) {
        appCount--
    }

    for (let item of querySelectorAll('a', moreApps)) {
        item.classList.remove('active')
    }

    let k = 0
    let notInHeader = 0

    for (let app of appShown) {
        const name = app.getAttribute('data-id')
        const li = querySelector('#apps li[data-id=' + name + '].app-external-site')

        if (k < appCount && appCount > 0) {
            app.classList.remove('hidden')
            li.classList.add('in-header')

            lastShownApp = app
        } else {
            app.classList.add('hidden')
            li.classList.remove('in-header')

            notInHeader++

            const a = querySelector('a', app)

            if (appCount > 0 && a.classList.contains('active')) {
                lastShownApp.classList.add('hidden')
                app.classList.remove('hidden')
                notInHeader++

                li.classList.add('in-header')
            }
        }

        k++
    }

    // Hack for:
    // - https://github.com/nextcloud/server/blob/master/core/src/components/MainMenu.js#L97-L119
    // - https://github.com/nextcloud/server/blob/master/core/src/components/MainMenu.js#L97-L119
    jQuery(menu).undelegate('li:not(#more-apps) > a', 'click')
    jQuery(navigation).undelegate('a', 'click')

    const confs = [
        {
            items: querySelectorAll('#navigation li'),
            icon: 'icon-loading-small'
        },
        {
            items: querySelectorAll('li:not(#more-apps)', menu),
            icon: OCA.Theming && OCA.Theming.inverted ? 'icon-loading-small' : 'icon-loading-small-dark'
        },
    ]

    for (let conf of confs) {
        for (let item of conf.items) {
            item.addEventListener('click', (e) => {
                handleMenuClick(e, conf.icon)
            })
        }
    }

    for (let app of querySelectorAll('#apps li.app-external-site')) {
        const appId = app.getAttribute('data-id')

        if (app.classList.contains('in-header')) {
            for (let defs of querySelectorAll('svg defs', app)) {
                defs.remove()
            }
        } else {
            const svg = querySelector('svg', app)

            if (querySelectorAll('svg defs', app).length > 0) {
                continue
            }

            const defs = `
                <defs>
                    <filter id="invertMenuMore-${appId}">
                        <feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"></feColorMatrix>
                    </filter>
                </defs>`

            svg.innerHTML = defs + svg.innerHTML

            for (let image of querySelectorAll('image', svg)) {
                image.setAttribute('filter', `url(#invertMenuMore-${appId})`)
            }

            svg.innerHTML = svg.innerHTML.replace(/fecolormatrix/g, 'feColorMatrix')
        }
    }

    if (notInHeader === 0) {
        moreApps.style.display = 'none'
        navigation.style.display = 'none'
    } else {
        moreApps.style.display = 'flex'
    }

    menuCache = menu.innerHTML + menu.nextSibling.innerHTML
}

for (let i = 0; i < 3000; i+= 100) {
    setTimeout(updateTopMenu, i)
}

let resizeTimeout = null;

window.addEventListener('resize', () => {
    if (resizeTimeout !== null) {
        clearTimeout(resizeTimeout)
    }

    resizeTimeout = setTimeout(updateTopMenu, 100)
})
    
    })();
