(function ($) {
	var dropdownJSProcessed = false;
	
	
	$.fn.extend({

		datagrid: function (options) {

		return this.each(function () {
			
			var o = options;
			var obj = $(this);
			var dropdown_open = -1;
			var header_pos = 0;
			var dropdown_position_x = 0;

			// Removes action button and sets on select behaviour to dropdown
			$(obj).find('.ops_datagrid_options_actions input:submit').remove();
			
			if ( $(obj).attr("id").indexOf("_data") != -1 ) {
				// Hover and click behaviour on rows for grids with fixed rows/columns
				var re = /_data$/;
				var dgID = $(obj).attr("id").replace(re, "");

				var $trs = $('table#' + dgID + '_data tr, table#' + dgID + '_rowLabels tr');
				$trs.hover(
					function() {
						var i = $(this).index() + 1;
						$trs.filter(':nth-child(' + i + ')').addClass('hover');
					},
					function() {
						var i = $(this).index() + 1;
						$trs.filter(':nth-child(' + i + ')').removeClass('hover');
					}
				);
			} else {
				// Hover and click behaviour on rows of standard datagrids
				$(obj).find('tbody td').hover(function () {
					$(this).closest('tr').addClass('hover');
				}, function () {
					$(this).closest('tr').removeClass('hover');
				}).click(function () {
					if ($(this).is(':not(.ops_datagrid_blocklink)')) {
						var togglerow = $(this).closest('tr');
						toggleselect(togglerow, "toggle");
					}
				});
			}


			// All, invert selections
			$(obj).find('.ops_datagrid_options_selections_icon_all').each(function () {
				$(this).click(function () {
					if ($(this).is('.checked')) {
						var togglerow = $(this).closest('.ops_datagrid').find('tbody > tr');
						toggleselect(togglerow, "unset");
						$(this).removeClass('checked');
						$(this).attr('src', 'Static/Icons/C/checkbox_empty.png');
					} else {
						var togglerow = $(this).closest('.ops_datagrid').find('tbody > tr:visible');
						toggleselect(togglerow, "set");
						$(this).addClass('checked');
						$(this).attr('src', 'Static/Icons/C/checkbox_checked.png');
					}
				});
			});
			$(obj).find('.ops_datagrid_options_selections_icon.ops_datagrid_options_selections_icon_invert').each(function () {
				$(this).click(function () {
					$(this).closest('.ops_datagrid').find('tbody > tr:visible').each(function () {
						var togglerow = $(this);
						toggleselect(togglerow, "toggle");
					});
				});
			});

			// Closes dropdown if click event is on body, has class .ops_datagrid_dropdown_open or if click is within dropdown
			$('body').click(function (event) {
				if ($(event.target).is('.ops_datagrid_dropdown') || $(event.target).is('.ops_datagrid_dropdown_open') || $(event.target).closest('.ops_datagrid_dropdown').length > 0) {
					// Do nothing
				} else {
					if (dropdown_open !== -1) {
						close_dropdown();
					}
				}
			});

			// Sets pre checked rows to be highlighted
			$(obj).find('.ops_datagrid_rowselect:checked').each(function () {
				var togglerow = $(this).closest('tr');
				toggleselect(togglerow, "set");
			});

			// Opens dropdown menu when .ops_datagrid_dropdown_open is clicked
			$(obj).find('.ops_datagrid_dropdown_open').click(function (event) {

				var header = $(this);
				if (dropdown_open == -1 || $('.ops_datagrid_dropdown_open').index($(event.target)) !== dropdown_open) {

					// Create dropdown within <body>
					$(obj).append(
							"<div class='ops_datagrid_dropdown' style='opacity: 0;'></div>"
						);
					$('.ops_datagrid_dropdown').animate({ opacity: 1 }, 200);

					makeWindowed($('.ops_datagrid_dropdown'));

					// Create array to contain information for template
					var dropdown_content = {};

					// Sets sortable status
					if ($(header).is('.ops_datagrid_column_sortable')) {
						dropdown_content.sort_status = 'true';
					} else {
						dropdown_content.sort_status = 'false';
					}

					// Sets sortable status
					if ($(header).is('.ops_datagrid_column_filterable_search')) {
						dropdown_content.search_status = 'true';
					} else {
						dropdown_content.search_status = 'false';
					}

					// Creates information for discreet filtering
					if ($(header).is('.ops_datagrid_column_filterable_discreet')) {

						var discreet_searchable_tr = $(header).parent();
						var discreet_searchable_th_index;
						
						var i = $(header).attr('class').indexOf("ops_datagrid_column_index_");
						if (i > -1) {
							discreet_searchable_th_index = $(header).attr('class').substring(i + 26, i + 27);
						}
						if ($(header).closest('.ops_datagrid').find('.ops_datagrid_column_rowselect').length == 1) {
							discreet_searchable_th_index++;
						}
						
						if ($(header).parent().siblings().length == 0) {
							discreet_searchable_th_index = $(discreet_searchable_tr).children('th').index(header);
						} else if ($(header).parent().siblings().length == 1) {
							if ($(header).closest('thead').children().index($(header).parent()) == 0) {
								//on first row

							} else {
								//on second row
								var index_thisrow = $(discreet_searchable_tr).children('th').index(header);

								var row = $(header).parent().siblings().children();
								//var teeaitches = $(row).children();
								var teeaitch = $(row).find('th:not([rowspan])').eq(index_thisrow);

								var thing = $(teeaitches).index($(teeaitch));


								var ache = $(row).children().filter(':lt(' + thing + ')').filter('[rowspan]');


								discreet_searchable_th_index = $(ache).length + index_thisrow;
							}
						} else {

						}

						var discreet_options = new Array();

						$(this).closest('.ops_datagrid').find('tbody > tr').each(function () {
							if ($(this).is('.no_results')) {
								return;
							}
							var td_content = $(this).children('td').eq(discreet_searchable_th_index);
							var bool = 'false';
							var visible = 'false';
							for (var i in discreet_options) {
								if (discreet_options[i].value == td_content.text()) {
									bool = 'true';
								}
							}
							if ($(td_content).is(':visible')) {
								visible = 'true';
							}
							if (bool == 'false') {
								discreet_options.push({ name: 'something', value: td_content.text(), visible: visible });
							}
						});

						discreet_options.sort();

						dropdown_content.discreet_options = discreet_options;
					}

					// Apply and process template
					$(".ops_datagrid_dropdown").setTemplate($("#dropdown_template").html());
					$(".ops_datagrid_dropdown").processTemplate(dropdown_content);

					update_checkbox();

					// Position dropdown
					header_pos = $(this).position();
					header_width = $(this).width();
					dropdown_width = $('.ops_datagrid_dropdown').width();

					if (header_pos.left + header_width + 12 + dropdown_width < document.documentElement.clientWidth) {
						dropdown_position_x = header_pos.left + header_width + 12;
					} else {
						dropdown_position_x = header_pos.left - dropdown_width - 10;
					}
					$('.ops_datagrid_dropdown').css({ 'top': header_pos.top + 31, 'left': dropdown_position_x });

					dropdown_open = $('.ops_datagrid_dropdown_open').index($(this));

					$('.ops_datagrid_dropdown_searching_searchfield').focus();

					// Binds click events to submit buttons with dropdown
					// Binds click event to sort links
					$('.ops_datagrid_dropdown_sorting_sort').click(function () {
						var table = $(header).closest('.ops_datagrid');
						var headers = $(header).parent().children();
						var column = headers.index(header);
						if ($(this).is('.ops_datagrid_dropdown_sorting_sort_asc')) {
							sort_table(table, header, column, 'asc');
						} else if ($(this).is('.ops_datagrid_dropdown_sorting_sort_desc')) {
							sort_table(table, header, column, 'desc');
						}
						close_dropdown();
					});

					// Binds click event for search field
					$('.ops_datagrid_dropdown_searching_searchfield').keyup(function () {
						var table_id = $('.ops_datagrid').index($(header).closest('.ops_datagrid'));

						var search_field = $(header).text();
						search_term = new Array($(this).val());

						filtertable(table_id, search_field, search_term);
					});

					// Binds click event for discreet filters
					$('.ops_datagrid_dropdown_filtering_checkbox_option').click(function () {
						update_checkbox();
					});
					$('.ops_datagrid_dropdown_filtering_checkbox_all').click(function () {
						if ($(this).attr('checked')) {
							$(this).siblings('.ops_datagrid_dropdown_filtering_checkbox_option').attr('checked', 'true');
						} else {
							$(this).siblings('.ops_datagrid_dropdown_filtering_checkbox_option').attr('checked', '');
						}
					});
					$('.ops_datagrid_dropdown_filtering_submit').click(function () {
						var table_id = $('.ops_datagrid').index($(header).closest('.ops_datagrid'));
						var discreet_field = $(header).text();
						discreet_terms = new Array();
						$(this).parent().find('.ops_datagrid_dropdown_filtering_checkbox_option:checked').each(function () {
							discreet_terms.push($(this).val());
						});

						filtertable(table_id, discreet_field, discreet_terms);
						close_dropdown();
					});

					// Binds click event for reset link
					$('.ops_datagrid_dropdown_reset').click(function () {
						var table_id = $('.ops_datagrid').index($(header).closest('.ops_datagrid'));
						filtertable(table_id);
						close_dropdown();
					});

				} else {
					close_dropdown();
				}
			});

			// When clicking the datagrid's "Export" button, ensure that the list of options shown
			// is sticky i.e. stays on the screen when the mouse moves outside the container.
			// The "hover_toggle" class is what causes it to maintain this state.
			$(obj).find('.ops_datagrid_export_button').click( function() {
				$(this).closest('.ops_datagrid_export').toggleClass('hover_toggle');
			} );
			
			// On the click of a dropdown item, remove any toggled state of the dropdown.
			$(obj).find('.ops_datagrid_export_options a').click( function() { 
				$(this).closest('.ops_datagrid_export').removeClass('hover_toggle'); 
			} );
		});

		// Fades then closes dropdown dependant on mouse position
		$(document).mousemove(function (e) {

			var dropdown_width = $('.ops_datagrid_dropdown').width() + 10; // 10 is twice the padding
			var dropdown_height = $('.ops_datagrid_dropdown').height() + 10;
			var dis_x;
			var dis_y;

			if (e.pageX < dropdown_position_x) {
				dis_x = -1 * (dropdown_position_x - e.pageX);
			} else if (e.pageX > (dropdown_position_x + dropdown_width)) {
				dis_x = dropdown_position_x + dropdown_width - e.pageX;
			} else {
				dis_x = 0;
			}

			if (e.pageY < header_pos.top + 31) {
				dis_y = -1 * (header_pos.top + 31 - e.pageY);
			} else if (e.pageY > (header_pos.top + 31 + dropdown_height)) {
				dis_y = header_pos.top + 31 + dropdown_height - e.pageY;
			} else {
				dis_y = 0;
			}

			var dis = Math.sqrt(dis_x * dis_x + dis_y * dis_y);

			if (dis > 200) {
				close_dropdown();
			} else {
				$('.ops_datagrid_dropdown').css({ 'opacity': 1 - (dis / 500) });
			}

		});

		function sort_table(table, tab_header, col_index, direction) {

			var amount_num = 0;
			var amount_date_ddMMMyy = 0;
			var amount_date_ddMMMyyhhmm = 0;
			var amount_btec = 0;
			var btec_chars = /[DMPF]{1,3}/;

			// Count different data types
			$(table).find('tbody > tr').each(function () {
				var td_content = $(this).find('td:eq(' + col_index + ')').text();
				if (parseInt(td_content, '10')) { // If number
					amount_num++;
					if ((td_content.charAt(2) == ' ') && (td_content.charAt(6) == ' ') && (td_content.length == 9)) { // If ddMMMyy
						amount_date_ddMMMyy++;
					} else if ((td_content.charAt(2) == ' ') && (td_content.charAt(6) == ' ') && (td_content.charAt(9) == ' ') && (td_content.charAt(12) == ':') && (td_content.length == 15)) { // If ddMMMyyhhmm
						amount_date_ddMMMyyhhmm++;
					}
				} else if (td_content.match(btec_chars)) { // If btec
					amount_btec++;
				}
			});

			var amount_rows = $(table).find('tbody > tr').length;
			if (amount_date_ddMMMyy == amount_rows) {
				var datatype = 'ddMMMyy';
			} else if (amount_date_ddMMMyyhhmm == amount_rows) {
				var datatype = 'ddMMMyyhhmm';
			} else if (amount_num == amount_rows) {
				var datatype = 'number';
			} else if (amount_btec == amount_rows) {
				var datatype = 'btec';
			}

			var rows = table.find('tbody > tr').get();
			var direction;
			if (direction == 'desc') {
				direction = -1;
				$(tab_header).closest('.ops_datagrid').find('tbody tr').each(function () {
					$(this).find('td.ordered_column').removeClass('ordered_column');
					$(this).find('td').eq(col_index).addClass('ordered_column');
				});
			} else if (direction == 'asc') {
				direction = 1;
				$(tab_header).closest('.ops_datagrid').find('tbody tr').each(function () {
					$(this).find('td.ordered_column').removeClass('ordered_column');
					$(this).find('td').eq(col_index).addClass('ordered_column');
				});
			}
			rows.sort(function (a, b) {
				if (datatype == 'number') {
					var numberA = parseInt($(a).children('td').eq(col_index).text());
					var numberB = parseInt($(b).children('td').eq(col_index).text());
					if (numberA < numberB) return -direction;
					if (numberA > numberB) return direction;
					return 0;
				} else if (datatype == 'ddMMMyy') {
					var dateA = new Date(getDateFromFormat($(a).children('td').eq(col_index).text(), 'dd MMM yy'));
					var dateB = new Date(getDateFromFormat($(b).children('td').eq(col_index).text(), 'dd MMM yy'));
					if (dateA < dateB) return -direction;
					if (dateA > dateB) return direction;
					return 0;
				} else if (datatype == 'ddMMMyyhhmm') {
					var dateA = new Date(getDateFromFormat($(a).children('td').eq(col_index).text(), 'dd MMM yy kk:mm'));
					var dateB = new Date(getDateFromFormat($(b).children('td').eq(col_index).text(), 'dd MMM yy kk:mm'));
					if (dateA < dateB) return -direction;
					if (dateA > dateB) return direction;
					return 0;
				} else if (datatype == 'btec') {
					var grades = new Array('D', 'M', 'P', 'F');
					var gradeAArray = $(a).children('td').eq(col_index).text().split('');
					var gradeBArray = $(b).children('td').eq(col_index).text().split('');
					for (i = 0; i < gradeAArray.length; i++) {
						gradeA = jQuery.inArray(gradeAArray[i], grades);
						gradeB = jQuery.inArray(gradeBArray[i], grades);
						if (gradeA < gradeB) { return direction; break; }
						if (gradeA > gradeB) { return -direction; break; }
					}
					return 0;
				} else {
					var keyA = $(a).children('td').eq(col_index).text();
					var keyB = $(b).children('td').eq(col_index).text();
					if (keyA < keyB) return -direction;
					if (keyA > keyB) return direction;
					return 0;
				}
			});
			$.each(rows, function (index, row) {
				table.children('tbody').append(row);
			});

		}

		function filtertable(table_id, field, terms) {
			var table = $('.ops_datagrid').eq(table_id);
			$(table).find('tbody > tr').show();
			$('.no_results').remove();

			if (!field) {
				return false;
			}

			$(table).find('th').each(function (index) {
				if ($(this).text() == field) {
					column_index = index;
				}
			});

			$(table).find('tbody > tr').each(function () {
				var td_content = $(this).children('td').eq(column_index).text();
				var keep_layer = 'false';
				for (i = 0; i < terms.length; i++) {
					if (td_content.toUpperCase().indexOf(terms[i].toUpperCase()) > -1) {
						keep_layer = 'true';
						return;
					}

				}
				if (keep_layer == 'false') {
					$(this).hide();
					toggleselect($(this), "unset");
				}
			});

			if ($(table).find('tbody > tr:visible').length == 0) {
				$(table).find('tbody').append("<tr class='no_results'><td colspan='100'>There are no search results. Please remove a filter to try again.</td></tr>");
			}

		}

		// Changes toggle state of given row
		function toggleselect(togglerow, state) {

			if ($(togglerow).find('.ops_datagrid_rowselect').length == 0) {
				return false;
			}

			if (state == "set") {
				$(togglerow).each(function () {
					$(this).addClass('checked');
				});
				$(togglerow).find('td > .ops_datagrid_rowselect').each(function () {
					$(this).attr('checked', 'true');
				});
			} else if (state == "unset") {
				$(togglerow).each(function () {
					$(this).removeClass('checked');
				});
				$(togglerow).find('td > .ops_datagrid_rowselect').each(function () {
					$(this).attr('checked', '');
				});
			} else if (state == "toggle") {
				if ($(togglerow).hasClass('checked')) {
					$(togglerow).each(function () {
						$(this).removeClass('checked');
					});
					$(togglerow).find('td > .ops_datagrid_rowselect').each(function () {
						$(this).attr('checked', '');
					});
				} else {
					$(togglerow).each(function () {
						$(this).addClass('checked');
					});
					$(togglerow).find('td > .ops_datagrid_rowselect').each(function () {
						$(this).attr('checked', 'true');
					});
				}
			}
			if ($(togglerow).parent().children('tr').length == $(togglerow).parent().children('.checked').length) {
				$(togglerow).closest('.ops_datagrid').find('.ops_datagrid_options_selections_icon_all').addClass('checked').attr('src', 'Static/Icons/C/checkbox_checked.png');
			} else {
				$(togglerow).closest('.ops_datagrid').find('.ops_datagrid_options_selections_icon_all').removeClass('checked').attr('src', 'Static/Icons/C/checkbox_empty.png');
			}
		}

		function update_checkbox() {
			if ($('.ops_datagrid_dropdown_filtering_checkbox_option').length == $('.ops_datagrid_dropdown_filtering_checkbox_option:checked').length) {
				$('.ops_datagrid_dropdown_filtering_checkbox_all').attr('checked', 'true');
			} else {
				$('.ops_datagrid_dropdown_filtering_checkbox_all').attr('checked', '');
			}
		}

		function close_dropdown() {
			$('.ops_datagrid_dropdown').animate({ opacity: 0 }, 200, function () {
				$('.ops_datagrid_dropdown').remove();
				dropdown_open = -1;
			});
		}
	}

});


})(jQuery);