;(function($) {
	$.extend($.fn, {
	    removeClasses: function() {	        
	        $.each(arguments, $.proxy(function(i, c){this.removeClass(c);}, this));
	        return this;
	    },
		swapClass: function(c1, c2) {		    
		    if (this.filter("." + c1).length) {
	            return this.filter("." + c1).removeClass(c1).addClass(c2).end();
	        } else {
	            return this.filter("." + c2).removeClass(c2).addClass(c1).end();
	        }
		},
		replaceClass: function(c1, c2) {			
		    return this.filter("." + c1).removeClass(c1).addClass(c2).end();
		},
		heightToggle: function(callback) {		    
		    return this.each(function() {
                with ($(this)) parent().hasClass("expandable") ? hide() : show();
                if(callback) callback.apply(this, arguments);
            });
		},
		applyClasses: function() {		    
		    this.parent()
		        .find(">li")
		            .removeClasses("last", "expandable", "collapsable")
		            .filter(":has(>ul)")
    		            .filter(":has(>ul:hidden)")
    		                .addClass("expandable")
    		            .end()
    		            .not(":has(>ul:hidden)")
                            .addClass("collapsable")
                        .end()
                    .end()
                .end()
                .find(">li:last-child")
                    .addClass("last");		    
		    this.parent()
		        .find(">li:has(>ul)")
		            .not(":has(>div.hitarea)")
                        .prepend($("<div class=\"hitarea\"/>").click(function(e) {
                            e.stopImmediatePropagation();
                            $(this).parent().treeviewToggle();
                        }));
			return this;
		},		
		treeview: function() {
		    
		    return this.find("li")
                .applyClasses()
                .find(">span")
                    .click(function(e){
                        e.stopImmediatePropagation();
                        $(this).parent().treeviewSelect();
                    })
                .end()
           .end()
           .addClass("treeview");		    
        },
        treeviewLoad: function(gid, full) {
            
            return this.each($.proxy(function(){
                var showoutdated = eval($("#op").val());
                var id = typeof(gid) != "undefined" ? gid : (parseInt(this.attr("id")) || 0);
                var tv = this.parents(".treeview").andSelf().filter(".treeview");
                var bookid = this.parents(".treeview").andSelf().filter(".treeview").attr("bookid");
                if (typeof(gid) != "undefined") tv.filter("[unique=true]").treeviewCollapse();
                if (tv.find("li#" + gid).size()) {
                    tv.find("li#" + id)
                        .parentsUntil(".treeview")
                        .filter("li")
                            .replaceClass("expandable", "collapsable")
                            .find(">ul")
                                .heightToggle();
                    if (!!full) tv.find("li#" + id).treeviewSelect(true);
                } else {
                    $.get("/tree", {bookid: bookid, id: id, full: !!full}, $.proxy(function(group) {
                       if (!group) return false;
                       var cnt = !group.id ? tv : tv.find("li#" + group.id);
                       cnt.find(">ul").empty().show();
                       if (!!full) {
                           cnt
                               .removeClass("hasChildren")
                               .swapClass("collapsable", "expandable")
                               .find(">ul")
                                   .heightToggle();
                       }
                       $.each(group.childrens, cn, [cnt, showoutdated, !!full]);                
                       if (!!full) tv.find("li#" + id).treeviewSelect(true);
                    }, this));                    
                }
            }, this));         
        },        
        treeviewToggle: function(callback) {
            
            return this
                .swapClass("expandable", "collapsable")
                .find(">ul")
                    .heightToggle()
                .end()
                .filter(".collapsable")
                    .find("li")
                        .replaceClass("collapsable", "expandable")
                        .find(">ul")
                            .heightToggle()
                        .end()
                    .end()
                .end()
                .parents(".treeview[unique=true]")
                    .find("li#"+this.attr("id"))
                        .siblings()
                            .replaceClass("collapsable", "expandable")
                            .find(">ul")
                                .heightToggle()
                            .end()                            
                        .end()                        
                    .end()                    
                .end()
                .not(".hasChildren")
                    .each(callback||function(){})
                .end()
                .filter(".hasChildren")
                    .removeClass("hasChildren")
                    .treeviewLoad()                    
                .end();
        },
        treeviewCollapse: function() {
            
            return this.treeviewUnSelect()
                .find("li")
                    .replaceClass("collapsable", "expandable")
                    .find(">ul")
                        .heightToggle()
                    .end()
                .end();
        },
        treeviewSelect: function(noevent) {            
            if (!noevent) {
                this.parents(".treeview").trigger("groupselect", this.attr("id"));
            }
            return this.treeviewUnSelect().addClass("selected");
        },
        treeviewUnSelect: function() {            
            return this.parents(".treeview").andSelf()
                .filter(".treeview")
                    .find(".selected")
                        .removeClass("selected")
                    .end()
                .end();
        }        
	});
	// provide backwards compability
	$.fn.Treeview = $.fn.treeview;
	
	function cn(cnt, outdated, expand) {
        var current = $("<li/>")
            .append($("<span class=\"folder\">" + this.name + "</span>")
            .click(function(e){
                e.stopImmediatePropagation();
                $(this).parent().treeviewSelect();
            }))
            .attr("id", this.id || "")
            .appendTo(cnt.find(">ul"));
        if (this.hasChildren) {
            if (!expand || !this.childrens || !this.childrens.length) {
                $("<ul/>").appendTo(current.addClass("hasChildren").addClass("expandable")).hide();
            } else {
                $.each(this.childrens, cn, [current.append("<ul/>"), outdated, expand]);
            }
        } else {
            if ((this.productsCount == 0 && this.productsCountAll > 0)) {
                current.addClass("op");
                if (!outdated) current.addClass("hidden");
            }
        }
        current.applyClasses();
    }
	
	$("#ap + :checkbox").live("change", function() {
        var outdated = eval($("#ap").val());
        $(".treeview").find("li.op")
            .toggleClass("hidden", outdated)
            .find(">span.selected").each(function() {
                if (!outdated) {
                    $("#body").empty();
                    // match Li element
                    $(this).removeClass("selected")
                    // match parent Li element
                    .parents("li:first")
                    // match first child Li element
                    .find("li:not(.hidden):first span").triggerHandler("click");
                }
            });
    });
	
})(jQuery);
