/*=============================================================================
 isInputValid(string input, string type, string compare)

 tests a string against a regular expression and bad value string

 Parameters:
	  input: (required) the string that will be checked for validity
	   type: (required) type of pattern to validate against
	compare: cannot be equal to this string

 Returns:
	true|false if input is valid
=============================================================================*/
function isInputValid(input, type, compare) {
	// optional parameters
	compare = (typeof compare === 'string') ? compare : '';

	var pattern;

	// pattern is different depending on the type
	switch (type.toLowerCase())
	{
	case 'date':
		pattern = /^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/;
		break;
	case 'fullname':
		pattern = /^[A-z., ]+$/;
		break;
	case 'email':
		pattern = /^[A-z0-9._-]+@([A-z0-9-]+\.)+[A-z0-9]{2,6}$/;
		break;
	case 'phone':
		pattern = /^[0-9]{10}$/;
		break;
	case 'address': case 'city': case 'description':
		pattern = /^.+$/;
		break;
	}

	// test for invalid input
	if (input.toLowerCase() === compare.toLowerCase() || !(new RegExp(pattern)).test(input)) {
		return false;
	}

	// input is valid
	return true;
}

/*=============================================================================
 validateInput(HTMLDOM elem, string compare)

 tests the input against different criteria based on the type then changes
 the related validation div to reflect it's validity 

 Parameters:
	   elem: (required) element that is being checked
	compare: string to compare input to

 Returns:
	  nothing
=============================================================================*/
function validateInput(elem, compare) {
	// optional parameters
	compare = (typeof compare === 'string') ? compare : '';

	var input = elem.value, type = elem.name;

	//
	// graphical notification
	//

	// clear the validity
	elem.className = elem.className.replace(/( (bad|good))/g, '');

	if (isInputValid(input, type, compare)) {
		elem.title = '';
		elem.className += ' good';
	} else {
		switch (type.toLowerCase())
		{
		case 'date':
			elem.title = 'The date must be in the format MM/DD/YYYY';
			break;
		case 'fullname':
			elem.title = 'Your name may only contain letters, periods (.), commas (,), and spaces';
			break;
		case 'email':
			elem.title = 'Your email address must be in the format:\n\njohndoe@example.com';
			break;
		case 'phone':
			elem.title = 'Your phone number must contain 10 digits';
			break;
		case 'address':
			elem.title = 'Please enter your address';
			break;
		case 'city':
			elem.title = 'Please enter your city';
			break;
		case 'description':
			elem.title = 'Please enter a description';
			break;
		}

		elem.className += ' bad';
	}
}

/*=============================================================================
 validateForm(DOMObject form)

 check all fields in a form for valid entries

 Parameters:
	form: (required) form element to be validated

 Returns:
	 true|false if all fields in form are valid
=============================================================================*/
function validateForm(form) {

	// go through each element in the form and validate it
	with (form) {
		switch(form.name)
		{
		case 'form_pudo':
			if (!pickup.checked && !dropoff.checked && !pickupclient.checked && !dropoffclient.checked) {
				alert('Please select whether this will be for pick-up or drop off.');
				return false;
			}

			if (!isInputValid(date.value, 'date', 'date')) {
				date.focus();
				alert('Please enter a date for pick up or drop off.\n\nThe date must be in the format MM/DD/YYYY');
				return false;
			}

			if (!isInputValid(fullname.value, 'name', 'full name')) {
				fullname.focus();
				alert('Please enter your name.\n\nYour name may only contain letters, periods (.), commas (,), and spaces');
				return false;
			}

			if (!isInputValid(email.value, 'email', 'email')) {
				email.focus();
				alert('Please enter your email address.\n\nYour email address must be in the format:\n\njohndoe@example.com');
				return false;
			}

			if (!isInputValid(phone.value, 'phone', 'phone')) {
				phone.focus();
				alert('Please enter your phone number.\n\nYour phone number must contain 10 digits');
				return false;
			}

			// only check these if pickup is selected
			if (pickupclient.checked || dropoffclient.checked) {
				if (!isInputValid(address.value, 'address', 'address')) {
					address.focus();
					alert('Please enter your address for drop off.');
					return false;
				}

				if (!isInputValid(city.value, 'city', 'city')) {
					city.focus();
					alert('Please enter your city for drop off.');
					return false;
				}
			}
			break;
		case 'form_signup':
			if (!isInputValid(fullname.value, 'name', 'full name')) {
				fullname.focus();
				alert('Please enter your name.\n\nYour name may only contain letters, periods (.), commas (,), and spaces');
				return false;
			}

			if (!isInputValid(email.value, 'email', 'email')) {
				email.focus();
				alert('Please enter your email address.\n\nYour email address must be in the format:\n\njohndoe@example.com');
				return false;
			}

			if (!isInputValid(phone.value, 'phone', 'phone')) {
				phone.focus();
				alert('Please enter your phone number.\n\nYour phone number must contain 10 digits');
				return false;
			}

			if (!isInputValid(address.value, 'address', 'address')) {
				address.focus();
				alert('Please enter your address for drop off.');
				return false;
			}

			if (!isInputValid(city.value, 'city', 'city')) {
				city.focus();
				alert('Please enter your city for drop off.');
				return false;
			}

			if (!isInputValid(item_description.value, 'description', '(Item, Year, Make, Model, Description)')) {
				item_description.focus();
				alert('Please enter a description about the item.');
				return false;
			}
			break;
		case 'form_estimate':
			if (!isInputValid(fullname.value, 'name', 'full name')) {
				fullname.focus();
				alert('Please enter your name.\n\nYour name may only contain letters, periods (.), commas (,), and spaces');
				return false;
			}

			if (!isInputValid(email.value, 'email', 'email')) {
				email.focus();
				alert('Please enter your email address.\n\nYour email address must be in the format:\n\njohndoe@example.com');
				return false;
			}

			if (!isInputValid(phone.value, 'phone', 'phone')) {
				phone.focus();
				alert('Please enter your phone number.\n\nYour phone number must contain 10 digits');
				return false;
			}

			if (!isInputValid(item_description.value, 'description', '(Item, Year, Make, Model, Description)')) {
				item_description.focus();
				alert('Please enter a description about the item.');
				return false;
			}

			if (!isInputValid(repair_description.value, 'description', 'Detailed description of what needs to be done')) {
				repair_description.focus();
				alert('Please enter a detailed description of the what needs to be done to the item.');
				return false;
			}
			break;
		}
	}

	// all fields are filled out
	return true;
}

