// Validation errors and other messages
var InvalidPostcodeMessage = '';
var InvalidStreetMessage = '';
var InvalidTownMessage = '';
var InvalidCompanyMessage = '';
var InvalidBuildingNameNumberMessage = '';
var ManualInputMessage = '';
var KnowPostcodeMessage = '';
var DontKnowPostcodeMessage = '';
var AddressesNotFoundMessage = '';

// Maximum tries of invalid postcode submitting
var SEARCH_MAX_TRY = 3;
// Maximum size of the address list dropdown.
var MAX_DROPDOWN_SIZE = 3;
// Timeout for the address search (in seconds)
var SEARCH_TIMEOUT_SEC = 30;
// A postfix for preview field ids generating.
var PREVIEW_POSTFIX = 'Preview';
// A postfix for DIV where the field is containing.
var BLOCK_POSTFIX = 'Id';
var ID_SEPARATOR = '-';

function AddressList(type, form) {
	this.addresses = null;	// Array of addresses found
	this.search = true;		// Address search fields should be shown
	this.list = false;		// Address list should be shown
	this.editable = false;	// Editable address fields should be shown
	this.failed = false;	// Search is failed - no address search available
	this.visible = false;	// Address details could be temporary hidden
	this.backButton = false;
	this.postcodeUnknown = false;
	this.business = false;
	this.searchTry = SEARCH_MAX_TRY;
	this.type = type;
	this.step= type + '_address_search';	// Step name for the address search
	this.searchChanged = false;
	this.form = form;		// A form object where address fields are posted.
	this.tooManyMatches = false;
	this.addressMessage = false;
	this.httpRequest = null;
	this.processListHandler = this.type + 'AddressListHandler()';
//	this.ids = new AddressFields(type, form);
	this.fields = new AddressFields(type, form);
	this.locked = false;	// Could be locked for address search.

	this.setAddresses = function(addresses) {
		this.addresses = addresses;
		this.list = addresses && addresses.length > 0;
		this.search = false;
		this.editable = false;
		this.backButton = this.list;
	}

	this.searchFailed = function() {
		this.addresses = null;
		this.failed = true;
		this.editable = true;
		this.search = false;
		this.list = false;
		this.backButton = false;
	}

	this.hasSearchTries = function() {
		return !this.searchTry || (this.searchTry > 1);
	}

	this.reset = function() {
		this.addresses = null;
		this.search = true;
		this.list = false;
		this.backButton = false;
		this.editable = false;
		//		this.failed = false;
//		this.visible = true;
		this.searchChanged = false;
		this.tooManyMatches = false;
		this.addressMessage = false;
	}

	this.getPostcodeUnknownText = function() {
	    var text = '';
		if (!this.failed && this.search && !this.locked) {
			text = this.postcodeUnknown? KnowPostcodeMessage: DontKnowPostcodeMessage;
		}
		return text;
	}

	this.getFormField = function(id) {
		var result = null;
		if (id && this.form) {
			result = this.form[id];
		}
		return result;
	}

	this.searchParamsChanged = function() {
		this.searchChanged = true;
		var field = this.fields.getIsSearchChanged();
		if (field) {
			field.disabled = false;
			field.value = 'true';
		}
	}

	this.copySearchValues = function() {
		this.fields.fillSearchFields();
	}

	this.manualInput = function() {
		this.editable = true;
		this.search = false;
		this.list = false;
		this.backButton = !this.failed;
//		this.addresses = null;
		this.addressMessage = false;
	}

	this.updateListId = function() {
		//TODO: Review, rename fields
		var tempId = this.fields.getListTemp();
		var id = this.fields.getListSelected();
		if (tempId && id) {
			id.value = tempId.value;
			if ('' == tempId.value) {
				tempId.selectedIndex = 0;
			}
		}
	}

	this.processSelectedAddress = function() {
		var selectbox = this.fields.getListTemp();
		var index = selectbox.selectedIndex;
		this.editable = (selectbox.length - 1) == index;
//		if (selectbox.length - 1 == index) {
//			this.editable = true;
//		} else {
//			this.editable = false;
//		}
	}

	this.hideAddressPreview = function() {
		for (var i in this.fields.previewIds) {
			var previewField = this.getFormField(this.fields.previewIds[i]);
	
			if (previewField && previewField.parentNode && previewField.parentNode.parentNode) {
				hideElement(previewField.parentNode.parentNode);
			}
		}
	}

	this.update = function() {
		if (!this.locked) {
			this.updateListId();
			this.processSelectedAddress();
			hideError(this.fields.getListSelected().name);	// Hide an error message if present.
			hideArrow(this.fields.getListSelected().name);
			if (this.editable) {
				this.copySearchValues();
//				showMessageForField(this.fields.getBuildingSubNumber(), ManualInputMessage);
			}
			this.draw();
		}
	}

	this.populateInputField = function(field, content) {
		if (field) {
			field.value = content;
		}
	}

	this.showPreview = function(id, value) {
		var previewField = this.getFormField(id);
		if (previewField && isNotBlank(value) && previewField.parentNode && previewField.parentNode.parentNode) {
			this.populateInputField(previewField, value);
			showElement(previewField.parentNode.parentNode);
		}
	}

	this.isNoneOfTheseSelected = function() {
		var dropdown = this.fields.getListTemp();
		return ((dropdown != null) && (this.list == true) && (dropdown.selectedIndex != null) && (dropdown.selectedIndex == (dropdown.length - 1)));
	}

	this.updateView = function() {
		var selectbox = this.fields.getListTemp();
		this.editable = false;
		var index = selectbox.selectedIndex;
		this.hideAddressPreview();
		if (index > 0) {	// Non 'Please select' option chosen
			if (index < (selectbox.length - 1)) {
				var address = this.addresses[index - 1];
				var buildingNumberLine = address.buildingNumber != null? address.buildingNumber: "";
				var showThoroughfare1 = true;
				var showThoroughfare2 = true;
				// Dependant thoroughfare = thoroughfare2
				if (isNotBlank(address.thoroughfare2)) {
					if (isNotBlank(buildingNumberLine)) {
						buildingNumberLine = buildingNumberLine + ', ';
					}
					buildingNumberLine = buildingNumberLine + address.thoroughfare2;
					showThoroughfare2 = false;
				} else if (isNotBlank(address.thoroughfare1)) {
					if (isNotBlank(buildingNumberLine)) {
						buildingNumberLine = buildingNumberLine + ', ';
					}
					buildingNumberLine = buildingNumberLine + address.thoroughfare1;
					showThoroughfare1 = false;
				}
				this.showPreview(this.fields.previewIds.subNumber, address.buildingSubNumber);
				this.showPreview(this.fields.previewIds.number, buildingNumberLine);
				this.showPreview(this.fields.previewIds.name, address.buildingName);
				this.showPreview(this.fields.previewIds.postcode, address.postcode);
				if (showThoroughfare1) {
					this.showPreview(this.fields.previewIds.street1, address.thoroughfare1);
				}
				if (showThoroughfare2) {
					this.showPreview(this.fields.previewIds.street2, address.thoroughfare2);
				}
				this.showPreview(this.fields.previewIds.locale, address.locale);
				this.showPreview(this.fields.previewIds.town, address.town);
				this.showPreview(this.fields.previewIds.company, address.company);
				this.showPreview(this.fields.previewIds.subName, address.buildingSubName);
				this.showPreview(this.fields.previewIds.dependantLocality, address.dependantLocality);
				this.list = false;
				this.drawDropdown(false);
			} else {
				// None of these option is selected.
				this.manualInput();
				this.drawAddressSearchFields(false);
				drawElement(this.fields.addressListSelectDiv, false);
				drawElement(this.fields.addressSelectBtn, false);
			}
		}
	}

	this.setAddressMessage = function() {
		this.reset();
		this.addressMessage = true;
		this.search = false;
	}

	this.setTooManyMatches = function() {
		this.tooManyMatches = true;
		this.setAddressMessage();
	}

	/**
	 * Draws an address list dropdown.
	 *
	 * @param isVisible A flag to show visiblity condition.
	 */
	this.drawDropdown = function(isVisible) {
		drawGroup(isVisible, new Array(this.fields.addressListSelectDiv));
		drawElement(this.fields.addressSelectBtn, isVisible);
	}

	/**
	 * Draws an editable address details.
	 */
	this.drawEditable = function() {
		var isVisible = this.visible && this.editable;

		drawGroup(isVisible, this.fields.fieldIds);
		var editableField = this.fields.getIsEditable();
		if (editableField) {
			editableField.disabled = !isVisible;
			if (isVisible) {
				editableField.value = true;
			}
		}
	}

	this.drawAddressSearchFields = function(isVisible) {
		drawGroup(isVisible && this.postcodeUnknown, this.fields.searchPostcodeIds);
		drawGroup(isVisible && !this.postcodeUnknown, this.fields.searchIds);
	}

	/**
	 * Draws an address details based on a flags stored.
	 */
	this.draw = function() {
		if (this.visible && this.failed) {
			// Failed search.
			var elem = this.fields.getIsFailed();
			if (elem) {
				// Enable hidden field
				elem.disabled = false;
				elem.value = "true";
			}
			this.copySearchValues();
		}
		this.drawAddressSearchFields(this.visible && this.search && !this.editable)
		if (!this.postcodeUnknown) {
			var searchBuildingName = this.fields.getSearchBuildingNameNumber();
			if (searchBuildingName) searchBuildingName.disabled = this.locked;

			var searchPostcode = this.fields.getSearchPostcode();
			if (searchPostcode) searchPostcode.disabled = this.locked;

		} else {
			var searchCompany = this.fields.getSearchCompany();
			if (searchCompany) {
				searchCompany.disabled = this.locked;
//				if (!this.locked) {
//					// Business checkout related only
//					var companyField = this.getFormField('companyName');
//					if (!companyField) {
//						companyField = this.getFormField('tradingAs');
//					}
//					if (companyField && companyField.value) {
//						searchCompany.value = companyField.value;
//					}
//				}
			}

			var searchTown = this.fields.getSearchTown();
			if (searchTown) searchTown.disabled = this.locked;

			var searchStreet = this.fields.getSearchThoroughfare();
			if (searchStreet) searchStreet.disabled = this.locked;
		}
		// Draw and disable back button if required
		drawElement(this.fields.backButtonId, this.visible && this.backButton);
		disableButton(this.fields.backButtonId, this.locked);
		// Hide preview for address list
		this.hideAddressPreview();
		// Address list
		this.drawDropdown(this.visible && this.list && !this.locked);
		// Disable search button
		if (this.postcodeUnknown) {
			disableButton(this.fields.postcodeUnknownSearchButtonId, this.visible && this.search && this.locked);
		} else {
			disableButton(this.fields.postcodeKnownSearchButtonId, this.visible && this.search && this.locked);
		}

		if (this.visible && this.list && !this.locked) {
			this.updateView();
		}

		// Update postcode unknown link text
		setElementText(this.fields.postcodeUnknownLink, this.getPostcodeUnknownText());

		// Display postcode unknown link
		if (null != getElement(this.fields.postcodeUnknownLink)) {
			if (this.visible && this.search && !this.failed && !this.locked) {
				showElement(getElement(this.fields.postcodeUnknownLink).parentNode);
			} else {
				hideElement(getElement(this.fields.postcodeUnknownLink).parentNode);
			}
		}

		// Editable address
		this.drawEditable();
		if (!this.visible) {
			if (this.list) {
				// Remove address list
				this.cleanDropdown();
				this.list = false;
			}
//			this.reset();
//			this.visible = false;
		}

		// Display address header
		drawElement(this.fields.header, this.visible);

		// Show/hide TooManyMatches screen ([Address Message])
		drawElement(this.fields.addressMessageDivId, this.addressMessage);
		// Disable hidden field with a result of list selection
		if (this.visible && this.addressMessage) {
			enableElement(this.fields.getIsTooManyMatches());
		} else {
			clearAndDisableElement(this.fields.getIsTooManyMatches());
		}

		// Disable hidden field with a result of list selection
		if (this.visible && this.backButton) {
			enableElement(this.fields.getListSelected());
		} else {
			clearAndDisableElement(this.fields.getListSelected());
		}
	}

	/**
	 * Switches between 'postcode known' and 'postcode unknown' search.
	 */
	this.switchPostcodeUnknown = function() {
		if (!this.locked) {
			this.postcodeUnknown = !this.postcodeUnknown;
			var flag = this.fields.getIsPostcodeUnknown();
			if (flag != null) {
				flag.disabled = !this.postcodeUnknown;
				flag.value = this.postcodeUnknown ? 'true' : 'false';
			}
			this.editable = false;
			this.list = false;
			this.draw();
		}
	}

	/**
	 * Resets an address search state.
	 */
	this.restartSearch = function() {
		if (!this.locked) {
			this.reset();
			clearValue(this.fields.getSearchThoroughfare());
			clearValue(this.fields.getSearchTown());
			clearValue(this.fields.getSearchCompany());
			clearValue(this.fields.getSearchBuildingNameNumber());
			clearValue(this.fields.getSearchPostcode());
			clearValue(this.fields.getListSelected());
			this.draw();
			if (this.fields.getListSelected()) {
				hideError(this.fields.getListSelected().name);
				hideArrow(this.fields.getListSelected().name);
			}
		}
	}

	this.hasAddresses = function() {
		return this.addresses != null && this.addresses.length > 0;
	}

	/**
	 * Back button was clicked.
	 */
	this.back = function() {
		if ((!this.list || this.editable) && this.hasAddresses()) {
			this.list = true;
			this.editable = false;
			// Reset address list choice
			var dropdown = this.fields.getListTemp();
			if (dropdown) {
				dropdown.selectedIndex = 0
			}
			var dropdownSelected = this.fields.getListSelected();
			if (dropdownSelected) {
				dropdownSelected.value = '';
			}
			this.draw();
		} else {
			this.restartSearch();
		}
	}

	this.cleanDropdown = function() {
		var dropdown = this.fields.getListTemp();
		if (dropdown) {
			var opts = dropdown.options;
			var nonOfTheseOption = opts[opts.length - 1];	// Last option in list is "None of these"
			while (opts.length > 1) {
				dropdown.remove(opts.length - 1);
			}

			opts.add(nonOfTheseOption);
			dropdown.selectedIndex = 0;
		}
	}

	this.getUrl = function() {
		return document.location.href.replace(/^((http|https)\:\/\/[^\/]+\/shop\/)(business\/){0,1}([^\/]+\/).*/g, '$1$4')
				+ 'address-search/';
	}
}

