var a11ySlideMenu = function(options) {
    var defaultOptions = {
        'direction' : 'right',
        'toggler': "#a11yMenuToggler",
        'page': '#content',
        'panel': '.a11y-sliding-menu__panel',
        'closeButton': "#closeSlideMenu"
    }

    options = typeof options !== 'undefined' ? options : defaultOptions;

    this.options = mergeObjects(defaultOptions, options)

    this.initSlideMenu(this.options)
    this.openSlideMenu(this.options)

};


a11ySlideMenu.prototype.initSlideMenu = function(props) {
    var body = document.body
    var page = returnElement(props.page)
    var panel = returnElement(props.panel)

    body.classList.add('a11y-sliding-menu')
    body.classList.add('a11y-sliding-menu--hidden')
    body.classList.add('a11y-sliding-menu-direction--' + props.direction)

    if (panel !== null) {
        panel.setAttribute('aria-hidden', 'true')
        panel.setAttribute('tabIndex', '-1')
    }
    if (page !== null) {
        page.classList.add('a11y-sliding-menu__page')
        createShader(page)
    }
}
a11ySlideMenu.prototype.openSlideMenu = function(props) {
    var button = returnElement(props.toggler);
    var page = returnElement(props.page)
    var panel = returnElement(props.panel)
    var insideCloseButton = returnElement(props.closeButton)
    if (button !== null) {

        button.addEventListener('click',function (){
            var ariaExpanded = button.getAttribute('aria-expanded')
            if (ariaExpanded === 'false') {
                document.body.classList.remove('a11y-sliding-menu--hidden')
                document.body.classList.add('a11y-sliding-menu--visible')
                button.setAttribute('aria-expanded', 'true')
                panel.setAttribute('aria-hidden','false')
                panel.setAttribute('tabIndex','0')
                page.setAttribute('tabIndex', '-1')

                // After opening menu focous on first element inside panel
                focusOnFirstElement(panel)

                // Close panel by click close button at bottom
                if (insideCloseButton !== undefined) {
                    insideCloseButton.addEventListener('click', function () {
                        document.body.classList.remove('a11y-sliding-menu--visible')
                        document.body.classList.add('a11y-sliding-menu--hidden')
                        button.setAttribute('aria-expanded', 'false')
                        panel.setAttribute('aria-hidden','true')
                        panel.setAttribute('aria-hidden','-1')
                        page.setAttribute('tabIndex', '0')
                    })
                }


            } else {
                document.body.classList.remove('a11y-sliding-menu--visible')
                document.body.classList.add('a11y-sliding-menu--hidden')
                button.setAttribute('aria-expanded', 'false')
                panel.setAttribute('aria-hidden','true')
                panel.setAttribute('aria-hidden','-1')
                page.setAttribute('tabIndex', '0')

            }

        },false)

        // Clos slide menu
        document.addEventListener("click", clickOutside, false);
        document.addEventListener('keydown', closeByEsc, false);


    } else {
        console.log('A11Y Slide open eror, check page and toggler elements')
    }
}

a11ySlideMenu.prototype.closeSlideMenu = function(props) {
    // close by clicking outside
    closeByClickingOutside(props)
}

//
// https://stackoverflow.com/questions/30498318/es5-object-assign-equivalent
function mergeObjects(){
    var res = {};
    for(var i = 0;i<arguments.length;i++){
        for(var x in arguments[i]){
            res[x] = arguments[i][x];
        };
    };
    return res;
};

function createShader(parent) {
    var shader = document.createElement('div')
    shader.classList.add('a11y-sliding-menu__shader')
    parent.parentElement.insertBefore(shader, parent)
}
function clickOutside(e) {
    var button = returnElement("#a11yMenuToggler");
    var panel = returnElement("#a11ySlidingMenu");
    var page = returnElement("#content")

    if (!button.contains(e.target)) {
        var inside = panel.contains(e.target);

        if (!inside) {
            document.body.classList.remove('a11y-sliding-menu--visible')
            document.body.classList.add('a11y-sliding-menu--hidden')
            button.setAttribute('aria-expanded', 'false')
            panel.setAttribute('aria-hidden','true')
            panel.setAttribute('tabIndex','-1')
            page.setAttribute('tabIndex','0')
        }
    }
}

function closeByEsc(e) {
    var button = returnElement("#a11yMenuToggler");
    var panel = returnElement("#a11ySlidingMenu");
    var page = returnElement("#content")

    var key = e.key; // const {key} = event; in ES6+
    if (key === "Escape") {
        document.body.classList.remove('a11y-sliding-menu--visible')
        document.body.classList.add('a11y-sliding-menu--hidden')
        button.setAttribute('aria-expanded', 'false')
        panel.setAttribute('aria-hidden', 'true')
        panel.setAttribute('tabIndex', '-1')
        page.setAttribute('tabIndex', '0')
    }
}

function returnElement(elem) {
    if (elem.charAt(0) === '#') {
       return  document.getElementById(elem.substring(1))
    } else if (elem.charAt(0) === '.') {
       return document.querySelectorAll(elem)[0]
    } else {
        return null
    }

}

function closeByClickingOutside(props) {

    console.log('click');


    /*
        panel.addEventListener('blur', function(event) {
            if (panel.contains(event.relatedTarget) || button.contains(event.relatedTarget)) {
                // don't react to this
                return;
            }
            document.body.classList.remove('a11y-sliding-menu--visible')
            document.body.classList.add('a11y-sliding-menu--hidden')
            button.setAttribute('aria-expanded', 'false')
            panel.setAttribute('aria-hidden','true')
            panel.setAttribute('tabIndex','-1')
            page.setAttribute('tabIndex','0')
        });
    */
}


function closeByClickingButton(props) {
    var button = returnElement(props.closeButton)
    var headerButton = returnElement(props.toggler)
    var panel = returnElement(props.panel)

    if (button !== null && button !== undefined ) {
        button.addEventListener('click', function() {
            document.body.classList.remove('a11y-sliding-menu--visible')
            document.body.classList.add('a11y-sliding-menu--hidden')
            headerButton.setAttribute('aria-expanded', 'false')
            panel.setAttribute('aria-hidden','true')
            panel.setAttribute('aria-hidden','-1')
            page.setAttribute('tabIndex', '0')
            headerButton.focus()
        },false)
    }

}

function focusOnFirstElement(container) {
    if (container !== undefined && container !== null) {
        var focusable = container.querySelectorAll('a[href],input, button, [tabindex="-1"]')
        focusable[0].focus()
    }
}

// ----------------
// IE polyfills
// ----------------

if (!Element.prototype.matches) {
    Element.prototype.matches = Element.prototype.msMatchesSelector ||
        Element.prototype.webkitMatchesSelector;
}

if (!Element.prototype.closest) {
    Element.prototype.closest = function(s) {
        var el = this;

        do {
            if (Element.prototype.matches.call(el, s)) return el;
            el = el.parentElement || el.parentNode;
        } while (el !== null && el.nodeType === 1);
        return null;
    };
}