/*=============================================================================
 sendEmail(HTMLDOM form)

 use AJAX to send an email

 Parameters:
	form: (required) form to submit

 Returns:
	nothing
=============================================================================*/
function sendEmail(form) {
	var httpObj = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'),		// cross-browser http object
		params = [];

	// stop if the form isn't filled out correctly
	if (!validateForm(form)) {
		return false;
	}

	// create the email
	with (form) {
		switch(form.name)
		{
		case 'form_pudo':
			if (pickup.checked) {
				params.push('subject=Pick-Up From Warehouse Request', 'email=' + email.value);
				params.push('msg=' +
					'Pick-Up From Warehouse Request\n\n' +
					'Name: ' + fullname.value + '\n' +
					'Email: ' + email.value + '\n' +
					'Phone: ' + phone.value + '\n\n' +
					'Date/Time: ' + date.value + ' ' + hour.value + ':' + minute.value + ' ' + meridiem.value
				);
			} else if (dropoff.checked) {
				params.push('subject=Drop Off At Warehouse Request', 'email=' + email.value);
				params.push('msg=' +
					'Drop Off At Warehouse Request\n\n' +
					'Name: ' + fullname.value + '\n' +
					'Email: ' + email.value + '\n' +
					'Phone: ' + phone.value + '\n\n' +
					'Date/Time: ' + date.value + ' ' + hour.value + ':' + minute.value + ' ' + meridiem.value
				);
			} else if (pickupclient.checked) {
				params.push('subject=Pick-Up From Client Request', 'email=' + email.value);
				params.push('msg=' +
					'Pick-Up From Client Request\n\n' +
					'Name: ' + fullname.value + '\n' +
					'Email: ' + email.value + '\n' +
					'Phone: ' + phone.value + '\n\n' +
					'Date/Time: ' + date.value + ' ' + hour.value + ':' + minute.value + ' ' + meridiem.value + '\n' +
					'Address: ' + address.value + '\n' +
					'City: ' + city.value
				);
			} else if (dropoffclient.checked) {
				params.push('subject=Delivery To Client Request', 'email=' + email.value);
				params.push('msg=' +
					'Delivery To Client Request\n\n' +
					'Name: ' + fullname.value + '\n' +
					'Email: ' + email.value + '\n' +
					'Phone: ' + phone.value + '\n\n' +
					'Date/Time: ' + date.value + ' ' + hour.value + ':' + minute.value + ' ' + meridiem.value + '\n' +
					'Address: ' + address.value + '\n' +
					'City: ' + city.value
				);
			}
			
			break;
		case 'form_signup':
			params.push('subject=Sign Up for Services', 'email=' + email.value);
			params.push('msg=' +
				'Name: ' + fullname.value + '\n' +
				'Email: ' + email.value + '\n' +
				'Phone: ' + phone.value + '\n\n' +
				'Address: ' + address.value + '\n' +
				'City: ' + city.value + '\n' +
				'Item Description:\n' + item_description.value
			);

			break;
		case 'form_estimate':
			params.push('subject=Estimate Request', 'email=' + email.value);
			params.push('msg=' +
				'Name: ' + fullname.value + '\n' +
				'Email: ' + email.value + '\n' +
				'Phone: ' + phone.value + '\n\n' +
				'Item Description:\n' + item_description.value + '\n\n' +
				'Repair Description:\n' + repair_description.value
			);
			break;
		}
	}

	// create the request
	httpObj.open('POST', 'php/sendEmail.php', true);
	httpObj.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

	// receive the response
	httpObj.onreadystatechange = function () { if (httpObj.readyState === 4) {
		alert(httpObj.responseText);

		if (form.name === 'form_signup') {
			window.open('images/fullservicestoragecontract.pdf', 'Contract - Full Service Storage');
		}
	}};

	// send the request
	httpObj.send(params.join('&'));

	// always return false
	return false;
}