//
// Creates AddressObject for the address list dropdown.
//
function AddressObject(id, buildingSubNumber, buildingSubName, buildingName, buildingNumber, thoroughfare1, 
					   thoroughfare2, town, locale, postcode, company, preview, dependantLocality) {
	this.id = id;
	this.buildingSubNumber = buildingSubNumber;
	this.buildingName = buildingName;
	this.buildingNumber = buildingNumber;
	this.thoroughfare1 = thoroughfare1;
	this.thoroughfare2 = thoroughfare2;
	this.town = town;
	this.locale = locale;
	this.postcode = postcode;
	this.company = company;
	this.preview = preview;
	this.buildingSubName = buildingSubName;
	this.dependantLocality = dependantLocality;
}

/**
 * Object for addresses fields names and ids storing.
 */
function AddressFields (type, form) {
	this.buildingNameNumberValue = '';
	this.postcodeValue = '';
	this.townValue = '';
	this.streetValue = '';
	this.companyValue = '';

	this.form = form;
	this.fillSearchFields = function() {
		if (this.getBuildingNumber() != null && isNotBlank(this.buildingNameNumberValue)) {
			this.getBuildingNumber().value = this.buildingNameNumberValue;
		}
		if (this.getPostcode() != null && isNotBlank(this.postcodeValue)) {
			this.getPostcode().value = this.postcodeValue;
		}
		// Uses for the unknown postcode mode.
		if (this.getBuildingNumber() != null && isNotBlank(this.companyValue)) {	//todo: Should be renamed since company no longer used.
//			this.getCompany().value = this.companyValue;
			this.getBuildingNumber().value = this.companyValue;
		}
		if (this.getTown() != null && isNotBlank(this.townValue)) {
			this.getTown().value = this.townValue;
		}
		if (this.getThoroughfare1() != null && isNotBlank(this.streetValue)) {
			this.getThoroughfare1().value = this.streetValue;
		}
	}

	this.storeSearchFields = function() {
		this.buildingNameNumberValue = getDefaultString(getFieldValue(this.getSearchBuildingNameNumber()));
		this.postcodeValue = getDefaultString(getFieldValue(this.getSearchPostcode()));
		//todo: Should be renamed since company no longer used.
		this.companyValue = getDefaultString(getFieldValue(this.getSearchCompany()));
		this.streetValue = getDefaultString(getFieldValue(this.getSearchThoroughfare()));
		this.townValue = getDefaultString(getFieldValue(this.getSearchTown()));
	}
	this.getField = function(id) {
		return (id && this.form)? this.form[id]: null;
	}
	this.getBuildingSubNumber = function() {
		return this.getField(type + 'Address.buildingSubNumber');
	}
	this.getBuildingNumber = function() {
		return this.getField(type + 'Address.buildingNumber');
	}
	this.getBuildingName = function() {
		return this.getField(type + 'Address.buildingName');
	}
	this.getPostcode = function() {
		return this.getField(type + 'Address.postcode');
	}
	this.getThoroughfare1 = function() {
		return this.getField(type + 'Address.thoroughfare1');
	}
	this.getThoroughfare2 = function() {
		return this.getField(type + 'Address.thoroughfare2');
	}
	this.getLocale = function() {
		return this.getField(type + 'Address.locale');
	}
	this.getTown = function() {
		return this.getField(type + 'Address.town');
	}
	this.getCompany = function() {
		return this.getField(type + 'Address.company');
	}
	this.getListTemp = function() {
		return this.getField(type + 'Address.tempListId');
	}
	this.getListSelected = function() {
		return this.getField(type + 'Address.addressListId');
	}
	this.getIsTooManyMatches = function() {
		return this.getField(type + 'Address.isTooManyMatches');
	}
	this.getSearchBuildingNameNumber = function() {
		return this.getField(type + 'Address.searchBuildingNameNumber');
	}
	this.getSearchPostcode = function() {
		return this.getField(type + 'Address.searchPostcode');
	}
	this.getSearchCompany = function() {
		return this.getField(type + 'Address.searchCompany');
	}
	this.getSearchTown = function() {
		return this.getField(type + 'Address.searchTown');
	}
	this.getSearchThoroughfare = function() {
		return this.getField(type + 'Address.searchThoroughfare');
	}
	this.getIsSearchChanged = function() {
		return this.getField(type + 'Address.isSearchChanged');
	}
	this.getIsEditable = function() {
		return this.getField(type + 'Address.isEditable');
	}
	this.getIsFailed = function() {
		return this.getField(type + 'Address.isFailed');
	}
	this.getIsPostcodeUnknown = function() {
		return this.getField(type + 'Address.isPostcodeUnknown');
	}
	this.getIsOverseas = function() {
		return this.getField(type + 'Address.isOverseas');
	}
	this.fields = new function() {
		this.subNumber = type + 'Address.buildingSubNumber';
		this.number		= type + 'Address.buildingNumber';
		this.name 		= type + 'Address.buildingName';
		this.postcode	= type + 'Address.postcode';
		this.street1	= type + 'Address.thoroughfare1';
		this.street2	= type + 'Address.thoroughfare2';
		this.locale		= type + 'Address.locale';
		this.town		= type + 'Address.town';
		this.company	= type + 'Address.company';
		this.subName	= type + 'Address.buildingSubName';
		this.dependantLocality		= type + 'Address.dependantLocality';
	};
	this.fieldIds = addPostfixForArray(replaceInArray(this.fields, /\./g, '-'), 'Id');
	this.previewIds = addPostfixForArray(this.fields, PREVIEW_POSTFIX);
	this.searchIds = new function() {
		this.nameNumber = getFieldBlockId(type + 'Address.searchBuildingNameNumber');
		this.postcode 	= getFieldBlockId(type + 'Address.searchPostcode');
	}
	this.searchPostcodeIds = new function() {
		this.street	= getFieldBlockId(type + 'Address.searchThoroughfare');
		this.town	= getFieldBlockId(type + 'Address.searchTown');
		this.company	= getFieldBlockId(type + 'Address.searchCompany');
		this.postcodeUnknown = getFieldBlockId(type + 'Address.isPostcodeUnknown');
	};
	this.dropdownId	= type + 'AddressListDivId';
	this.overseasId	= getFieldBlockId(type + 'Address.isOverseas');
	this.postcodeUnknownLink = type + 'Address-postcodeUnknownLinkId';
	this.postcodeKnownSearchButtonId = type + 'PostcodeKnownAddressSearchBtn';
	this.postcodeUnknownSearchButtonId = type + 'PostcodeUnknownAddressSearchBtn';
    this.addressSelectBtn = type + 'AddressSelectBtn';
    this.addressListSelectDiv = type + 'AddressListSelectDivId';
	this.header		= type + 'AddressHeader';
	this.addressMessageDivId = type + 'AddressMessageDivId';
	this.backButtonId = type + 'AddressBackBtn';
	this.searchBlockId = type + 'AddressSearchDivId';
};

