jQuery(function()
{
    var body = jQuery('body');
    if (body.length < 1)
    {
        return;
    }

    body.on('expand', '.expandable:not(.expanded)', function(e)
    {
        if (e.currentTarget != e.target)
        {
            return;
        }
        var element = jQuery(e.target);
        element.find('.expandable-content').first().slideDown('fast');
        element.addClass('expanded');
    });

    body.on('collapse', '.expandable.expanded', function(e)
    {
        if (e.currentTarget != e.target)
        {
            return;
        }
        var element = jQuery(e.target);
        element.find('.expandable-content').first().slideUp('fast');
        element.removeClass('expanded');
    });

    body.on('toggle', '.expandable', function(e)
    {
        if (e.currentTarget != e.target)
        {
            return;
        }
        var target = jQuery(e.target);

        if (target.is('.expanded'))
        {
            target.trigger('collapse');
        }
        else
        {
            target.trigger('expand');
        }
    });

    body.on('click', '.expandable-switch', function(e)
    {
        // a switch can be either a link or a button
        // the difference is that a link switch will attempt to modify the fragment part of the url

        var trigger = jQuery(e.target);
        if (!trigger.is('a, button'))
        {
            trigger = trigger.closest('a, button');
        }
        if (trigger.length < 1)
        {
            return;
        }

        e.preventDefault();
        e.stopPropagation();

        var target      = trigger.closest('.expandable');
        var expanding   = !target.is('.expanded');
        target.trigger('toggle');

        if (trigger.is('a'))
        {
            var hash   = target.attr('data-hash');

            var base_url        = (hash) ? window.location.href : trigger.attr('href');

            var collapsed_url   = base_url.split('#')[0];

            var expanded_url    = (hash) ? collapsed_url + '#' + hash : base_url;

            var new_url = (expanding) ? expanded_url : collapsed_url;

            jQuery(window).trigger('urlchange', new_url);
        }
    });


    body.on('contentloaded', function(e)
    {
        // convert all non-link and non-button expandable switches to buttons
        jQuery(e.target).find('.expandable-switch').not('a, button').each(function()
        {
            var node = jQuery(this);
            var button = jQuery('<button />').attr('type', 'button').attr('class', node.attr('class')).text(node.text());
            node.replaceWith(button);
        });
    });

    var expand_from_url = function()
    {
        var hash = document.location.hash.replace(/^#/,'');
        if (hash.length < 1)
        {
            return;
        }

        body.find('.expandable#' + hash + ', .expandable[data-hash="' + hash + '"]').first().trigger('expand');
    };

    jQuery(window).on('hashchange', function(e)
    {
        expand_from_url();
    });

    expand_from_url();

});
