/*
 * Treeview 1.5pre - jQuery plugin to hide and show branches of a tree
 * 
 * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
 * http://docs.jquery.com/Plugins/Treeview
 *
 * Copyright (c) 2007 Jörn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.treeview.js 5759 2008-07-01 07:50:28Z joern.zaefferer $
 *
 */

;(function($) {

	// TODO rewrite as a widget, removing all the extra plugins
	$.extend($.fn, {
		swapClass: function(c1, c2) {
			var c1Elements = this.filter('.' + c1);
			this.filter('.' + c2).removeClass(c2).addClass(c1);
			c1Elements.removeClass(c1).addClass(c2);
			return this;
		},
		replaceClass: function(c1, c2) {
			return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
		},
		hoverClass: function(className) {
			className = className || "hover";
			return this.hover(function() {
				$(this).addClass(className);
			}, function() {
				$(this).removeClass(className);
			});
		},
		heightToggle: function(animated, callback) {
			animated ?
				this.animate({ height: "toggle" }, animated, callback) :
				this.each(function(){
					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
					if(callback)
						callback.apply(this, arguments);
				});
		},
		heightHide: function(animated, callback) {
			if (animated) {
				this.animate({ height: "hide" }, animated, callback);
			} else {
				this.hide();
				if (callback)
					this.each(callback);				
			}
		},
		prepareBranches: function(settings) {
			if (!settings.prerendered) {
				// mark last tree items
				this.filter(":last-child:not(ul)").addClass(CLASSES.last);
				// collapse whole tree, or only those marked as closed, anyway except those marked as open
				this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
			}
			// return all items with sublists
			return this.filter(":has(>ul)");
		},
		applyClasses: function(settings, toggler) {
			// TODO use event delegation
			this.filter(":has(>ul):not(:has(>a))").find(">span").unbind("click.treeview").bind("click.treeview", function(event) {
				// don't handle click events on children, eg. checkboxes
				if ( this == event.target )
					toggler.apply($(this).next());
			}).add( $("a", this) ).hoverClass();
			
			if (!settings.prerendered) {
				// handle closed ones first
				this.filter(":has(>ul:hidden)")
						.addClass(CLASSES.expandable)
						.replaceClass(CLASSES.last, CLASSES.lastExpandable);
						
				// handle open ones
				this.not(":has(>ul:hidden)")
						.addClass(CLASSES.collapsable)
						.replaceClass(CLASSES.last, CLASSES.lastCollapsable);
						
	            // create hitarea if not present
				var hitarea = this.find("div." + CLASSES.hitarea);
				if (!hitarea.length)
					hitarea = this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea);
				hitarea.removeClass().addClass(CLASSES.hitarea).each(function() {
					var classes = "";
					$.each($(this).parent().attr("class").split(" "), function() {
						classes += this + "-hitarea ";
					});
					$(this).addClass( classes );
				})
			}
			
			// apply event to hitarea
			this.find("div." + CLASSES.hitarea).click( toggler );
		},
		treeview: function(settings) {
			
			settings = $.extend({
				cookieId: "treeview"
			}, settings);
			
			if ( settings.toggle ) {
				var callback = settings.toggle;
				settings.toggle = function() {
					return callback.apply($(this).parent()[0], arguments);
				};
			}
		
			// factory for treecontroller
			function treeController(tree, control) {
				// factory for click handlers
				function handler(filter) {
					return function() {
						// reuse toggle event handler, applying the elements to toggle
						// start searching for all hitareas
						toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
							// for plain toggle, no filter is provided, otherwise we need to check the parent element
							return filter ? $(this).parent("." + filter).length : true;
						}) );
						return false;
					};
				}
				// click on first element to collapse tree
				$("a:eq(0)", control).click( handler(CLASSES.collapsable) );
				// click on second to expand tree
				$("a:eq(1)", control).click( handler(CLASSES.expandable) );
				// click on third to toggle tree
				$("a:eq(2)", control).click( handler() ); 
			}
		
			// handle toggle event
			function toggler() {
				$(this)
					.parent()
					// swap classes for hitarea
					.find(">.hitarea")
						.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
						.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
					.end()
					// swap classes for parent li
					.swapClass( CLASSES.collapsable, CLASSES.expandable )
					.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
					// find child lists
					.find( ">ul" )
					// toggle them
					.heightToggle( settings.animated, settings.toggle );
				if ( settings.unique ) {
					$(this).parent()
						.siblings()
						// swap classes for hitarea
						.find(">.hitarea")
							.replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
							.replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
						.end()
						.replaceClass( CLASSES.collapsable, CLASSES.expandable )
						.replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
						.find( ">ul" )
						.heightHide( settings.animated, settings.toggle );
				}
			}
			this.data("toggler", toggler);
			
			function serialize() {
				function binary(arg) {
					return arg ? 1 : 0;
				}
				var data = [];
				branches.each(function(i, e) {
					data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
				});
				$.cookie(settings.cookieId, data.join(""), settings.cookieOptions );
			}
			
			function deserialize() {
				var stored = $.cookie(settings.cookieId);
				if ( stored ) {
					var data = stored.split("");
					branches.each(function(i, e) {
						$(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
					});
				}
			}
			
			// add treeview class to activate styles
			this.addClass("treeview");
			
			// prepare branches and find all tree items with child lists
			var branches = this.find("li").prepareBranches(settings);
			
			switch(settings.persist) {
			case "cookie":
				var toggleCallback = settings.toggle;
				settings.toggle = function() {
					serialize();
					if (toggleCallback) {
						toggleCallback.apply(this, arguments);
					}
				};
				deserialize();
				break;
			case "location":
				var current = this.find("a").filter(function() {
					return this.href.toLowerCase() == location.href.toLowerCase();
				});
				if ( current.length ) {
					// TODO update the open/closed classes
					var items = current.addClass("selected").parents("ul, li").add( current.next() ).show();
					if (settings.prerendered) {
						// if prerendered is on, replicate the basic class swapping
						items.filter("li")
							.swapClass( CLASSES.collapsable, CLASSES.expandable )
							.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
							.find(">.hitarea")
								.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
								.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea );
					}
				}
				break;
			}
			
			branches.applyClasses(settings, toggler);
				
			// if control option is set, create the treecontroller and show it
			if ( settings.control ) {
				treeController(this, settings.control);
				$(settings.control).show();
			}
			
			return this;
		}
	});
	
	// classes used by the plugin
	// need to be styled via external stylesheet, see first example
	$.treeview = {};
	var CLASSES = ($.treeview.classes = {
		open: "open",
		closed: "closed",
		expandable: "expandable",
		expandableHitarea: "expandable-hitarea",
		lastExpandableHitarea: "lastExpandable-hitarea",
		collapsable: "collapsable",
		collapsableHitarea: "collapsable-hitarea",
		lastCollapsableHitarea: "lastCollapsable-hitarea",
		lastCollapsable: "lastCollapsable",
		lastExpandable: "lastExpandable",
		last: "last",
		hitarea: "hitarea"
	});
	
})(jQuery);

