var USA_ID = 204;

	// URL's for AJAX requests 
	var CHECK_NICKNAME_URL = "/registration/checkNickname.do";
	var CHECK_EMAIL_URL    = "/registration/checkEmail.do";
	var CHECK_ZIP_CODE_URL = "/registration/checkZipCode.do";
	
	// Status icons URL's
	var STATUS_ICON_OK_URL = "/images/field_ok.gif";
	var STATUS_ICON_ERROR_URL = "/images/field_error.gif";
	var STATUS_ICON_LOADING_URL = "/images/field_loading.gif";
	
	// Tip icons URL's
	var TIP_ICON_ACTIVE_URL = "/images/field_tip_active.gif"
	var TIP_ICON_PASSIVE_URL = "/images/field_tip_passive.gif"		
	
	// Form
	var FORM_ID = "RegistrationCommand";
	
	// Nickname html elements
	var NICKNAME_ID = "nick";	
	var NICKNAME_MESSAGE_ID = "nickname_message";	
	var NICKNAME_MESSAGE_CONTENT_ID = "nickname_message_content";
	var NICKNAME_STATUS_ID = "nickname_status";
	var NICKNAME_TIP_ID = "nickname_tip";

	// Password html elements
	var PASSWORD_ID = "pass";
	var PASSWORD_MESSAGE_ID = "password_message";	
	var PASSWORD_MESSAGE_CONTENT_ID = "password_message_content";
	var PASSWORD_STATUS_ID = "password_status";
	var PASSWORD_TIP_ID = "password_tip";

	// Email html elements
	var EMAIL_ID = "email";		
	var EMAIL_MESSAGE_ID = "email_message";	
	var EMAIL_MESSAGE_CONTENT_ID = "email_message_content";
	var EMAIL_STATUS_ID = "email_status";

	// ZipCode html elements
	var ZIP_CODE_ID = "zipCode";
	var ZIP_CODE_MESSAGE_ID = "zipCode_message"
	var ZIP_CODE_MESSAGE_CONTENT_ID = "zipCode_message_content"
	var ZIP_CODE_BLOCK_ID = "zipCodeBlock";

	// Birthdate
	var BIRTH_DATE_DAY_ID = "birthDateDay1";
	var BIRTH_DATE_MONTH_ID = "birthDateMonth1";
	var BIRTH_DATE_YEAR_ID = "birthDateYear1";
	var BIRTH_DATE_DAY_ID2 = "birthDateDay2";
	var BIRTH_DATE_MONTH_ID2 = "birthDateMonth2";
	var BIRTH_DATE_YEAR_ID2 = "birthDateYear2";
	var BIRTH_DATE_STATUS_ID = "birthDate_status";
	var BIRTH_DATE_STATUS_ID2 = "birthDate_status2";
	
	var BIRTH_DATE_DIV_ID2 = "birthdate2";
	
	var SEX_ID = "sexId";
	// Location
	var COUNTRIES_LIST_ID = "countryId";	
	var REGIONS_LIST_ID = "regionId";	
	var REGIONS_LIST_BLOCK_ID = "regionBlock";	
	var CITIES_LIST_ID = "cityId";
	var CITIES_LIST_BLOCK_ID = "cityBlock";	
	var LOCATION_STATUS_ID = "location_status";
	
	// Agree to TOS
	var AGREE_TO_TOS_ID = "agreeToTOS";

	// Regular expressions
	var REGEX_NICKNAME = /^[\d]{0,7}([-_a-zA-Z]{1,}[\d]{0,7}){1,}$/;
	var REGEX_PASSWORD = /^[a-zA-Z\d]*$/;
	var REGEX_PASSWORD_ONLY_DIGITS = /^[\d]*$/;	
	var REGEX_EMAIL    = /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*([,;]\s*\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)*/;	
	var REGEX_ZIP_CODE = /^\d{5}$/;	
	
	
	var ZIP_CODE_SIZE = 5;

	var AJAX_FORCED_DELAY = 700;
	var AJAX_MAXIMUM_DELAY = 7000;	
	
	var SETTINGS_APPEAR_EFFECT = {duration: 0.2};
	
	var SETTINGS_TIPS = {
		className: "RegistrationStep1_forIndex",
		fixed: true,
		target: true,
		autoOffset: false,
		offset: [20, 0],
		tipJoint: ['right', 'top'],
		delay: 0.2,
		hideDelay: 0.1,
		showEffectDuration: 0.2,
		hideEffectDuration: 0.2
	};
	
	
		
	// Field invalid values
	var invalidNickname = null;
	var invalidEmail = null;
	var invalidZipCode = null;
	
	// Messages
	var nicknameMessage = null;
	var passwordMessage = null;
	var emailMessage = null;
	var zipCodeMessage = null;
	
	// Field current values
	var nicknameValue = null;
	var emailValue = null;
	var zipCodeValue = null;
	
	var ajaxCheckNicknameAllowed = true;
	var ajaxCheckEmailAllowed = true;
	var ajaxCheckZipCodeAllowed = true;
	
	
	// ================== Nickname events :: BEGIN ==================
	
	function nicknameOnFocus() {
		showMessage(NICKNAME_MESSAGE_ID, NICKNAME_MESSAGE_CONTENT_ID, nicknameMessage);
	} 	
	
	function nicknameOnBlur() {
		hideMessage(NICKNAME_MESSAGE_ID);
		validateNickname();
	}

	function nicknameOnKeyPress() {
		hideMessage(NICKNAME_MESSAGE_ID);
	}
	
	// ================== Nickname events :: END ==================

	
	
	// ================== Password events :: BEGIN ==================
	
	function passwordOnFocus() {
		showMessage(PASSWORD_MESSAGE_ID, PASSWORD_MESSAGE_CONTENT_ID, passwordMessage);
	} 
	
	function passwordOnBlur() {
		hideMessage(PASSWORD_MESSAGE_ID);
		validatePassword();
	}

	function passwordOnKeyPress() {
		hideMessage(PASSWORD_MESSAGE_ID);
	}	
	
	// ================== Password events :: END ==================

	

	// ================== Email events :: BEGIN ==================
	
	function emailOnFocus() {
		showMessage(EMAIL_MESSAGE_ID, EMAIL_MESSAGE_CONTENT_ID, emailMessage);
	} 
	
	function emailOnBlur() {
		hideMessage(EMAIL_MESSAGE_ID);
		validateEmail();
	}

	function emailOnKeyPress() {
		hideMessage(EMAIL_MESSAGE_ID);
	}	
	
	// ================== Email events :: END ==================
	
	
	
	// ================== Zip Code events :: BEGIN ==================
	
	function zipCodeOnFocus() {
		showMessage(ZIP_CODE_MESSAGE_ID, ZIP_CODE_MESSAGE_CONTENT_ID, zipCodeMessage);
	} 
	
	function zipCodeOnBlur() {
		hideMessage(ZIP_CODE_MESSAGE_ID);
		validateZipCode();
	}

	function zipCodeOnKeyPress() {
		hideMessage(ZIP_CODE_MESSAGE_ID);
	}	
	
	// ================== Zip Code events :: END ==================	

	
	
	// ================== Birth date events :: BEGIN ==================
		
	function birthDateOnBlur() {
		adjustDays();
		validateBirthDate();
	}
	
	function birthDateYear1OnChange() {
		adjustDays();
		validateBirthDate();
	}
	
	function birthDateMonth1OnChange() {
		adjustDays();
		validateBirthDate();
	}
	
	function birthDateDay1OnChange() {
		validateBirthDate();
	}
	
	function birthDateOnBlur2() {
		adjustDays2();
		validateBirthDate2();
	}
	
	function birthDateYear2OnChange() {
		adjustDays2();
		validateBirthDate2();
	}
	
	function birthDateMonth2OnChange() {
		adjustDays2();
		validateBirthDate2();
	}
	
	function birthDateDay2OnChange() {
		validateBirthDate2();
	}
	
	// ================== Birth date events :: BEGIN ==================
	
	
	
	// ================== Location events :: BEGIN ==================
	
	function locationOnBlur() {
		validateLocation();
	}	
	
	function countryIdOnChange() {
		onCountryChange();
		validateLocation();
	}
	
	function regionIdOnChange() {
		onRegionChange();
		validateLocation();
	}

	function cityIdOnChange() {
		validateLocation();
	}
	
	// ================== Location events :: END ==================	
	
	
	
	
	// ================== Validation functions :: BEGIN ==================

	// Validate nickname.
	function validateNickname() {		
		var isAjaxRequestSent = false;
		var isValid = true;		
		var value = $F(NICKNAME_ID);

		// Check emptyness.
		if (value.blank()) {
			nicknameMessage = LL_ERROR_NICKNAME_INCORRECT;
			isValid = false;
		}
		
		// Check syntax
		else if (!REGEX_NICKNAME.test(value)) {
			nicknameMessage = LL_ERROR_NICKNAME_INCORRECT;
			isValid = false;
		}
		
		// Check min size
		else if (!(value.length >= NICKNAME_SIZE_MIN)) {
			nicknameMessage = LL_ERROR_NICKNAME_INCORRECT;
			isValid = false;
		}			
		
		// Check max size
		else if (!(value.length <= NICKNAME_SIZE_MAX)) {
			nicknameMessage = LL_ERROR_NICKNAME_INCORRECT;
			isValid = false;
		}	
		
		// Check for equality to nickname just checked using engine
		else if (value == invalidNickname) {
			isValid = false;
		}
		
		// Start engine checking
		else if (nicknameValue != value) {
			nicknameValue = value;
			checkNickname(value);
			isAjaxRequestSent = true;
		}
		
		if (!isAjaxRequestSent) {	
			if (isValid) {
				setNicknameValid();
			} else {
				showStatusIcon(NICKNAME_STATUS_ID, STATUS_ICON_ERROR_URL); 			
			}		
		}

		return isValid && !isAjaxRequestSent;
	
	}
	
	// Validate password.
	function validatePassword() {
		var isAjaxRequestSent = false;
		var isValid = true;		
		var value = $F(PASSWORD_ID);	
		var nickname = $F(NICKNAME_ID);
		var email = $F(EMAIL_ID);
		
		// Check emptyness.
		if (value.blank()) {
			passwordMessage = LL_ERROR_PASSWORD_INCORRECT;
			isValid = false;
		}

		// Check syntax
		else if (!REGEX_PASSWORD.test(value)) {
			passwordMessage = LL_ERROR_PASSWORD_INCORRECT;
			isValid = false;
		}		
		
		// Check for digits-only passwords
		/*else if (REGEX_PASSWORD_ONLY_DIGITS.test(value)) {
			passwordMessage = LL_ERROR_PASSWORD_NOT_SECURE;
			isValid = false;
		}*/		
		
		// Check min size
		else if (!(value.length >= PASSWORD_SIZE_MIN)) {
			passwordMessage = LL_ERROR_PASSWORD_NOT_SECURE;
			isValid = false;
		}			
		
		// Check max size
		else if (!(value.length <= PASSWORD_SIZE_MAX)) {
			passwordMessage = LL_ERROR_PASSWORD_INCORRECT;
			isValid = false;
		}		

		// Check equality to nickname		
		else if (value == nickname) {
			passwordMessage = LL_ERROR_PASSWORD_IS_NICK;
			isValid = false;
		}			
		
		// Check equality to email		
		else if (value == email) {
			passwordMessage = LL_ERROR_PASSWORD_IS_EMAIL;
			isValid = false;
		}		
		
		if (isValid) {
			setPasswordValid();
		} else {
			showStatusIcon(PASSWORD_STATUS_ID, STATUS_ICON_ERROR_URL);
		}	

	return isValid;
	
	}
	
	// Validate email.
	function validateEmail() {
		var isAjaxRequestSent = false;
		var isValid = true;		
		var value = $F(EMAIL_ID);		

		// Check emptyness.
		if (value.blank()) {
			emailMessage = LL_ERROR_EMAIL_INCORRECT;
			isValid = false;
		}

		// Check syntax
		else if (!REGEX_EMAIL.test(value)) {
			emailMessage = LL_ERROR_EMAIL_INCORRECT;
			isValid = false;
		}
		
		// Check max size
		else if (!(value.length <= EMAIL_SIZE_MAX)) {
			emailMessage = LL_ERROR_EMAIL_INCORRECT;
			isValid = false;
		}			

		// Check for equality to email just checked using engine
		else if (value == invalidEmail) {
			isValid = false;
		}						
		
		// Start engine checking
		else if (emailValue != value) {		
			emailValue = value;
			checkEmail(value);			
			isAjaxRequestSent = true;
		}
		
		if (!isAjaxRequestSent) {	
			if (isValid) {
				setEmailValid();
			} else {
				showStatusIcon(EMAIL_STATUS_ID, STATUS_ICON_ERROR_URL); 			
			}		
		}
		
		return isValid && !isAjaxRequestSent;

	}
	
	// Validate zip code.
	function validateZipCode() {
		var isAjaxRequestSent = false;
		var isValid = true;
		var value = $F(ZIP_CODE_ID);

		// Check emptyness.
		if (value.blank()) {
			zipCodeMessage = LL_ERROR_ZIP_CODE_INCORRECT;
			isValid = false;
		}

		// Check syntax
		else if (!REGEX_ZIP_CODE.test(value)) {
			zipCodeMessage = LL_ERROR_ZIP_CODE_INCORRECT;
			isValid = false;
		}
		
		// Check size
		else if (value.length != ZIP_CODE_SIZE) {
			zipCodeMessage = LL_ERROR_ZIP_CODE_INCORRECT;
			isValid = false;
		}			

		// Check for equality to zip just checked using engine
		else if (value == invalidZipCode) {
			isValid = false;
		}						
		
		// Start engine checking
		else if (zipCodeValue != value) {
			zipCodeValue = value;
			checkZipCode(value);
			isAjaxRequestSent = true;
		}
		
		if (!isAjaxRequestSent) {
			if (isValid) {
				if (!$(ZIP_CODE_ID).disabled){				
					setZipCodeValid();
				}
				else{
					return false;
				}
			} else {
				showStatusIcon(LOCATION_STATUS_ID, STATUS_ICON_ERROR_URL); 			
			}		
		}
		
		return isValid && !isAjaxRequestSent;
	
	}
	
	// Validate birth date.
	function validateBirthDate() {	
		var isValid = validateBirthDay() && validateBirthMonth() && validateBirthYear();		
		
		if (isValid) {
			showStatusIcon(BIRTH_DATE_STATUS_ID, STATUS_ICON_OK_URL);
		} else {
			showStatusIcon(BIRTH_DATE_STATUS_ID, STATUS_ICON_ERROR_URL);
		}
		
		return isValid;
		
	}
	
	function validateBirthDate2() {	
		var isValid = validateBirthDay2() && validateBirthMonth2() && validateBirthYear2();		
		
		if (isValid) {
			showStatusIcon(BIRTH_DATE_STATUS_ID2, STATUS_ICON_OK_URL);
		} else {
			showStatusIcon(BIRTH_DATE_STATUS_ID2, STATUS_ICON_ERROR_URL);
		}
		
		return isValid;
		
	}
	
	// Validate birth day.	
	function validateBirthDay() {
		var daysList = $(BIRTH_DATE_DAY_ID);
		var day;
		
		if (daysList.selectedIndex < 0) {
			day = 0;
		} else {
			day = daysList.options[daysList.selectedIndex].value;
		}
							
		return !isNullOrZero(day);
		
	}
		
	// Validate birth month.	
	function validateBirthMonth() {
		var monthesList = $(BIRTH_DATE_MONTH_ID);
		var month;
			
		if (monthesList.selectedIndex < 0) {
			month = 0;
		} else {
			month = monthesList.options[monthesList.selectedIndex].value;
		}		

		return !isNullOrZero(month);
		
	}

	// Validate birth year.
	function validateBirthYear() {
		var yearsList = $(BIRTH_DATE_YEAR_ID);		
		var year;
		
		if (yearsList.selectedIndex < 0) {
			year = 0;
		} else {
			year = yearsList.options[yearsList.selectedIndex].value;
		}
		
		return !isNullOrZero(year);
		
	}	
	
	// Validate birth day.	
	function validateBirthDay2() {
		var daysList = $(BIRTH_DATE_DAY_ID2);
		var day;
		
		if (daysList.selectedIndex < 0) {
			day = 0;
		} else {
			day = daysList.options[daysList.selectedIndex].value;
		}
							
		return !isNullOrZero(day);
		
	}
		
	// Validate birth month.	
	function validateBirthMonth2() {
		var monthesList = $(BIRTH_DATE_MONTH_ID2);
		var month;
			
		if (monthesList.selectedIndex < 0) {
			month = 0;
		} else {
			month = monthesList.options[monthesList.selectedIndex].value;
		}		

		return !isNullOrZero(month);
		
	}

	// Validate birth year.
	function validateBirthYear2() {
		var yearsList = $(BIRTH_DATE_YEAR_ID2);		
		var year;
		
		if (yearsList.selectedIndex < 0) {
			year = 0;
		} else {
			year = yearsList.options[yearsList.selectedIndex].value;
		}
		
		return !isNullOrZero(year);
		
	}	
	
	// Validate location.
	function validateLocation() {
		var isValid = validateCountry();		
		var isUsa = isUsaSelected();
		var isValidZipCode = true;
		
		if (isValid) {
			if (isUsa) {
				isValidZipCode = validateZipCode();
				isValid = isValid && isValidZipCode;
			} else {
				isValid = isValid && validateRegion();
				isValid = isValid && validateCity();			
			}
		}
		
		if (isValidZipCode) {
			if (isValid) {
				showStatusIcon(LOCATION_STATUS_ID, STATUS_ICON_OK_URL);
			} else {
				showStatusIcon(LOCATION_STATUS_ID, STATUS_ICON_ERROR_URL);
			}
		}
		
		return isValid;
			
	}
	
	// Validate country.
	function validateCountry() {
		var countriesList = $(COUNTRIES_LIST_ID);
		var country;
		
		if (countriesList.selectedIndex < 0) {
			country = 0;
		} else {
			country = countriesList.options[countriesList.selectedIndex].value;
		}
		
		return !isNullOrZero(country);
		
	}

	// Validate region.
	function validateRegion() {
		var regionsList = $(REGIONS_LIST_ID);
		var countriesList = $(COUNTRIES_LIST_ID);
		var citiesList = $(CITIES_LIST_ID);	
		var region;
		
		if (regionsList.selectedIndex < 0) {
			region = 0;
		} else {
			region = regionsList.options[regionsList.selectedIndex].value;
		}

		if (regionsList.selectedIndex < 0 && countriesList.selectedIndex >= 0 && citiesList.selectedIndex >= 0)
		return true;
		else
		return !isNullOrZero(region);
		
	}

	// Validate location.
	function validateCity() {
		var citiesList = $(CITIES_LIST_ID);		
		var city;
		
		if (citiesList.selectedIndex < 0) {
			city = 0;
		} else {
			city = citiesList.options[citiesList.selectedIndex].value;
		}
		
		return !isNullOrZero(city);
		
	}	
	
	// Validate agree to TOS.
	function validateAgreeToTos() {
		var isValid = $(AGREE_TO_TOS_ID).checked;
		
		return isValid;
		
	}

	// ================== Validation functions :: END ==================
	
	
	// Set nickname as valid.
	function setNicknameValid() {
		nicknameMessage = null;
		invalidNickname = null;
		showStatusIcon(NICKNAME_STATUS_ID, STATUS_ICON_OK_URL);	
	}
	
	// Set password as valid.
	function setPasswordValid() {
		passwordMessage = null;
		showStatusIcon(PASSWORD_STATUS_ID, STATUS_ICON_OK_URL);	
	}	
		
	// Set email as valid.
	function setEmailValid() {
		emailMessage = null;
		invalidEmail = null;
		showStatusIcon(EMAIL_STATUS_ID, STATUS_ICON_OK_URL);	
	}	
	
	// Set zip code as valid.
	function setZipCodeValid() {
		zipCodeMessage = null;
		invalidZipCode = null;
		showStatusIcon(LOCATION_STATUS_ID, STATUS_ICON_OK_URL);	
	}		
	
	
	
	// Show status icon.
	//    id - id of the image html element.
	//    url - url of the new image.	
	function showStatusIcon(id, url) {
		var element = $(id);

		element.style.display = "block";
		element.src = url;
	}
	
	
	// Show message.
	//    id - id of the message's element.
	//    contentId - id of the html element, where to put message's content.
	//    message - text to show.
	function showMessage(id, contentId, message) {
		hideAllMessages();
		if (message != null) {
			$(contentId).innerHTML = message;
			Effect.Appear(id, SETTINGS_APPEAR_EFFECT);
		}
	}

	// Hide message.
	//    id - id of the message's element.	
	function hideMessage(id) {
		$(id).style.display = 'none';
	}

	// Hide all currently visible messages.
	function hideAllMessages() {
		hideMessage(NICKNAME_MESSAGE_ID);
		hideMessage(PASSWORD_MESSAGE_ID);
		hideMessage(EMAIL_MESSAGE_ID);
		hideMessage(ZIP_CODE_MESSAGE_ID);	
	}	
	
	
	// Set visual status of checking nickname with Ajax (show/hide html elements etc).
	//    flag - true/false.
	function setCheckNicknameStatus(flag) {
		if (flag) {
			showStatusIcon(NICKNAME_STATUS_ID, STATUS_ICON_LOADING_URL);
			$(NICKNAME_ID).disabled = true;
			ajaxCheckNicknameAllowed = true;
		} else {
			$(NICKNAME_ID).disabled = false;
			ajaxCheckNicknameAllowed = false;
		}
	}
	

	// Set visual status of checking email with Ajax (show/hide html elements etc).
	//    flag - true/false	
	function setCheckingEmailStatus(flag) {
		if (flag) {
			showStatusIcon(EMAIL_STATUS_ID, STATUS_ICON_LOADING_URL);
			$(EMAIL_ID).disabled = true;
			ajaxCheckEmailAllowed = true;
		} else {
			$(EMAIL_ID).disabled = false;
			ajaxCheckEmailAllowed = false;
		}
	}
	
	
	// Set visual status of checking zip code with Ajax (show/hide html elements etc).
	//    flag - true/false	
	function setCheckingZipCodeStatus(flag) {
		if (flag) {		
			showStatusIcon(LOCATION_STATUS_ID, STATUS_ICON_LOADING_URL);
			$(ZIP_CODE_ID).disabled = true;
			ajaxCheckZipCodeAllowed = true;
		} else {
			$(ZIP_CODE_ID).disabled = false;
			ajaxCheckZipCodeAllowed = false;
		}
	}
	
	
	// Do all logic when user select USA as a country.
	function doUsaSelectionLogic() {			
		if (isUsaSelected()) {
			onUsaSelected();
		} else {
			onUsaNotSelected();
		}
	}
	
	// Check is USA selected as a country.
	function isUsaSelected() {
		var countriesList = $(COUNTRIES_LIST_ID);			
		
		countryId = countriesList.options[countriesList.selectedIndex].value;
		return countryId == USA_ID;
	}
	
	// Show/hide html components when USA selected.
	function onUsaSelected() {	
		var citiesBlock = $(CITIES_LIST_BLOCK_ID);
		var regionsBlock = $(REGIONS_LIST_BLOCK_ID);
		var citiesList = $(CITIES_LIST_ID);
		var regionsList = $(REGIONS_LIST_ID);
		var zipCodeBlock = $(ZIP_CODE_BLOCK_ID);
		var zipCode = $(ZIP_CODE_ID);		
			
		citiesBlock.style.display = "none";
		regionsBlock.style.display = "none";
		citiesList.style.display = "none";
		regionsList.style.display = "none";
		zipCode.style.display = "";
		zipCodeBlock.style.display = "";
		
	}
	

	// Show/hide html components when USA not selected.
	function onUsaNotSelected() {
		var citiesBlock = $(CITIES_LIST_BLOCK_ID);
		var regionsBlock = $(REGIONS_LIST_BLOCK_ID);
		var citiesList = $(CITIES_LIST_ID);
		var regionsList = $(REGIONS_LIST_ID);		
		var zipCodeBlock = $(ZIP_CODE_BLOCK_ID);
		var zipCode = $(ZIP_CODE_ID);
			
		citiesBlock.style.display = "";
		regionsBlock.style.display = "";
		citiesList.style.display = "";
		regionsList.style.display = "";
		zipCode.style.display = "none";
		zipCodeBlock.style.display = "none";
		
	}	

	
	// Check nickname in engine using AJAX.
	//    value - nickname value.
	function checkNickname(value) {
		var ajaxCheckNicknameTimeout = setTimeout("abortAjaxCheckNickname()", AJAX_MAXIMUM_DELAY);	

		setCheckNicknameStatus(true);
	
		new Ajax.Request(CHECK_NICKNAME_URL, {
			method: "post",
			parameters: {nickname: value},
			onSuccess: function(transport) {				
				setTimeout(function() {
					var response = transport.responseText;

					clearTimeout(ajaxCheckNicknameTimeout);
					
					if (ajaxCheckNicknameAllowed && !response.blank()) {		
						invalidNickname = value;
						nicknameMessage = response;						
						validateNickname();
					} else {
						setNicknameValid();
					}
									
					setCheckNicknameStatus(false);
									
				}, AJAX_FORCED_DELAY);
			}		
		});	
	
    }
	
	
	// Check email in engine using AJAX.
	//    value - email value.	
	function checkEmail(value) {
		var ajaxCheckEmailTimeout = setTimeout("abortAjaxCheckEmail()", AJAX_MAXIMUM_DELAY);			
	
		setCheckingEmailStatus(true);		
	
		new Ajax.Request(CHECK_EMAIL_URL, {
			method: "post",
			parameters: {email: value},
			onSuccess: function(transport) {
				setTimeout(function() {			
					var response = transport.responseText;

					clearTimeout(ajaxCheckEmailTimeout);
								
					if (ajaxCheckEmailAllowed && !response.blank()) {
						invalidEmail = value;
						emailMessage = response;						
						validateEmail();										
					} else {
						setEmailValid();
					}					
					
					setCheckingEmailStatus(false);

				}, AJAX_FORCED_DELAY);

			}		
		});	
		
	}
	
	
	// Check zip code in engine using AJAX.
	//    value - zip code value.		
	function checkZipCode(value) {
		var ajaxCheckZipCodeTimeout = setTimeout("abortAjaxCheckZipCode()", AJAX_MAXIMUM_DELAY);			
		var countryIdValue = $F(COUNTRIES_LIST_ID);
		setCheckingZipCodeStatus(true);
				
		new Ajax.Request(CHECK_ZIP_CODE_URL, {
			method: "post",
			parameters: {zipCode: value, countryId: countryIdValue},
			onSuccess: function(transport) {
				setTimeout(function() {							
					var response = transport.responseText;
					
					clearTimeout(ajaxCheckZipCodeTimeout);					
					if (ajaxCheckZipCodeAllowed && !response.blank()) {
						invalidZipCode = value;
						zipCodeMessage = response;
						validateZipCode();
					} else {
						setZipCodeValid();
					}
					
					setCheckingZipCodeStatus(false);
				
				}, AJAX_FORCED_DELAY);					

			}		
		});			
		
	}
	
	
	// Abirt ajax nickname checking by setting correspondent flag and status.
	function abortAjaxCheckNickname() {
		setCheckNicknameStatus(false);
		setNicknameValid();
	}
	
	
	// Abirt ajax email checking by setting correspondent flag and status.
	function abortAjaxCheckEmail() {
		setCheckingEmailStatus(false);
		setEmailValid();
	}


	// Abirt ajax zip code checking by setting correspondent flag and status.
	function abortAjaxCheckZipCode() {
		setCheckingZipCodeStatus(false);
		setZipCodeValid();
	}		
	
	
	// Do all logic on country change.
	function onCountryChange() {		
		var component = $(COUNTRIES_LIST_ID);
		var callback;
		var countryId;
		var regionsList = $(REGIONS_LIST_ID);
		var citiesList = $(CITIES_LIST_ID);
		var isUsa;
		
		if (component.selectedIndex < 0) {
			countryId = 0;
		} else {
			countryId = component.options[component.selectedIndex].value;
		}
		
		doUsaSelectionLogic();
		isUsa = isUsaSelected();

		if (!isUsa) {
			onUsaNotSelected();
			regionsList = fastClearOptions(REGIONS_LIST_ID);
			regionsList.disabled = true;

			callback = function (count) {
				if (count > 1) {
					insertFirstOption(regionsList, MSG_CHOOSE_REGION, 0, false, true);
					regionsList.selectedIndex = 0;
				}
				regionsList.disabled = false;
				onRegionChange(regionsList);				
			};
			
			callbackCities = function (count) {
				if (count > 1) {
					insertFirstOption(citiesList, MSG_CHOOSE_CITY, 0, false, true);
				 	citiesList.selectedIndex = 0;
				}
				citiesList.disabled = false;
			};

			getRegionsListByCountryId(countryId, regionsList, callback, citiesList, callbackCities);					
		}
		
	}	
	
	function sexOnChange() {
		var component = $(SEX_ID);
		var birthdate = $(BIRTH_DATE_DIV_ID2);
		if (component.selectedIndex < 5 && component.selectedIndex > 1) {
			birthdate.style.display = "block";
		}
		else
			birthdate.style.display = "none";
	}

	
	// Do all logic on region change.
	function onRegionChange() {		
		var component = $(REGIONS_LIST_ID);	
		var callback;
		var regionId;
		var citiesList = $(CITIES_LIST_ID);		
		
		if (component.selectedIndex < 0) {
			regionId = 0;
		} else {
			regionId = component.options[component.selectedIndex].value;
		}		
				
		citiesList = fastClearOptions(CITIES_LIST_ID);
		citiesList.disabled = true;
		
		callback = function (count) {
			if (count > 1) {
				insertFirstOption(citiesList, MSG_CHOOSE_CITY, 0, false, true);
				citiesList.selectedIndex = 0;
			}
			citiesList.disabled = false;
		};				
		getCitiesListByRegionIdWithGeoInfo(regionId, citiesList, callback);				
	
	}	
		
	// Fix message for nickname (not hide it when mouse leave html element).
	function fixNicknameMessage() {
		$(NICKNAME_ID).onblur = "";
	}

	
	// Unfix message for nickname (it can be hidden when mouse leave html element).
	function unfixNicknameMessage() {
		$(NICKNAME_ID).onblur = function () {
			nicknameOnBlur();
		};	
	}
	
	
	// Do all logic when setting nickname.
	//    value - nickname value.
	function setNickname(value) {
		var element = $(NICKNAME_ID)	
		
		unfixNicknameMessage();
		hideMessage(NICKNAME_MESSAGE_ID);
		
		invalidNickname = "";
		nicknameValue = "";		
		nicknameMessage = null;
		
		element.value = value;
		element.focus();	
		
	}
	
	// Adjust days in days list according to currently selected year and month.
	// If selected day higher than maximum day in selected month, than select last day in selected month.
	function adjustDays() {
		var daysList = $(BIRTH_DATE_DAY_ID);		
		var month = $F(BIRTH_DATE_MONTH_ID);
		var year = $F(BIRTH_DATE_YEAR_ID);
		var firstDayOption = daysList.options[0];
		var lastDay = daysList.options[daysList.length - 1].value;
		var lastDayOption;
		var selectedDay = daysList.options[daysList.selectedIndex].value;
		var maxDay = lastDay;
		var isSelected = false;
		
		// If no year selected, than use current year.
		if (year < 1) {
			year = new Date().getFullYear();
		}
		
		if (month > 0) {
			maxDay = getDaysInMonth(year, month);			
		}
		
		if (lastDay != maxDay) {
		
			fastClearOptions(BIRTH_DATE_DAY_ID);
			daysList = $(BIRTH_DATE_DAY_ID);
			daysList.appendChild(firstDayOption);
			
			for (var i = 1; i <= maxDay; ++i) {
				isSelected = i == selectedDay;
				addOption(daysList, i + "", i, false, isSelected);
			}						
			
			if (selectedDay > maxDay) {
				var lastDayOption = daysList.options[daysList.length - 1];
				lastDayOption.selected = true;
			}
			
		}		
		
	}
	
	function adjustDays2() {
		var daysList = $(BIRTH_DATE_DAY_ID2);		
		var month = $F(BIRTH_DATE_MONTH_ID2);
		var year = $F(BIRTH_DATE_YEAR_ID2);
		var firstDayOption = daysList.options[0];
		var lastDay = daysList.options[daysList.length - 1].value;
		var lastDayOption;
		var selectedDay = daysList.options[daysList.selectedIndex].value;
		var maxDay = lastDay;
		var isSelected = false;
		
		// If no year selected, than use current year.
		if (year < 1) {
			year = new Date().getFullYear();
		}
		
		if (month > 0) {
			maxDay = getDaysInMonth(year, month);			
		}
		
		if (lastDay != maxDay) {
		
			fastClearOptions(BIRTH_DATE_DAY_ID2);
			daysList = $(BIRTH_DATE_DAY_ID2);
			daysList.appendChild(firstDayOption);
			
			for (var i = 1; i <= maxDay; ++i) {
				isSelected = i == selectedDay;
				addOption(daysList, i + "", i, false, isSelected);
			}						
			
			if (selectedDay > maxDay) {
				var lastDayOption = daysList.options[daysList.length - 1];
				lastDayOption.selected = true;
			}
			
		}		
		
	}
	
	// Grant only numbers for html input element.
	// Copyright 1999 Idocs, Inc. http://www.idocs.com
	// Distribute this script freely but keep this notice in place
	//    element - html element.
	//    event - event on current html element.
	function grantNumbersOnly(element, event) {
		var key;
		var keyChar;

		if (window.event) {
			key = window.event.keyCode;
		} else if (event) {
			key = event.which;
		} else {
			return true;
		}
		
		keyChar = String.fromCharCode(key);

		// Control keys
		if ((key == null) || (key == 0) || (key == 8) || (key == 9) || (key == 13) || (key == 27)) {
			return true;			
		// Numbers
		} else if ((("0123456789").indexOf(keyChar) > -1)) {
			return true;
		} else {
			return false;
		}
		
	}
	
	
	function tipOnMouseOver(element) {
		element.src = TIP_ICON_ACTIVE_URL;
	}
	
	function tipOnMouseOut(element) {
		element.src = TIP_ICON_PASSIVE_URL;
	}
	
	
	function onSubmit() {

		var isValid = true;
		var isValidNickname = true;
		var isValidPassword = true;
		var isValidEmail = true;
		var isValidZipCode = true;
		var isValidBirthDate = true;
		var isValidBirthDay = true;
		var isValidBirthMonth = true;
		var isValidBirthYear = true;
		var isValidLocation = true;
		var isValidCountry = true;
		var isValidRegion = true;
		var isValidCity = true;
		var isValidAgreeToTos = true;
		var nicknameElement = $(NICKNAME_ID);
		var passwordElement = $(PASSWORD_ID);
		var emailElement = $(EMAIL_ID);
		var birthDayElement = $(BIRTH_DATE_DAY_ID);
		var birthMonthElement = $(BIRTH_DATE_MONTH_ID);
		var birthYearElement = $(BIRTH_DATE_YEAR_ID);
		var countryElement = $(COUNTRIES_LIST_ID);
		var regionElement = $(REGIONS_LIST_ID);
		var cityElement = $(CITIES_LIST_ID);
		var zipCodeElement = $(ZIP_CODE_ID);
		var agreeToTosElement = $(AGREE_TO_TOS_ID);

		// Validate all fields
		isValidNickname = validateNickname();
		isValidPassword = validatePassword();
		isValidEmail = validateEmail();
		if (isUsaSelected()) {
			isValidZipCode = validateZipCode();
		}
		else
		{
			isValidRegion = validateRegion();
			isValidCity = validateCity();	
		}
		isValidBirthDate = validateBirthDate();
		isValidBirthDay = validateBirthDay();
		isValidBirthMonth = validateBirthMonth();
		isValidBirthYear = validateBirthYear();
		isValidLocation = validateLocation();
		isValidCountry = validateCountry();
	
		isValidAgreeToTos = validateAgreeToTos();
		
		// Focus on the first invalid field
		if (!isValidEmail && !emailElement.disabled) {
			emailElement.focus();		
		} else if (!isValidNickname && !nicknameElement.disabled) {
			nicknameElement.focus();			
		} else if (!isValidPassword && !passwordElement.disabled) {
			passwordElement.focus();
		} else if (!isValidBirthDay && !birthDayElement.disabled) {
			birthDayElement.focus();
		} else if (!isValidBirthMonth && !birthMonthElement.disabled) {
			birthMonthElement.focus();
		} else if (!isValidBirthYear && !birthYearElement.disabled) {
			birthYearElement.focus();			
		} else if (!isValidCountry && !countryElement.disabled) {
			countryElement.focus();
		} else if (!isValidRegion && !regionElement.disabled) {
			regionElement.focus();
		} else if (!isValidCity && !cityElement.disabled) {		
			cityElement.focus();			
		} else if (!isValidZipCode && !zipCodeElement.disabled) {
			zipCodeElement.focus();
		} else if (!isValidAgreeToTos && !agreeToTosElement.disabled) {
			agreeToTosElement.focus();
		}
		
		// Calculate total result
		isValid = isValidNickname && isValidPassword && isValidEmail && 
				  isValidZipCode && isValidBirthDate && isValidLocation &&
				  isValidAgreeToTos;
		
		
		return isValid;
		
	}
	
	// Calling of this function will show zip code if USA was detected using GeoIP.
	doUsaSelectionLogic();	
	
	// Preload images
	preloadImage(STATUS_ICON_OK_URL);
	preloadImage(STATUS_ICON_ERROR_URL);
	preloadImage(STATUS_ICON_LOADING_URL);
	preloadImage(TIP_ICON_ACTIVE_URL);
	preloadImage(TIP_ICON_PASSIVE_URL);
		
	// Set maximum lengthes for all input fields.
	$(NICKNAME_ID).setAttribute('maxLength', NICKNAME_SIZE_MAX);
	$(PASSWORD_ID).setAttribute('maxLength', PASSWORD_SIZE_MAX);
	$(EMAIL_ID).setAttribute('maxLength', EMAIL_SIZE_MAX);
	$(ZIP_CODE_ID).setAttribute('maxLength', ZIP_CODE_SIZE);
	
	// Setup tips
	Tips.add(NICKNAME_TIP_ID, LL_TIP_NICKNAME_INCORRECT, SETTINGS_TIPS);
	Tips.add(PASSWORD_TIP_ID, LL_TIP_PASSWORD_INCORRECT, SETTINGS_TIPS);
