$(document).ready(
	function() {

		Features.init();
		Features.filter();
	}
);

var Features = {
	that: this,
	mode: 'showall',
	categories: [],
	oTable: null,
	oRdoMode: null,
	cEditions: null,
	oCategories: null,
	bFiltered: false,

	init: function(loadmode) {
		var that = this;
		this.oTable = $('#features');
		this.oRdoMode = $('#filter-all');
		this.cEditions = this.oTable.find('input[name=editions]');
		this.cFilterMethods = $('input[name=filter-method]');
		// cache rows and cells so they only need to be retrieved once
		this.cTR = this.oTable.find('tr');
		this.cTD = this.oTable.find('td');
		this.oCategories = this.oTable.find('tbody.category');

		this.getCategories();

		this.cEditions.click(
			function() {
				var jChecked = that.cEditions.filter(
					function() {
						return $(this).is(':checked');
					}
				);
				if( jChecked.size() == 0 ) {
					jChecked.attr('disabled', 'disabled');
					return false;
				} else {
					jChecked.removeAttr('disabled');
				}
				that.filter();
			}
		);

		this.cFilterMethods.click(
			function() {
				that.mode = $(this).val();
				that.filter();
			}
		);

		$('#filter-reset').click(
			function() {
				that.reset();
			}
		);
		
		// Set grid values based on incoming parameters.
		var sMode = getUrlVars()["mode"];
		var sEditions = getUrlVars()["editions"];
		var selectedEditions = new Array();
		var selectedMode = null;
		
		if (!(sEditions === undefined))
		{
			selectedEditions = sEditions.split("");
			that.cEditions.each(function(){
				if (selectedEditions[this.value] == "0")
					$(this).click();  
				});
		}
		
		if (!(sMode === undefined) && (parseInt(sMode) != "nan"))
		{		
			var selectedMode = parseInt(sMode) - 1;
			if ((selectedMode == 1) || (selectedMode == 2))
				that.cFilterMethods[selectedMode].click();
		} 
	},

	getCategories: function() {
		var that = this;
		this.oCategories.each(
			function() {
				that.categories.push( new Category( $(this) ));
			}
		)
	},

	showAllSelected: function() {
		var selectedEditions = this.getSelectedEditions();

		if( this.bFiltered ) {
			this.unfilter();
		}

		for(var nCategory=0; nCategory<this.categories.length; nCategory++) {
			var oCat = this.categories[nCategory]; // jQuery object

			for(var nRow=0; nRow<oCat.rows.length; nRow++) {
				var oRow = oCat.rows[nRow]; // array.  each member is an object: { jQuery TD, feature support value }
				var nRowValue = 0;
				for( var nCell=0; nCell<oRow.length; nCell++) {
					var oCell = oRow[nCell];

					// if this edition is not being compared
					if( selectedEditions.indexOf(nCell) == -1 ) {
						oCell.field.addClass('disabled');
					}
				}
			}
		}

		this.bFiltered = true;
	},

	compareAllSelected: function() {
		var selectedEditions = this.getSelectedEditions();

		if( selectedEditions.length == 0 ) {
			this.unfilter();
			return false;
		}

		if( this.bFiltered ) {
			this.unfilter();
		}

		for(var nCategories=0; nCategories<this.categories.length; nCategories++) {
			var oCat = this.categories[nCategories]; // jQuery object

			var nRowsHidden = 0;

			for(var nRows=0; nRows<oCat.rows.length; nRows++) {
				var oRow = oCat.rows[nRows]; // array.  each member is an object: { jQuery TD, feature support value }
				var nRowValue = 0;
				for( var nCells=0; nCells<oRow.length; nCells++) {
					var oCell = oRow[nCells];

					// if this edition is not being compared
					if( selectedEditions.indexOf(nCells) == -1 ) {
						oCell.field.addClass('disabled');
					} else {
						if(oCell.value == 0) {
							oCell.field.addClass('no-support');
						} else {
							nRowValue += new Number( oCell.value );
						}
					}
				}
				// if no features are supported within the selected editions, hide the whole row

				if( nRowValue == 0 ) {
					nRowsHidden++;
					oCell.field.parent().hide();
				}
			}

			if( nRowsHidden == oCat.oRows.size() ) {
				oCat.oHeaderNoticeCell.html('(No features)');
			}
		}

		this.bFiltered = true;
	},

	compareHighestSelected: function() {
		var selectedEditions = this.getSelectedEditions();

		if( selectedEditions.length == 0 ) {
			this.unfilter();
			return false;
		}

		if( this.bFiltered ) {
			this.unfilter();
		}

		for(var nCategories=0; nCategories<this.categories.length; nCategories++) {
			var oCat = this.categories[nCategories]; // array of jQuery object

			// in case the notice cell was previously populated, clear it
			oCat.oHeaderNoticeCell.html('');

			var nRowsHidden = 0;

			for(var nRows=0; nRows<oCat.rows.length; nRows++) {
				var oRow = oCat.rows[nRows]; // array.  each member is an object: { jQuery TD, feature support value }
				var nRowValue = 0;
				var nAllValuesEqual = -1;
				var sAllValues = '';
				var bSingleEditionSelected = selectedEditions.length == 1;

				for( var nCells=oRow.length-1; nCells>=0; nCells--) {

					// determine whether this cell is being compared
					var bSelected = ( selectedEditions.indexOf( nCells.toString() ) != -1 );

					var oCell = oRow[nCells];

					if( bSelected ) {
						// if this is the first cell being evaluated, store the field value in nAllValuesEqual
						// otherwise, determine whether this cell value differs from the first cell value
						// if its anything different, than this whole row will be shown.
						// if all field values are the same, the whole row will be hidden
						if( bSingleEditionSelected ) {
							if( oCell.value != '0' ) {
								nAllValuesEqual = -2;
							}
						} else {
							if( nAllValuesEqual == -1 ) {
								nAllValuesEqual = oCell.value;
							} else if( nAllValuesEqual != oCell.value ) {
								nAllValuesEqual = -2; // columns didn't match - set flag so this row stays visible
							}
							sAllValues += oCell.value;
						}

						if(oCell.value == 0) {
							oCell.field.addClass('no-support');
						} else {
							nRowValue += new Number( oCell.value );
						}

					} else {
						oCell.field.addClass('disabled');
					}

				} // end for

				// if no features are supported within the selected editions, hide the whole row
				if( nRowValue == 0 || nAllValuesEqual != -2 ) {
					oCell.field.parent().hide();
					nRowsHidden ++;
				}

			}
			// Took out code to hide categories when no features are shown.
			//if( nRowsHidden == oCat.oRows.size() ) {
			//	oCat.element.hide();
			//}

			if( nRowsHidden == oCat.oRows.size() ) {
				oCat.oHeaderNoticeCell.html('(No differences)');
			}

		}

		this.bFiltered = true;
	},

	filter: function() {
		switch( this.mode) {
			case 'all':
				//this.cEditions.removeAttr('disabled');
				this.compareAllSelected();
				break;
			case 'highest':
				//this.cEditions.removeAttr('disabled');
				this.compareHighestSelected();
				break;
			case 'showall':
				//this.cEditions.attr({ disabled: 'disabled', checked: 'checked'} );
				//this.unfilter();
				this.showAllSelected();
				break;
		}
	},

	unfilter: function() {
		this.cTR.show();
		this.cTD.removeClass('no-support').removeClass('disabled');
		for( var i=0; i<this.categories.length; i++) {
			this.categories[i].oHeaderNoticeCell.html('');
		}
		this.oCategories.show();
		this.bFiltered = false;
	},

	reset: function() {
		this.unfilter();
		//this.cEditions.attr('checked', false);
	},

	collapse: function() {
		this.cTR.not('.category-header, .controls').hide();
		this.cTD.removeClass('no-support').removeClass('disabled');
		this.oCategories.show();
		this.bFiltered = true;
	},

	getSelectedEditions: function() {
		var sSelected = '';
		this.cEditions.each(
			function() {
				if( this.checked ) {
					sSelected += this.value;
				}
			}
		);
		return sSelected;
	}

} // Features