/*=============================================================================
 setCursorPos(HTMLDOM elem, int pos)

 set the cursor position in the element

 Parameters:
	elem: (required) element to move the cursor in
	pos: (required) where in the input box the cursor should go

 Returns:
	nothing
=============================================================================*/
function setCursorPos(elem, pos) {
	if (pos < 0) {
		pos = elem.value.length;
	}

	if (elem.createTextRange) {		// IE
		var range = elem.createTextRange();

		range.move('character', pos);
		range.select();
	} else if (elem.selectionStart) {		// everything else
		elem.setSelectionRange(pos, pos);
	}
}

/*=============================================================================
 reverseReplace(regexp needle, string newNeedle, string haystack)

 replaces the last occurance of needle in haystack with newNeedle

 Parameters:
	   needle: (required) what to replace
	newNeedle: (required) input element
	 haystack: (required) type of input mask used

 Returns:
	fixed string
=============================================================================*/
function reverseReplace(needle, newNeedle, haystack) {
	return haystack.split('').reverse().join('').replace(needle, newNeedle).split('').reverse().join('');
}

/*=============================================================================
 changeInput(event e, HTMLDOM elem, string type)

 changes the input based on the key pressed and type of input

 Parameters:
	   e: (required) event
	elem: (required) input element
	type: (required) type of input mask used

 Returns:
	nothing
=============================================================================*/
function setInput(e, elem, type) {
	var keyCode, cursorPos;

	if (window.event) {			// IE
		keyCode = e.keyCode
	} else if (e.which) {		// Netscape/Firefox/Opera
		keyCode = e.which
	}

	// escape if the tab key was pressed
	if (keyCode === 9) {
		return true;
	}

	// fix numpad craziness
	if (keyCode >= 96 && keyCode <= 105) {
		keyCode -= 48;
	}

	switch(type)
	{
	case 'phone':
		if (keyCode === 8) {
			// replace the last number with an x
			elem.value = reverseReplace(/[0-9]/, 'x', elem.value);

			// move the cursor to the first x
			setCursorPos(elem, elem.value.indexOf('x'));
		} else {
			if (keyCode >= 48 && keyCode <= 57) {		// numbers only
				// get position of first x
				cursorPos = elem.value.indexOf('x');

				// remove the first x
				elem.value = elem.value.replace('x', '');

				// move the cursor to where the first x used to be
				setCursorPos(elem, cursorPos);

				// input key that was pressed
				return true;
			}
		}

		break;
	}

	// don't input key that was pressed
	return false;
}

/*=============================================================================
 inputMask(string input, string type)

 wraps the input with a mask

 Parameters:
	input: (required) input string
	 type: (required) type of input mask to use

 Returns:
	the formatted input
=============================================================================*/
function inputMask(input, type) {
	var formatted = removeInputMask(input, type).split('');

	switch(type)
	{
	case 'phone':
		// fill missing number with x's
		for (var i = formatted.length; i < 10; i++) {
			formatted.push('x');
		}

		// add the separators
		formatted.splice(0, 0, '(');
		formatted.splice(4, 0, ')');
		formatted.splice(5, 0, ' ');
		formatted.splice(9, 0, '-');

		break;
	}

	return formatted.join('');
}

/*=============================================================================
 removeInputMask(string input, string type)

 removes an input mask

 Parameters:
	input: (required) input string
	 type: (required) type of input mask to remove

 Returns:
	the formatted input
=============================================================================*/
function removeInputMask(input, type) {
	switch(type)
	{
	case 'phone':
		return input.replace(/[x() -]/g, '');
	}
}

