(function () {
    'use strict';

    var internalId = 0;
    var togglesMap = {};
    var targetsMap = {};

    function $(selector, context) {
        return Array.prototype.slice.call(
            (context || document).querySelectorAll(selector),
        );
    }

    function getClosestToggle(element) {
        if (element.closest) {
            return element.closest('[data-a11y-toggle]');
        }

        while (element) {
            if (
                element.nodeType === 1 &&
                element.hasAttribute('data-a11y-toggle')
            ) {
                return element;
            }

            element = element.parentNode;
        }

        return null;
    }

    function handleToggle(toggle) {
        var target = toggle && targetsMap[toggle.getAttribute('aria-controls')];

        if (!target) {
            return false;
        }

        var toggles = togglesMap['#' + target.id];
        var isExpanded = target.getAttribute('aria-hidden') === 'false';

        target.setAttribute('aria-hidden', isExpanded);
        toggles.forEach(function (toggle) {
            toggle.setAttribute('aria-expanded', !isExpanded);
        });
    }

    var initA11yToggle = function (context) {
        togglesMap = $('[data-a11y-toggle]', context).reduce(function (
            acc,
            toggle,
        ) {
            var selector = '#' + toggle.getAttribute('data-a11y-toggle');
            acc[selector] = acc[selector] || [];
            acc[selector].push(toggle);
            return acc;
        }, togglesMap);

        var targets = Object.keys(togglesMap);
        targets.length &&
            $(targets).forEach(function (target) {
                var toggles = togglesMap['#' + target.id];
                var isExpanded = target.hasAttribute('data-a11y-toggle-open');
                var labelledby = [];

                toggles.forEach(function (toggle) {
                    toggle.id ||
                        toggle.setAttribute(
                            'id',
                            'a11y-toggle-' + internalId++,
                        );
                    toggle.setAttribute('aria-controls', target.id);
                    toggle.setAttribute('aria-expanded', isExpanded);
                    labelledby.push(toggle.id);
                });

                target.setAttribute('aria-hidden', !isExpanded);
                target.hasAttribute('aria-labelledby') ||
                    target.setAttribute(
                        'aria-labelledby',
                        labelledby.join(' '),
                    );

                targetsMap[target.id] = target;
            });
    };

    document.addEventListener('DOMContentLoaded', function () {
        initA11yToggle();
    });

    document.addEventListener('click', function (event) {
        var toggle = getClosestToggle(event.target);
        handleToggle(toggle);
    });

    document.addEventListener('keyup', function (event) {
        if (event.which === 13 || event.which === 32) {
            var toggle = getClosestToggle(event.target);
            if (toggle && toggle.getAttribute('role') === 'button') {
                handleToggle(toggle);
            }
        }
    });

    window && (window.a11yToggle = initA11yToggle);
})();