/**
 * Validates address details in a both search modes (postcode known/unknown).
 * @param addressList An object for addressList.
 */
function validateAddressDetails(addressList) {
	return (addressList.postcodeUnknown && validateUnknownAddressDetails(addressList))
			|| (!addressList.postcodeUnknown && validateKnownAddressDetails(addressList));
}

/**
 * Performs an address search.
 */
function addressSearch(addressList, listHandler, timeoutHandler) {
    if (window.invokeWTScript){
        setMeta("WT.si_p", "eShop_Checkout_Address_Details;Address Details");
        invokeWTScript();
    }
	addressList.fields.storeSearchFields();
	addressList.processList = listHandler;
	addressSearchAJAX(timeoutHandler, addressList);
}

//
// Performs address search by parameters in form specified.
//
function addressSearchAJAX(timeoutHandler, addressList) {
	var searchPostcode = addressList.fields.getSearchPostcode();
	var params;
	var searchBuildingNameNumber = addressList.fields.getSearchBuildingNameNumber();
	var searchCompany = addressList.fields.getSearchCompany();
	var searchTown = addressList.fields.getSearchTown();
	var searchStreet = addressList.fields.getSearchThoroughfare();
	params = buildAddressSearchParameters(
						searchBuildingNameNumber? searchBuildingNameNumber.value: null,
						searchPostcode? searchPostcode.value: null,
						searchCompany? searchCompany.value: null,
						searchStreet? searchStreet.value: null,
						searchTown? searchTown.value: null,
						addressList
			);
	doAddressSearchRequest(addressList, timeoutHandler, params);
}

