/**
 * Patterns collapsible - Collapsible content
 *
 * Copyright 2012-2013 Florian Friesdorf
 * Copyright 2012-2013 Simplon B.V. - Wichert Akkerman
 * Copyright 2012 Markus Maier
 * Copyright 2013 Peter Lamut
 * Copyright 2012 Jonas Hoersch
 */
define([
    "jquery",
    "./inject",
    "../core/logger",
    "../core/parser",
    "../core/store",
    "../registry"
], function($, inject, logger, Parser, store, registry) {
    var log = logger.getLogger("pat.collapsible"),
        parser = new Parser("collapsible");

    parser.add_argument("load-content");
    parser.add_argument("store", "none", ["none", "session", "local"]);
    parser.add_argument("transition", "slide", ["none", "css", "fade", "slide"]);
    parser.add_argument("effect-duration", "fast");
    parser.add_argument("effect-easing", "swing");
    parser.add_argument("closed", false);
    parser.add_argument("trigger", "::first");

    var _ = {
        name: "collapsible",
        trigger: ".pat-collapsible",
        jquery_plugin: true,

        transitions: {
            none: {closed: "hide", open: "show"},
            fade: {closed: "fadeOut", open: "fadeIn"},
            slide: {closed: "slideUp", open: "slideDown"}
        },

        init: function($el, opts) {
            return $el.each(function() {
                var $el = $(this),
                    options = _._validateOptions(this, parser.parse($el, opts)),
                // create collapsible structure
                    $content, state, storage;

                if (options.trigger === "::first") {
                    options.$trigger = $el.children(":first");
                    $content = $el.children(":gt(0)");
                } else {
                    options.$trigger = $(options.trigger);
                    $content = $el.children();
                }

                if (options.$trigger.length===0) {
                    log.error("Collapsible has no trigger.", this);
                    return;
                }

                if ($content.length)
                    options.$panel = $content.wrapAll("<div class='panel-content' />")
                        .parent();
                else
                    options.$panel = $("<div class='panel-content' />").insertAfter(options.$trigger);

                $el.data("patternCollapsible", options);
                state=(options.closed || $el.hasClass("closed")) ? "closed" : "open";
                if (options.store!=="none") {
                    storage=(options.store==="local" ? store.local : store.session)(_.name);
                    state=storage.get(this.id) || state;
                }

                if (state==="closed") {
                    options.$trigger.removeClass("collapsible-open").addClass("collapsible-closed");
                    $el.removeClass("open").addClass("closed");
                    options.$panel.hide();
                } else {
                    _.loadContent($el);
                    options.$trigger.removeClass("collapsible-closed").addClass("collapsible-open");
                    $el.removeClass("closed").addClass("open");
                    options.$panel.show();
                }

                options.$trigger
                    .off(".pat-collapsible")
                    .on("click.pat-collapsible", null, $el, _._onClick);

                return $el;
            });
        },

        _onClick: function(event) {
            _.toggle(event.data);
        },

        destroy: function($el) {
            $el.removeData("patternCollapsible");
            $el.children(":first").off(".pat-collapsible");
        },

        open: function($el) {
            if (!$el.hasClass("open"))
                _.toggle($el);
            return $el;
        },

        close: function($el) {
            if (!$el.hasClass("closed"))
                _.toggle($el);
            return $el;
        },

        _validateOptions: function(trigger, options) {
            if (options.store!=="none") {
                if (!trigger.id) {
                    log.warn("state persistance requested, but element has no id");
                    options.store="none";
                } else if (!store.supported) {
                    log.warn("state persistance requested, but browser does not support webstorage");
                    options.store="none";
                }
            }
            return options;
        },

        loadContent: function($el) {
            var options = $el.data("patternCollapsible");
            if (!options.loadContent)
                return;
            var components = options.loadContent.split("#"),
                url = components[0],
                id = components[1] ? "#" + components[1] : null,
                opts = [{
                    url: url,
                    source: id,
                    $target: options.$panel,
                    dataType: "html"
                }];
            inject.execute(opts, $el);
        },

        toggle: function($el) {
            var options = $el.data("patternCollapsible"),
                new_state = $el.hasClass("closed") ? "open" : "closed";

            if (options.store!=="none") {
                var storage=(options.store==="local" ? store.local : store.session)(_.name);
                storage.set($el.attr("id"), new_state);
            }

            if (new_state==="open") {
                $el.trigger("patterns-collapsible-open");
                _._transit($el, "closed", "open", options);
            } else {
                $el.trigger("patterns-collapsible-close");
                _._transit($el, "open", "closed", options);
            }

            // allow for chaining
            return $el;
        },

        _transit: function($el, from_cls, to_cls, options) {
            if (to_cls === "open")
                _.loadContent($el);

            var duration = (options.transition==="css" || options.transition==="none") ? null : options.effect.duration;

            if (!duration) {
                options.$trigger
                        .removeClass("collapsible-" + from_cls)
                        .addClass("collapsible-" + to_cls);
                $el
                    .removeClass(from_cls)
                    .addClass(to_cls);
            } else {
                var t = _.transitions[options.transition];
                $el.addClass("in-progress");
                options.$trigger.addClass("collapsible-in-progress");
                options.$panel[t[to_cls]](duration, options.effect.easing, function() {
                    options.$trigger
                            .removeClass("collapsible-" + from_cls)
                            .removeClass("collapsible-in-progress")
                            .addClass("collapsible-" + to_cls);
                    $el
                        .removeClass(from_cls)
                        .removeClass("in-progress")
                        .addClass(to_cls);
                });
            }
        }
    };

    registry.register(_);
    return _;
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab

@@ -2917,39 +2917,125 @@
             
-_.loadContent($
+if (options.loadContent)%0A                        _.loadContent($el, options.loadContent, options.$pan
 el);%0A       
@@ -4532,131 +4532,25 @@
 ($el
-) %7B%0A            var options = $el.data(%22patternCollapsible%22);%0A            if (!options.loadContent)%0A                return;
+, url, $target) %7B
 %0A   
@@ -4575,35 +4575,19 @@
 nents = 
-options.loadContent
+url
 .split(%22
@@ -4607,16 +4607,21 @@
         
+base_
 url = co
@@ -4749,16 +4749,21 @@
    url: 
+base_
 url,%0A   
@@ -4820,30 +4820,23 @@
 target: 
-options.$panel
+$target
 ,%0A      
@@ -5781,16 +5781,39 @@
 = %22open%22
+ && options.loadContent
 )%0A      
@@ -5839,16 +5839,53 @@
 tent($el
+, options.loadContent, options.$panel
 );%0A%0A    

Use more explicit API for loadContent and make internal.