(function(jQuery) {
jQuery.fn.aclTree = function(settings) {

    settings = jQuery.extend({
        /* Callbacks
            The callbacks should be functions that take one argument. The checkbox tree
            will return the jQuery wrapped LI element of the item that was checked/expanded.
        */
        onExpand: null,
        onCollapse: null,
        onCheck: null,
        onUnCheck: null,
        onHalfCheck: null,
        onLabelHoverOver: null,
        onLabelHoverOut: null,
        
        /* Valid choices: 'expand', 'check' */
        labelAction: "expand",
        
        // Debug (currently does nothing)
        debug: false
    }, settings);

    var $tree = this;

    $tree.find("li")
        // Hide all of the sub-trees
        //.find("ul")
        //    .hide()
        //.end()
                
        .find("label")
            // Clicking the labels should expand the children
            .click(function() {
                var action = settings.labelAction;
                switch(settings.labelAction) {
                    case 'expand':
                        jQuery(this).siblings(".arrow").click();
                        break;
                    case 'check':
                        jQuery(this).siblings(".checkbox").click();
                        break;
                }
            })
            
            // Add a hover class to the labels when hovering
            .hover(
                function() { 
                    jQuery(this).addClass("hover");
                    if (settings.onLabelHoverOver) settings.onLabelHoverOver(jQuery(this).parent());
                },
                function() {
                    jQuery(this).removeClass("hover");
                    if (settings.onLabelHoverOut) settings.onLabelHoverOut(jQuery(this).parent());
                }
            )
        .end()
        
        .each(function() {
					
						var $li = $(this);
						var $input = $li.find('input:first');
            // Create the image for the arrow (to expand and collapse the hidden trees)
            var $arrow = jQuery('<div class="arrow"></div>');
            
            // If it has children:
            if (jQuery(this).is(":has(ul)")) {
                $arrow.addClass("collapsed"); // Should start collapsed
                
                // When you click the image, toggle the child list
                $arrow.click(function() {
                    jQuery(this).siblings("ul").toggle();
                    
                    if (jQuery(this).hasClass("collapsed")) {
                        //toggled = settings.expandedarrow;
                        jQuery(this)
                            .addClass("expanded")
                            .removeClass("collapsed")
                        ;
                        if (settings.onExpand) settings.onExpand(jQuery(this).parent());
                    }
                    else {
                        //toggled = settings.collapsedarrow;
                        jQuery(this)
                            .addClass("collapsed")
                            .removeClass("expanded")
                        ;
                        if (settings.onCollapse) settings.onCollapse(jQuery(this).parent());
                    }
                });
            }
            
            // Create the image for the checkbox next to the label
            var $checkbox = $li.find('div.checkbox:first');
            
            // When you click the checkbox, it should do the checking/unchecking
            $checkbox.click(function() {
                // Make the current class checked
								
								$this = $(this);
								// Remove inherited classes
                $this.removeClass("deny_inherit").removeClass("allow_inherit");
								
								if ($this.hasClass('allow')) {
									$this.removeClass('allow').addClass('deny');
									$input.attr('value', 'deny');
								} else if ($this.hasClass('deny')) {
									$this.removeClass('deny');
									$input.attr('value', '');
								} else {
									$this.addClass('allow');
									$input.attr('value', 'allow');
								}
									
								$.fn.aclTree.updateTree($tree);
            });
            
            // Prepend the arrow and checkbox images to the front of the LI
            jQuery(this)
                .prepend($arrow);
        });

				$.fn.aclTree.updateTree($tree);

    return $tree;
};

jQuery.fn.aclTree.updateTree = function($tree) {
	
	$tree.find('li').each(function(i) {
		var $li = $(this);
		var $checkbox = $(this).find('div.checkbox:first');
		
		$checkbox
			.removeClass('allow_inherit')
			.removeClass('deny_inherit')
			.removeClass('exceptions')
			.removeClass('allow_exceptions')
			.removeClass('deny_exceptions');
		
		// check if there are exceptions to set permissions
		if($checkbox.hasClass('allow')) {
			if($li.find('div.deny').length > 0)
				$checkbox.addClass('allow_exceptions');
		} else if ($checkbox.hasClass('deny')) {
			if($li.find('div.allow').length > 0)
				$checkbox.addClass('deny_exceptions');
		} else if($li.find('div.allow, div.deny').length > 0) {
				$checkbox.addClass('exceptions');
		} else {
						
			// check inheritance
			var inherit = 'deny';
			var $parent = $li.parent('ul').parent('li');
			
			while($parent && $parent.length > 0) {
				console.log($parent);
				if($parent.find('div.checkbox:first').hasClass('allow')) {
					inherit = 'allow';
					break;
				}	else if($parent.find('div.checkbox:first').hasClass('deny')) {
					inherit = 'deny';
					break;
				}
				
				$parent = $parent.parent('ul').parent('li');
			}
			
			if(inherit == 'allow')
				$checkbox.addClass('allow_inherit');
			else
				$checkbox.addClass('deny_inherit');
		}
		
	});
	
}

})(jQuery);