function doAddressSearchRequest(addressList, timeoutHandler, params) {
	var httpRequest = addressList.httpRequest;
	if (!addressList.locked && (httpRequest == null || httpRequest.readyState == 0 || httpRequest.readyState == 4)) {
		// Request is available to send.
		addressList.locked = true;
		addressList.searchChanged = false;
		addressList.cleanDropdown();
		addressList.draw();
		try {
			addressList.searchTimeoutId = addTimeout(timeoutHandler, SEARCH_TIMEOUT_SEC);
			addressList.httpRequest = doPOSTRequest(httpRequest, addressList.getUrl(), params, true, addressList.processListHandler);
		} catch (e) {
			// Address search unavailable.
			searchUnavailable(addressList);
			addressList.draw();
		}
	}
}

/**
 * Builds request parameters string for address search.
 *
 * @param houseNameNumber A building name, number or flat number.
 * @param postcode A postcode to search.
 * @param organisation An organisation for business search.
 * @param street A street name to search.
 * @param town A town name to search.
 * @param addressList An address list for storing the result.
 */
function buildAddressSearchParameters(houseNameNumber, postcode, organisation, street, town, addressList) {
	var parameters = 'type=' + encodeURI(addressList.type);
	if (addressList.business) {
		// Search by company name
		parameters += '&businessSearch=true';
	}
	if (!addressList.hasSearchTries()) {
		parameters += '&failed=true';
	} else if (addressList.postcodeUnknown) {
		// Search an address with postcode unknown.
		if (isNotBlank(organisation)) {
			parameters += '&company=' + encodeURI(organisation);
		}
		if (isNotBlank(street)) {
			parameters += '&thoroughfare=' + encodeURI(street);
		}
		if (isNotBlank(town)) {
			parameters += '&town=' + encodeURI(town);
		}
	} else {
		// Search an address by postcode.
		parameters += '&postcodeKnown=true';
		if (isNotBlank(houseNameNumber)) {
			parameters += '&buildingNameNumber=' + encodeURI(houseNameNumber)
		}
		if (isNotBlank(postcode)) {
			parameters += '&postcode=' + encodeURI(postcode);
		}
	}
	return parameters;
}

