/*global document, tab_state, window */

function SearchPane() {
	this.errors = [];

	this.errorString = "";

	SearchPane.instance = this;
}

//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------

/**
 * Error messages
 */
SearchPane.beginDateAfterEndDate = "SearchPane.beginDateAfterEndDate";
SearchPane.noCategoriesSelected = "SearchPane.noCategoriesSelected";
SearchPane.searchEmptyMessage = "SearchPane.searchEmptyMessage";
SearchPane.searchFieldEmpty = "SearchPane.searchFieldEmpty";

SearchPane.currentYear = new Date().getFullYear();
SearchPane.minYear = "<<uninitialized>>";
SearchPane.invalidTitle = "<<uninitialized>>";
SearchPane.invalidMsg = "<<uninitialized>>";
SearchPane.startYearLength = "<<uninitialized>>";
SearchPane.endYearLength = "<<uninitialized>>";
SearchPane.earliestStartYear = "<<uninitialized>>";
SearchPane.earliestEndYear = "<<uninitialized>>";
SearchPane.latestStartYear = "<<uninitialized>>";
SearchPane.latestEndYear = "<<uninitialized>>";

/**
 * The single instance of the searchPane object
 */
SearchPane.instance = null;

/**
 * regexp for empty field expression test.
 */
SearchPane.emptyString = /^\s*$/;

/**
 * Initializes the search pane following load
 * @param {Object} config contains the data to initialize the search pane.
 */
SearchPane.prototype.init = function(config) {
	// Adds an onclick handler
	var add_onclick = function(tabName) {
		return function() {
			SearchPane.switchTabs(tabName);
			return false;
		};
	};

	var i, eles;

	if (config.startYear) {
		SearchPane.minYear = config.startYear;
	}

	if (config.showSimpleSearch) {
		eles = YAHOO.util.Dom.getElementsByClassName('simpleToggle');
		for (i = 0; i < eles.length; i++) {
			eles[i].onclick = add_onclick('simple');
		}

		eles = YAHOO.util.Dom.getElementsByClassName('advancedToggle');
		for (i = 0; i < eles.length; i++) {
			eles[i].onclick = add_onclick('advanced');
		}
	}

	g_collectionTreeManager.setupCategoryTree(config.expandAllCategories);

	//Set the tab order of the form elements
	eles = document.getElementById("search").elements;
	for (i = 0; i < eles.length; ++i) {
		eles[i].tabIndex = i;
	}

	this.focusOnSearch();
};

/**
 * Set focus on the first search field.
 */
SearchPane.prototype.focusOnSearch = function() {
	if (tab_state == "simple") {
		document.getElementById("search_terms").focus();
	} else {
		// Find the first input element in the form and set focus to it
		var formElements = document.search.elements;
		for ( var i = 0; i < formElements.length; ++i) {
			if (formElements[i].type == "text") {
				formElements[i].focus();
				break;
			}
		}
	}
};

/**
 * add an error the the array of errors to display.
 * @param errorMessage the error message to add
 */
SearchPane.prototype.addError = function(errorMessage) {
	this.errors.push(errorMessage);
};

/**
 * An associative array that contains the name of test elements to ignore when
 * determininng if at least one field is filled out
 */
SearchPane.textElementsToIgnore = {
	"toYear" : "toYear",
	"fromYear" : "fromYear",
	"alertName" : "alertName",
	"description" : "description",
	"frequency.multiplier" : "frequency.multiplier"
};

/**
 * Ensure that at least one of the required fields is filled out.
 * @param errors object to add errors to if any have occurred
 * @param form the form to validate against
 */
SearchPane.prototype.atLeastOne = function(form) {
	var isNoSearchTerms = true;
	var formElements = form.elements;
	for ( var i = 0; i < formElements.length; ++i) {
		if (formElements[i].type == "text") {
			if (typeof SearchPane.textElementsToIgnore[formElements[i].name] != "undefined") {
				continue;
			}

			isNoSearchTerms &= SearchPane.emptyString
					.test(formElements[i].value);
			if (!isNoSearchTerms) {
				break;
			}
		}
	}

	if (isNoSearchTerms) {
		this.addError(SearchPane.searchEmptyMessage);
	}
};

/**
 * Determines if any of the checkboxes in the search form are checked
 */
SearchPane.prototype.areAnyCollectionsChecked = function() {
	if (!g_collectionTreeManager.areAnyChecked()) {
		this.addError(SearchPane.noCategoriesSelected);
	}
};

/**
 * Validates the single field in a simple search form
 * @param requiredElementId the id of the single field that would contain the term to search for.
 * @return true if the data in the form is valid, false otherwise
 */