// ====================================================
// Function for treeview [start]
// ====================================================

/* variable using for node ID */
var nodeId = 0;

function TreeNode() {
    var currDate = new Date();
    this.Id = "node" + currDate.toIdString();
    this.Value = "";
    this.Text = "New text";
    this.Tooltip = this.Text;
    this.ChildNodes = new Array();
    this.IsClosed = true;
    this.IsCategory = true;
    this.ContentCount = 0;
    this.ChildsCount = 0;
    this.ExpandAfterBuild = false;
    /*
    AddChild = function(newNode) {
        ChildNodes.push(newNode);
    };
    RemoveChild = function(index) {
        ChildNodes.splice(index, 1);
    };
    */
};





// Add category node
function AddCategory(targetTreeView, sourceTreeNode, targetTreeNode, callbackFunction) {
	var branches;
	var scriptCallback = "";
	
	if (callbackFunction != undefined && callbackFunction != null) {
	        
	    scriptCallback += ' onclick="';
	    scriptCallback += "var currNode = new TreeNode(); currNode.Id = '" + sourceTreeNode.Id + "'; currNode.Text = '" + sourceTreeNode.Text + "';";
	    scriptCallback += "currNode.Value = '" + sourceTreeNode.Value + "'; currNode.Tooltip = '" + sourceTreeNode.Tooltip + "'; currNode.IsClosed = " + sourceTreeNode.IsClosed + ";";
        scriptCallback += "currNode.IsCategory = " + sourceTreeNode.IsCategory + ";";
	    scriptCallback += callbackFunction + "(currNode);";
	    scriptCallback += '"';
	            
	}
	if (targetTreeNode != undefined && targetTreeNode != null) {
	    if (sourceTreeNode.IsClosed == true) {  // Collapse
	        if (targetTreeView.IsShowTotal == true) {  // Show total count
	            branches = $("<li class='closed'><" + targetTreeView.CategoryTagName + " style='padding-left: 5px;' class='folder' " + scriptCallback + ">" + sourceTreeNode.Text + "</" + targetTreeView.CategoryTagName + ">&nbsp;(" + sourceTreeNode.ContentCount + ")<ul id='" + sourceTreeNode.Id + "'>" +
					"</ul></li>").appendTo("#" + targetTreeNode.Id);
	        }
	        else {
	            branches = $("<li class='closed'><" + targetTreeView.CategoryTagName + " style='padding-left: 5px;' class='folder' " + scriptCallback + ">" + sourceTreeNode.Text + "</" + targetTreeView.CategoryTagName + "><ul id='" + sourceTreeNode.Id + "'>" +
					"</ul></li>").appendTo("#" + targetTreeNode.Id);
	        }
	    }
	    else {
	        if (targetTreeView.IsShowTotal == true) {  // Show total count
	            branches = $("<li ><" + targetTreeView.CategoryTagName + " style='padding-left: 5px;' class='folder'" + scriptCallback + ">" + sourceTreeNode.Text + "</" + targetTreeView.CategoryTagName + ">&nbsp;(" + sourceTreeNode.ContentCount + ")<ul id='" + sourceTreeNode.Id + "'>" +
					"</ul></li>").appendTo("#" + targetTreeNode.Id);
	        }
	        else {
	            branches = $("<li ><" + targetTreeView.CategoryTagName + " style='padding-left: 5px;' class='folder'" + scriptCallback + ">" + sourceTreeNode.Text + "</" + targetTreeView.CategoryTagName + "><ul id='" + sourceTreeNode.Id + "'>" +
					"</ul></li>").appendTo("#" + targetTreeNode.Id);
	        }
	    }
	}
	else {
	    if (sourceTreeNode.IsClosed == true) {  // Collapse
	        if (targetTreeView.IsShowTotal == true) {  // Show total count
	            branches = $("<li class='closed'><" + targetTreeView.CategoryTagName + " style='padding-left: 5px;' class='folder'" + scriptCallback + ">" + sourceTreeNode.Text + "</" + targetTreeView.CategoryTagName + ">&nbsp;(" + sourceTreeNode.ContentCount + ")<ul id='" + sourceTreeNode.Id + "'>" +
					"</ul></li>").appendTo("#" + targetTreeView.Id);
	        }
	        else {
	            branches = $("<li class='closed'><" + targetTreeView.CategoryTagName + " style='padding-left: 5px;' class='folder'" + scriptCallback + ">" + sourceTreeNode.Text + "</" + targetTreeView.CategoryTagName + "><ul id='" + sourceTreeNode.Id + "'>" +
					"</ul></li>").appendTo("#" + targetTreeView.Id);
	        }
	    }
	    else {
	        if (targetTreeView.IsShowTotal == true) {  // Show total count
	            branches = $("<li><" + targetTreeView.CategoryTagName + " style='padding-left: 5px;' class='folder'" + scriptCallback + ">" + sourceTreeNode.Text + "</" + targetTreeView.CategoryTagName + ">&nbsp;(" + sourceTreeNode.ContentCount + ")<ul id='" + sourceTreeNode.Id + "'>" +
					"</ul></li>").appendTo("#" + targetTreeView.Id);
	        }
	        else {
	            branches = $("<li><" + targetTreeView.CategoryTagName + " style='padding-left: 5px;' class='folder'" + scriptCallback + ">" + sourceTreeNode.Text + "</" + targetTreeView.CategoryTagName + "><ul id='" + sourceTreeNode.Id + "'>" +
					"</ul></li>").appendTo("#" + targetTreeView.Id);
	        }
	    }
	}

	if (sourceTreeNode.ExpandAfterBuild == true) {
	    // Add node to expand after build treeview
	    targetTreeView.ExpandNodes.push(sourceTreeNode.Id);
	}
	
	/*$("#" + targetTreeView.Id).treeview({
	    add: branches
	});*/
};
// Add item
function AddItem(targetTreeView, sourceTreeNodeItem, targetTreeNode, callbackFunction) {
	var branches;

	var scriptCallback = "";

	if (callbackFunction != undefined && callbackFunction != null) {
	    scriptCallback += ' id="' + sourceTreeNodeItem.Id + '"';
	    scriptCallback += ' onclick="';
	    //scriptCallback += "var currNode = new TreeNode(); currNode.Id = '" + sourceTreeNodeItem.Id + "'; currNode.Text = '" + sourceTreeNodeItem.Text + "';";
	    scriptCallback += "var currNode = new TreeNode(); currNode.Id = '" + sourceTreeNodeItem.Id + "';";
	    scriptCallback += "currNode.Value = '" + sourceTreeNodeItem.Value + "'; currNode.Tooltip = '" + sourceTreeNodeItem.Tooltip + "'; currNode.IsClosed = " + sourceTreeNodeItem.IsClosed + ";";
        scriptCallback += "currNode.IsCategory = " + sourceTreeNodeItem.IsCategory + ";";
	    scriptCallback += callbackFunction + "(currNode);";
	    scriptCallback += '"';

	}

	if (targetTreeNode != undefined && targetTreeNode != null) {
	    // Nodes of root
	    if (targetTreeView.IsShowTotal == true) {
	        branches = $("<li><" + targetTreeView.CategoryTagName + " class='file'" + scriptCallback + ">" + sourceTreeNodeItem.Text + "</" + targetTreeView.CategoryTagName + ">&nbsp;(" + sourceTreeNodeItem.ContentCount + ")</li>").appendTo("#" + targetTreeNode.Id);
	    }
	    else {
	        branches = $("<li><" + targetTreeView.CategoryTagName + " class='file'" + scriptCallback + ">" + sourceTreeNodeItem.Text + "</" + targetTreeView.CategoryTagName + ">&nbsp;</li>").appendTo("#" + targetTreeNode.Id);
	    }
	}
	else {
	    if (sourceTreeNodeItem.Id == "all") {  // All nodes
	        if (targetTreeView.IsShowTotal == true) {
	            branches = $("<li><" + targetTreeView.CategoryTagName + " style='padding-left: 5px;' class='file lang root' lang='txtAll'" + scriptCallback + ">" + sourceTreeNodeItem.Text + "</" + targetTreeView.CategoryTagName + ">&nbsp;(" + targetTreeView.TotalCount + ")</li>").appendTo("#" + targetTreeView.Id);
	        }
	        else {
	            branches = $("<li><" + targetTreeView.CategoryTagName + " style='padding-left: 5px;' class='file lang root' lang='txtAll'" + scriptCallback + ">" + sourceTreeNodeItem.Text + "</" + targetTreeView.CategoryTagName + "></li>").appendTo("#" + targetTreeView.Id);
	        }
	    }
	    else {  // Node of root but not be "all node"
	        if (targetTreeView.IsShowTotal == true) {
	            branches = $("<li><" + targetTreeView.CategoryTagName + " style='padding-left: 5px;' class='file'" + scriptCallback + ">" + sourceTreeNodeItem.Text + "</" + targetTreeView.CategoryTagName + ">&nbsp;(" + sourceTreeNodeItem.ContentCount + ")</li>").appendTo("#" + targetTreeView.Id);
	        }
	        else {
	            branches = $("<li><" + targetTreeView.CategoryTagName + " style='padding-left: 5px;' class='file'" + scriptCallback + ">" + sourceTreeNodeItem.Text + "</" + targetTreeView.CategoryTagName + "></li>").appendTo("#" + targetTreeView.Id);
	        }
	    }
	}
	        
	/*$("#" + targetTreeView.Id).treeview({
	    add: branches
	});*/
};

