/**
* Provides a framework for the ST Subscription Process. Note that this requires
* Prototype 1.6.0.2+
*
* @author Duc Tri Le
*/
var STSub = Class.create({
	RequiredFields: [],
	validate_product_selections: null,

	/**
	 * Constructor: Will set up all necessary monitoring events.
	 *
	 * @param array		required_fields		An array of required fields.
	 * @param string	product_selection	The production selection function to
	 *		use to validate. Possible values are "step1", "step2+3", "step4".
	 *		Default to "step1".
	 * @param array		other				Optional. Array containing any other
	 *		data that this script should known about. Currently, this is used
	 *		for "step4" which needs the subproduct count.
	 * @return STSub
	 */
	initialize: function(required_fields, product_selection, other) {
		// Store the required fields
		this.RequiredFields = required_fields;

		// Set the function for the product selection
		if(product_selection == 'step2+3') {
			this.validate_product_selections = this.validate_product_selections_2;
		} else if(product_selection == 'step4') {
			this.validate_product_selections = this.validate_product_selections_4.bind(this, other[0]);
		} else {
			this.validate_product_selections = this.validate_product_selections_1;
		}

		// Set up the events for the required fields upon page load
		Event.observe(window, 'load', this.set_events.bind(this));
	},

	/**
	 * Display the error message.
	 *
	 * @param object    field       The field that generated the error message.
	 * @param string    message     The error message.
	 * @return void
	 */
	display_field_error: function(field, message) {
		var error_div = $('error'+field.name);
		if(error_div) {
			error_div.update(message);

			if(message.empty()) {
				error_div.setStyle({display: 'none'});
			} else {
				//error_div.show(); // Can't use this since display property is set in stylesheet
				error_div.setStyle({display: 'block'});
			}
		}
	},

	/**
	 * Clears and hide the main error field.
	 *
	 * @return void
	 */
	hide_main_error: function() {
		var element = $('mainerror');
		if(element) {
			element.update('').setStyle({display: 'none'});
		}
	},

	/**
	 * Set the necessary events for the required fields.
	 *
	 * @return void
	 */
	set_events: function() {
		var field;

		// For each required fields, set up the event for each required fields
		for(var i = 0; i < this.RequiredFields.length; ++i) {
			// Make sure that the element exists
			if(field = $(this.RequiredFields[i])) {
				// Set the blur event
				Event.observe(field, 'blur', this.validate_required_field.bind(this));

				// Set the change event if necessary
				if(field.type == 'select-one') {
					Event.observe(field, 'change', this.validate_required_field.bind(this));
				}
			}
		}
	},

	/**
	 * Validate the given form.
	 *
	 * @param object    form    The form to validate.
	 * @return boolean  Returns true if validation pass, false otherwise.
	 */
	validate_form: function(form) {
		var is_error = false;

		// Validate the require fields
		var field;
		for(var i = 0; i < this.RequiredFields.length; ++i) {
			field = $(this.RequiredFields[i]);
			if(field) {
				if(!this.validate_required_field(field)) {
					is_error = true;
				}
			}
		}

		// Make sure product/subproduct selections are ok
		if(!is_error && !this.validate_product_selections(form)) {
			is_error = true;
		}

		// If there is an error, let the user known
		if(is_error) {
			this.hide_main_error();
			window.alert('There were errors with your submission. Please see specific errors in red above.');

			return false;
		} else {
			var submit_button = $('submit_button');
			if(submit_button) {
				submit_button.disabled = true;
			}

			return true;
		}
	},

	/**
	 * Validate the production selections - Step 1.
	 *
	 * @param object    form    The submission form.
	 * @return boolean  Returns true if pass validation, false otherwise.
	 */
	validate_product_selections_1: function(form) {
		var message = '';
		var email = form.elements['email'].value;
		var product_id = form.elements['product'].value;
		var subproduct_select = $('productSelect' + product_id);

		if(subproduct_select) {
			// Make sure they selected at least one
			if(subproduct_select.value <= 0) {
				message = 'Please select at least one option from the box below.';
			}

			// Make sure they select no more than 20
			var num_selected = 0;
			for(var i = 0; i < subproduct_select.length; ++i) {
				if(subproduct_select.options[i].selected) {
					++num_selected;
				}
			}
			if(num_selected > 20 && !isSTMEmail(email)) {
				message = 'You may only subscribe to 20 newsletters.';
			}
		}

		if(!message.empty()) {
			if(error_element) { // Exactly where is this being declared?
				error_element.update(message).setStyle({display: 'block'});
			} else {
				window.alert(message);
			}

			return false;
		}

		return true;
	},

	/**
	 * Validate the production selections - Step 2.
	 *
	 * @param object    form    The submission form.
	 * @return boolean  Returns true if pass validation, false otherwise.
	 */
	validate_product_selections_2: function(form) {
		var index, product_id, error_element, subproduct_select;

		for(var i = 0; i < form.elements.length; ++i) {
			index = form.elements[i].id.indexOf('userproducts');
			if(index == 0) {
				// 'product' is 7 chars long; productid follows that in the id string
				product_id = form.elements[i].id.substr(12);

				error_element = $('productError' + product_id);
				subproduct_select = $('productSelect' + product_id);
				if(subproduct_select && form.elements[i].checked  && (subproduct_select.value <= 0 || subproduct_select.value.empty())) {
						var header = $('userproductsLabel' + product_id);
						var product_label = header.innerHTML;

						var message = 'Please select at least one option from the ' + product_label + ' box below, or uncheck the box above.';

						if (error_element) {
							error_element.update(message).setStyle({display: 'block'});
						} else {
							window.alert(message);
						}

						return false;
				} else {
					if (error_element) {
						error_element.update('').setStyle({display: 'none'});
					}
				}
			}
		}

		return true;
	},

	/**
	 * Validate the production selections - Step 4.
	 *
	 * @param int		subproduct_count	Count of the subproduct.
	 * @param object    form    			The submission form.
	 * @return boolean  Returns true if pass validation, false otherwise.
	 */
	validate_product_selections_4: function(subproduct_count, form) {
		var num_selected = 0;
		var message = '';
		var email = form.elements['email'].value;

		var checkbox_name, user_cities, j;
		for(var i = 0; i < form.elements.length; ++i) {
			checkbox_name = form.elements[i].name.substring(0,(form.elements[i].name.length)-2);
			if(checkbox_name == 'userproducts') {
				if(form.elements[i].checked) {
					++num_selected;

					if(form.elements[i].id == 'userproductsnl_product_lma') {
						user_cities = $('productSelectnl_product_lma');

						for(j = 0; j < user_cities.length; ++j) {
							if(user_cities.options[j].selected) {
								++num_selected;
							}
						}
					}
				}
			}
		}

		subproduct_count = subproduct_count + num_selected;

		if(subproduct_count > 20 && !isSTMEmail(email)) {
			message = 'You may only subscribe to 20 newsletters.'
			window.alert(message);

			return false;
		}

		return this.validate_product_selections_2(form);
	},

	/**
	 * Validate the required field.
	 *
	 * @param object    element     The element to validate or the event
	 *      containing the element
	 * @return boolean  Returns true if there isn't any error, false, otherwise.
	 */
	validate_required_field: function(element) {
		// Get the field
		var field;
		if(element.nodeType) {
			field = element;
		} else {
			field = element.element();
		}

		// Assume no error
		var is_error = false;

		// Begin validation
		if(((field.type == 'text') && (field.value.empty())) ||
		((field.type == 'select-one') && (field.options.selectedIndex == 0)) ||
		((field.type == 'checkbox') && !field.checked)) {
			is_error = true;
		}

		// Display the error message if there is an error
		if(is_error) {
			var message = '';

			// Get the label element
			var label_element = $('label'+field.name);
			if(label_element) {
				var field_display = label_element.innerHTML;
				var index = field_display.indexOf(':');
				if(index >= 0) {
					message = 'Please enter your '+field_display.substr(0, index);
				} else {
					message = 'Please enter your '+field_display;
				}
			} else {
				message = 'This field is required.';
			}

			this.display_field_error(field, message);
		}

		return !is_error;
	}
});