//
// Builds request parameters string for address search when it's not available (e.g. 3 wrong postcodes).
//
function buildSearchFailedParameters(addressType) {
	return 'failed=true&' + addressType + '=true';
}

function fillDropdown(addressList) {
	if (addressList && addressList.list && addressList.addresses) {
		var addressesDropdown = addressList.fields.getListTemp();
		if (addressesDropdown) {
			for (var i = 0; i < addressList.addresses.length; i++) {
				addOption(addressesDropdown, addressList.addresses[i].id, addressList.addresses[i].preview);
			}
			addressesDropdown.setAttribute('size', (addressList.addresses.length > MAX_DROPDOWN_SIZE? MAX_DROPDOWN_SIZE: addressList.addresses.length) + 2);
		}
	}
}

function processAddressList(addressList) {
	if (addressList.httpRequest && addressList.httpRequest.readyState == 4) {	// Response is ready.
		addressList.locked = false;	// Remove lock.
		addressList.cleanDropdown();
		var response = fetchSearchResponse(addressList);
		if (response) {
			if (response['failedSearch']) {
				searchUnavailable(addressList);
			} else if (response['tooManyMatches'] || response['emptyParameters']
					|| !response['addresses'] || response['addresses'].length == 0) {
				// Too many matches was found or empty parameters were specified
				addressList.setTooManyMatches();
			} else {
				addressList.setAddresses(response.addresses);
				fillDropdown(addressList);
			}
			if (response['attemptCount']) {
				addressList.searchTry = response['attemptCount'];
			}
		} else {
			searchUnavailable(addressList);
		}
		addressList.draw();
		addressList.searchChanged = false;
	}
}