// Add node loopback
function AddChildNode(tree, parenTreeNode, childDataNode, callbackFunctionName) {

    if (childDataNode.IsCategory) {
        
	    // Count contents of childs
	    childDataNode.ChildsCount = Number(childDataNode.ContentCount) + CountChilds(childDataNode.ChildNodes);
	    if (childDataNode.ChildsCount > 0) {
            // Set unique id
	        childDataNode.Id += nodeId++;

	        if (childDataNode.ChildsCount != childDataNode.ContentCount) {
	            
	            // Add category
	            AddCategory(tree, childDataNode, parenTreeNode, callbackFunctionName);
	            if (childDataNode.ChildNodes.length > 0) {
	                for (var nIndex = 0; nIndex < childDataNode.ChildNodes.length; nIndex++) {
	                    // Call loop back
	                    AddChildNode(tree, childDataNode, childDataNode.ChildNodes[nIndex], callbackFunctionName);
	                }
	            }
	        }
	        else {
                // Add as item
	            childDataNode.IsCategory = false;
	            AddItem(tree, childDataNode, parenTreeNode, callbackFunctionName);
	        }
	    }
	}
	else {
	    if (childDataNode.ContentCount > 0) {
	        // Set unique id
	        childDataNode.Id += nodeId++;

            // Add single item
	        AddItem(tree, childDataNode, parenTreeNode, callbackFunctionName);
	    }
	}
};