var Category = function(tbody) {
	// ref for closure
	var that = this;

	this.element = tbody;

	this.oRows = tbody.find('tr');

	this.oHeaderRow = this.oRows.get(0);

	this.oHeaderNoticeCell = $(this.oHeaderRow).find('td:last');

	this.oRows = this.oRows.slice(1, this.oRows.size());

	// will contain a series of integer values, each of which represents the
	// feature state of this edition
	// 0 = feature not present
	// 1 = feature present
	// 2 = feature present and supports local database only
	// 3 = feature present and supports shareable centralized database
	this.rows = [];

	// return the feature support level from a table cell
	this.getFieldValue = function(classname) {
		var n = classname.split('support-');
		return n[n.length-1].charAt(0);
	}

	// determine the feature support levels for each edition in this row
	// then push that array onto this.data
	this.oRows.each(
		function() {
			var data = [];
			$(this).find('td').each(
				function(index) {
					if( index != 0 ) {
						data.push(
							{
								field: $(this),
								value: that.getFieldValue( $(this).attr('class') )
							}
						);
					}
				}
			);
			that.rows.push(data);
		}
	);
}

function getUrlVars(){    
	var vars = [], hash;    
	var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');    
	for(var i = 0; i < hashes.length; i++)    
	{        
		hash = hashes[i].split('=');
		vars.push(hash[0]);
		vars[hash[0]] = hash[1];
		}
		return vars;
}