//
// Handles the response of address search - populates the list of addresses.
//
function fetchSearchResponse(addressList) {
	var result = null;
	if (addressList.httpRequest && addressList.httpRequest.readyState == 4) {	// Response is ready.
		removeTimeout(addressList.searchTimeoutId);
		if (addressList.httpRequest.status == 200 && addressList.httpRequest.responseText) {	// OK response
			try {
				result = eval("(" + addressList.httpRequest.responseText + ")");
			} catch (e) {
				// Response evaluation failed.
				result = null;
			}
		}
	}
	return result;
}

//
// Creates and adds an option for the select element specified.
//
function addOption(selectElement, id, text) {
	/* START CR7358 - bgazzard - adding catch to eleminate undefined values */
	if(typeof id != 'undefined' || typeof text != 'undefined'){
	var option = document.createElement("OPTION");
	option.text = text;
	option.value = id;
	selectElement.options.add(option, selectElement.length - 1);
}
	/* END CR7358 - bgazzard - adding catch to eleminate undefined values */	
}

//
// Submits form with given parameters for failed search situation.
//
function failedSearch(addressList) {
	var failedField = addressList.fields.getIsFailed();
	if (failedField) {
		failedField.disabled = false;
		failedField.value = 'true';
	}
	submitWithStep(addressList.step);
}