// Add node loopback
function AddChildNodeIndex(tree, parenTreeNode, childDataNode, callbackFunctionName) {

    if (childDataNode.IsCategory) {
	    
        // Set unique id
        childDataNode.Id += nodeId++;


        if (childDataNode.ChildNodes.length > 0) {
            // Add category
            AddCategory(tree, childDataNode, parenTreeNode, callbackFunctionName);

            for (var nIndex = 0; nIndex < childDataNode.ChildNodes.length; nIndex++) {
                // Call loop back
                AddChildNodeIndex(tree, childDataNode, childDataNode.ChildNodes[nIndex], callbackFunctionName);
            }
        }
        else {
            // Add as item
            childDataNode.IsCategory = false;
            AddItem(tree, childDataNode, parenTreeNode, callbackFunctionName);
        }
	}
	else {
        // Set unique id
        childDataNode.Id += nodeId++;

        // Add single item
        AddItem(tree, childDataNode, parenTreeNode, callbackFunctionName);
	}
};

/*
  Calculate childs count
*/
function CountChilds(nodes) {
    
    var nTotal = 0;
    if (nodes) {
        for (var nIndex = 0; nIndex < nodes.length; nIndex++) {
            // Count current node
            nTotal += Number(nodes[nIndex].ContentCount);
            // Continue to count childs
            if (nodes[nIndex].ChildNodes) {
                nTotal += CountChilds(nodes[nIndex].ChildNodes);
            }
        }
    }

    return nTotal;
};