SearchPane.prototype.validateSimpleSearch = function(requiredElementId) {
	var isValid = true;
	var simpleSearchInput = document.getElementById(requiredElementId);

	if (ValidationUtils.isBlank(simpleSearchInput.value)) {
		MessageBox.error(SearchPane.invalidTitle, SearchPane.invalidMsg);
		isValid = false;
	}

	return isValid;
};

/**
 * Validates the elements in the advanced search form
 * @param form the form to validate
 * @param displayAlert true if an alert should be displayed to the user on error. [optional, default = true]
 * @return true if the data in the form is valid, false otherwise
 */
SearchPane.prototype.validateAdvancedSearch = function(form, displayAlert) {
	var i;
	var isValid = true;

	if (typeof (displayAlert) == "undefined") {
		displayAlert = true;
	}

	// Reset the errors array
	this.errors = [];

	this.atLeastOne(form);

	this.validateDates();

	this.areAnyCollectionsChecked();

	if (this.errors.length > 0) {
		this.errorString = "";
		for (i = 0; i < this.errors.length; ++i) {
			this.errorString += this.errors[i];
			this.errorString += '<br/>';
		}

		if (displayAlert) {
			MessageBox.error(SearchPane.invalidTitle, this.errorString);
		}

		isValid = false;
	}

	return isValid;
};

/**
 * Determines if the date field element is valid.  The criteria is that it exists
 * and it is a text input field
 * @param ele the element to check
 * @return true if valid, false otherwise
 */
SearchPane.prototype.isValidDateElement = function(ele) {
	return (ele !== null) && (ele.tagName == "input") && (ele.type == "text");
};

/**
 * Performs validation on the date field elements, if they exist.
 * Adds an error to the errors array if the date fields do not contain valid dates
 */
SearchPane.prototype.validateDates = function() {
	var a = document.getElementById('fromYear');
	var b = document.getElementById('toYear');

	if (!a || !b) {
		return true;
	}

	// Validate each field
	this.dateFieldIsValid(a);
	this.dateFieldIsValid(b);

	if (a.value !== "" && b.value !== "" && a.value > b.value) {
		this.addError(SearchPane.beginDateAfterEndDate);
	}
};

/**
 * Performs validation on each date field
 * Adds an error to the errors array if the date field does not contain valid dates
 * @param field the field to validate
 */
SearchPane.prototype.dateFieldIsValid = function(field) {
	var value = field.value;

	if (value.length === 0) {
		// empty fields are fine
	} else if (!value.match(/^[0-9]{4}$/)) {
		if (field.id == 'fromYear') {
			this.addError(SearchPane.startYearLength);
		} else {
			this.addError(SearchPane.endYearLength);
		}
	} else if (value < SearchPane.minYear) {
		if (field.id == 'fromYear') {
			this.addError(SearchPane.earliestStartYear + ' '
					+ SearchPane.minYear);
		} else {
			this
					.addError(SearchPane.earliestEndYear + ' '
							+ SearchPane.minYear);
		}
	} else if (value > SearchPane.currentYear) {
		if (field.id == 'fromYear') {
			this.addError(SearchPane.latestStartYear + ' '
					+ SearchPane.currentYear + '.');
		} else {
			this.addError(SearchPane.latestEndYear + ' '
					+ SearchPane.currentYear + '.');
		}
	}
};

/**
 * Switches between the advanced and simple search.
 * @param caller the tab being clicked
 */
SearchPane.switchTabs = function(caller) {
	var simpleElements = YAHOO.util.Dom.getElementsByClassName('simpleElement');
	var advancedElements = YAHOO.util.Dom
			.getElementsByClassName('advancedElement');

	if (caller == tab_state) {
		return;
	}
	switch (caller) {
	case ('simple'):
		// switch to simple
		SearchPane.switchState(advancedElements, false);
		SearchPane.switchState(simpleElements, true);
		break;
	case ('advanced'):
		// switch to advanced
		SearchPane.switchState(simpleElements, false);
		SearchPane.switchState(advancedElements, true);
		break;
	}
	tab_state = caller;
	SearchPane.instance.focusOnSearch();
};

/**
 * Switches the state of each element in an array
 * @param elements array of elements to be switched
 * @param isSelected boolean flag for which "direction" to switch the elements
 */
SearchPane.switchState = function(elements, isSelected) {
	for (i = 0; i < elements.length; i++) {
		if (isSelected) {
			YAHOO.util.Dom.removeClass(elements[i], 'Removed');
			YAHOO.util.Dom.addClass(elements[i], 'Selected');
		} else {
			YAHOO.util.Dom.removeClass(elements[i], 'Selected');
			YAHOO.util.Dom.addClass(elements[i], 'Removed');
		}
	}
};

