(function($) {
	$.fn.subGroup = function() {
		return this.each(function() {
			var $this = $(this);
			this.subGroupOptions = $.metadata ? $.extend({}, $.fn.subGroup.defaults, $this.metadata()) : $.fn.subGroup.defaults;
			if (this.subGroupOptions.min > 0 && this.subGroupOptions.max > 0 && this.subGroupOptions.min > this.subGroupOptions.max) this.subGroupOptions.max = this.subGroupOptions.min;
			var $subItems = $this.find('input.subItem');
			$subItems.subItem(this);
			groupValidate(this);
			if (this.subGroupOptions.min > 0) {
				$subItems.bind('click', [this], function(e) {
					groupCheckMin(e.data[0]);
				});
			};
			if (this.subGroupOptions.max > 0) {
				$subItems.bind('click', [this], function(e) {
					groupCheckMax(e.data[0]);
				});
			};
			if (this.subGroupOptions.free > 0) {
				$subItems.bind('click', [this], function(e) {
					groupCheckFree(e.data[0]);
				});
			}
			for (i=0; i<this.subGroupOptions.controllers.length; i++) {
				var $controller = $('#'+this.subGroupOptions.controllers[i]);
				$('input[name='+$controller.attr('name')+'].subItem').bind('click', [this], function(e) {
					groupShowHide(e.data[0]);
				});
			};
		});
	};
	function groupValidate(section) {
		var $section = $(section);
		var options = section.subGroupOptions;
		if (options.min > 0) {
			groupCheckMin(section);
		}
		if (options.max > 0) {
			groupCheckMax(section);
		}
		if (options.free > 0) {
			groupCheckFree(section);
		}
		groupShowHide(section);
	}
	function groupShowHide(section) {
		var $section = $(section);
		var $sectionParent = false;
		if ($section.attr("tagName") == 'TD') {
			var $sectionParent = $section.parent();
		}
		var controllerIDs = section.subGroupOptions.controllers;
		var hide = false;
		for (var i=0; i<controllerIDs.length; i++) {
			if (!$('#'+controllerIDs[i]).attr('checked')) {
				if ($sectionParent) $sectionParent.hide().addClass('hide');
				$section.hide().addClass('hide');
				return;
			}
		}
		if ($sectionParent) $sectionParent.show().removeClass('hide');
		if ($($section).hasClass('hide')) $($section).find('table').glow('red',500, 25);
		$($section).show().removeClass('hide');
	};
	function groupCheckFree(section) {
		var $section = $(section);
		var $sectionBoxes = $section.find('input.subItem');
		var free = section.subGroupOptions.free;
		var amount = 0;
		$sectionBoxes.filter(":checked").each( function() {
			amount += itemGetQty(this);
			if (amount <= free) {
				$section.find('label[for='+this.id+'] .price').hide().addClass('hide');
			} else {
				$section.find('label[for='+this.id+'] .price').show().removeClass('hide');
			}
		});
		if (amount < free) {
			$section.find('label .price').hide().addClass('hide');
		} else {
			$sectionBoxes.not(":checked").each( function() {
				$section.find('label[for='+this.id+'] .price').show().removeClass('hide');
			});
		}
		$sectionBoxes.not(":checked").each( function() {
			if (this.subItemOptions.weight > 1 && this.subItemOptions.weight > (free-amount)) {
				$section.find('label[for='+this.id+'] .price').show().removeClass('hide');
			}
		});
		$sectionBoxes.filter('.disabled').each( function() {
			$section.find('label[for='+this.id+'] .price').hide().addClass('hide');
		});
	};
	function groupCheckMin(section) {
		var $section = $(section);
		var $sectionBoxes = $section.find('input.subItem');
		var min = section.subGroupOptions.min;
		var amount = 0;
		$sectionBoxes.filter(":checked").each( function() {
			amount += itemGetQty(this);
		});
		if (amount<min) {
			$section.addClass('boxError').find('.boxErrorBox').show().removeClass('hide').html('Must select at least ' + min + ' item' + (min>1?'s':''));
		} else {
			$section.removeClass('boxError').find('.boxErrorBox').hide();
		}
	};
	function groupCheckMax(section) {
		var $section = $(section);
		var $sectionBoxes = $section.find('input.subItem');
		var max = section.subGroupOptions.max;
		var amount = 0;
		$sectionBoxes.filter(":checked").each( function() {
			thisAmount = itemGetQty(this, (max - amount));
			if (amount + thisAmount > max) {
				itemSetCheck(this, false);
				itemValidate(this);
			} else {
				amount += thisAmount;
			}
		});
		if (amount < max) {
			$sectionBoxes.not(":checked").attr("disabled",false).removeClass('disabled');
		} else {
			$sectionBoxes.not(":radio").not(":checked").attr("disabled",true).addClass('disabled');
		}
		$sectionBoxes.not(":checked").each( function() {
			if ((this.subItemOptions.min > 0 && (this.subItemOptions.min*this.subItemOptions.weight) > (max-amount)) ||
				(this.subItemOptions.weight > 1 && this.subItemOptions.weight > (max-amount))) {
					$(this).attr("disabled",true).addClass('disabled');
			}
		});
	};
	$.fn.subGroup.defaults = {
			controllers: [],
			min: 0,
			max: 0,
			free: 0
	};
	$.fn.subItem = function(section) {
		var $section = $(section);
		return this.each(function () {
			var $this = $(this);
			this.subItemOptions = $.metadata ? $.extend({}, $.fn.subItem.defaults, $this.metadata()) : $.fn.subItem.defaults;
			itemValidate(this);
			if (this.subItemOptions.min > 0 || this.subItemOptions.max > 0) {
				$this.bind('click',[this, section],function(e) {
					itemCheckQty(e.data[0]);
					groupValidate(e.data[1]);
				});
				$('label[for='+this.id+'] input.subItemQty').click(function() {return false}).bind('change',[this, section],function(e) {
					itemCheckQty(e.data[0]);
					groupValidate(e.data[1]);
				});
			}
		});
	}
	function itemValidate(input) {
		var $input = $(input);
		var options = input.subItemOptions;
		if (options.min > 0 || options.max > 0) {
			itemCheckQty(input);
		}
	}
	function itemCheckQty(input) {
		var $input = $(input);
		var $qtybox = $('label[for='+$input.attr('id')+'] input.subItemQty');
		var min = input.subItemOptions.min;
		var max = input.subItemOptions.max;
		if ($input.attr('checked') == true) {
			if ($qtybox.attr('value') == 0) {
				itemSetCheck($input[0],false);
				itemCheckQty($input[0]);
			} else {
				$qtybox.show().removeClass('hide');
				if (min > 0 && $qtybox.attr('value') < min) {
					itemSetQty($qtybox[0],min);
				}
				if (max > 0 && $qtybox.attr('value') > max) {
					itemSetQty($qtybox[0],max);
				}
			}
		} else {
			$qtybox.hide().addClass('hide');
			itemSetQty($qtybox[0],(min>0 ? min : 1));
		}
	};
	function itemGetQty(input, max) {
		itemCheckQty(input);
		var $input = $(input);
		var $qtybox = $('label[for='+$input.attr('id')+'] input.subItemQty');
		var options = input.subItemOptions;
		var thisAmount = options.weight;
		if (options.min > 0 || options.max > 0) {
			var thisQty = $qtybox.attr('value');
			if (IsNumeric(thisQty)) thisAmount = options.weight * thisQty;
			if (typeof(max) != 'undefined' && thisAmount > max) {
				if (max >= options.weight) {
					maxQty = Math.floor(max/options.weight);
					if (maxQty > 0 && maxQty >= options.min) {
						$qtybox.attr('value', maxQty);
						thisAmount = options.weight * maxQty;
					}
				}
			}
		}
		return thisAmount;
	};
	function itemSetCheck(input, checked) {
		var $input = $(input);
		$input.attr('checked', checked).triggerHandler('change');
	}
	function itemSetQty(input, qty) {
		var $input = $(input);
		var options = input.subItemOptions;
		if (IsNumeric(qty)) {
			$input.attr('value',qty);
		};
	}
	$.fn.subItem.defaults = {
			weight: 1,
			min: 0,
			max: 0
	};
	function IsNumeric(sText) {
		var ValidChars = "0123456789.";
		var IsNumber=true;
		var Char;
		
		for (i = 0; i < sText.length && IsNumber == true; i++) {
			Char = sText.charAt(i);
			if (ValidChars.indexOf(Char) == -1) {
				IsNumber = false;
			}
		}
		return IsNumber;
	}

})(jQuery);