function TreeView() {
    var currDate = new Date();
    this.Id = "treeview" + currDate.toIdString();
    this.Nodes = new Array();
    this.TotalCount = 0;
    this.IsShowTotal = true;
    this.ExpandNodes = [];
    this.CategoryTagName = "span";  // Use to expand/ not expand when clicking in
    this.Show = function (containerId, nodes, callbackFunctionName) {
        var tree = this;
        tree.Id = containerId;
        var newItem = new TreeNode();
        newItem.Text = i18nText('txtAll');
        newItem.Id = "all";
        newItem.IsCategory = false;
        newItem.ContentCount = this.TotalCount;
        AddItem(tree, newItem, null, callbackFunctionName);

        if (nodes != undefined && nodes != null) {
            for (var nIndex = 0; nIndex < nodes.length; nIndex++) {
            	//alert(tree.IsShowTotal);
                if (tree.IsShowTotal == true) {
                	AddChildNode(tree, null, nodes[nIndex], callbackFunctionName);
                }
                else {
                	AddChildNodeIndex(tree, null, nodes[nIndex], callbackFunctionName);
                }
            }
        }
    };
};

function TreeViewIndex() {
   var currDate = new Date();
    this.Id = "treeview" + currDate.toIdString();
    this.Nodes = new Array();
    this.TotalCount = 0;
    this.IsShowTotal = true;
    this.CategoryTagName = "span";
    this.Show = function (containerId, nodes, callbackFunctionName) {
        var tree = this;
        tree.Id = containerId;     

        if (nodes != undefined && nodes != null) {
            for (var nIndex = 0; nIndex < nodes.length; nIndex++) {
            	//alert(tree.IsShowTotal);
                if (tree.IsShowTotal) {
                	AddChildNode(tree, null, nodes[nIndex], callbackFunctionName);
                }
                else {
                	AddChildNodeIndex(tree, null, nodes[nIndex], callbackFunctionName);
                }
            }
        }
    };
};
// ====================================================
// Function for treeview [ end ]
// ====================================================