/**
 * Converts a field's name like 'address.postcode' to its id like 'address-postcodeId'
 * @param field
 */
function getPreviewIdForField(field) {
	if (field && field.name) {
		return field.name + PREVIEW_POSTFIX;
	}
	return null;
}

function getFieldBlockId(fieldName) {
	if (isNotBlank(fieldName))
		return fieldName.replace(/\./g, ID_SEPARATOR) + BLOCK_POSTFIX;
	return fieldName;
}

//
// Validates postcode for address search.
//
function validateSearchPostcode(addressList) {
	var isValid = true;
	var postcode = addressList.fields.getSearchPostcode();

	if (addressList.visible
			&& addressList.search
            && ((!addressList.list && !addressList.editable) || (addressList.searchChanged))) {

        if (addressList.postcodeUnknown) {

            var noWildcardMask = /^[^\?\*]{2}[^\?\*]*$/;
            var isStreetValid = isMaskMatches(addressList.fields.getSearchThoroughfare(), noWildcardMask);
            if (!isStreetValid) {
                // Invalid street format.
				addMessageForField(addressList.fields.getSearchThoroughfare(), InvalidStreetMessage);
			}
            var isTownValid = isMaskMatches(addressList.fields.getSearchTown(), noWildcardMask);
            if (!isTownValid) {
                // Invalid town format.
                addMessageForField(addressList.fields.getSearchTown(), InvalidTownMessage);
			}
			var isCompanyValid = isMaskMatches(addressList.fields.getSearchCompany(), noWildcardMask);
			if (!isCompanyValid) {
				// Invalid Company format.
				addMessageForField(addressList.fields.getSearchCompany(), InvalidCompanyMessage);
			}

            isValid = isStreetValid && isTownValid && isCompanyValid;

            if (!isValid) {
                addressList.reset();
                if (addressList.failed) {
                    failedSearch(addressList);
                }
            }

        } else {

            if (
                postcode != null
			&& postcode.value != null
			&& !postcode.disabled
			&& !isValidPostcode(postcode.value)) {
				addressList.reset();
				if (addressList.failed) {
                    failedSearch(addressList);
                } else {
					addMessageForField(addressList.fields.getSearchPostcode(), InvalidPostcodeMessage);
                }
				isValid = false;
			}
        }
    }

	return isValid;
}


function validateUnknownAddressDetails(addressList) {
	var noWildcardMask = /^[^\?\*]*$/;
	var streetField = addressList.fields.getSearchThoroughfare();
	var isValid = true;
	if (!isNotValidate(streetField) && streetField.value && !isMaskMatches(streetField, noWildcardMask)) {
		// Invalid street format.
		isValid = false;
	}
	var townField = addressList.fields.getSearchTown();
	if (!isNotValidate(townField) && townField.value && !isMaskMatches(townField, noWildcardMask)) {
		// Invalid town format.
		isValid = false;
	}
	var companyField = addressList.fields.getSearchCompany();
	var isCompanyValid = isMaskMatches(companyField, noWildcardMask);
	if (!isNotValidate(companyField) && companyField.value && !isCompanyValid) {
		// Invalid company format.
		isValid = false;
	}
    return isValid;
}

function validateKnownAddressDetails(addressList) {
	var noWildcardMask = /^[^\?\*]*$/;
	var isValid = true;
	var nameNumberField = addressList.fields.getSearchBuildingNameNumber();
	var postcodeField = addressList.fields.getSearchPostcode();

	if (!isNotValidate(nameNumberField) && nameNumberField.value && !isMaskMatches(nameNumberField, noWildcardMask)) {
		// Invalid symbols in a search field
		isValid = false;
	}
	if (!isNotValidate(postcodeField) && postcodeField.value && !isMaskMatches(postcodeField, noWildcardMask)) {
		// Invalid symbols in a postcode field
		isValid = false;
	}
    return isValid;
}

function addressTimeoutHandler(addressList) {
	if (addressList.httpRequest) addressList.httpRequest.abort();
	addressList.httpRequest = null;
	addressList.locked = false;
	searchUnavailable(addressList);
}

function searchUnavailable(addressList) {
	addressList.manualInput();
//	showMessageForField(addressList.fields.getIsEditable(), ManualInputMessage);
	addressList.searchFailed();
}

function showEditableAddress(addressList) {
	addressList.manualInput();
	addressList.copySearchValues();
	addressList.draw();
	var dropdown = addressList.fields.getListSelected();
	if (dropdown) {
		dropdown.disabled = 'true';
	}
	drawElement(addressList.fields.addressSelectBtn, false);
	drawElement(addressList.fields.addressListSelectDiv, false);
}

function showMessageForField(field, message) {
	if (field && message) {
		showMessage(field.name, message);
	}
}

function addMessageForField(field, message) {
	if (field && field.name && isNotBlank(message)) {
		addFieldEntry(field.name, message);
	}
}

/**
 * Returns 'true' - when 'None of these' option is NOT selected. Sets AddressMessage flags.
 */
function validateNoneOfTheseSelected(list) {
	var result = list.isNoneOfTheseSelected();
	if (result) {
		list.updateListId();
		showEditableAddress(list);
	}
	return !result;
}

