// Key codes
var KEY_TAB = 9;
var KEY_ESC = 27;
var KEY_ARROW_UP = 38;
var KEY_ARROW_DOWN = 40;
var KEY_HOME = 36;
var KEY_SHIFT = 16;
var KEY_ENTER = 13;

function DestinationInput(inputObj, inputHiddenObj, selectId, product, noDestinationFoundText) {

	this.IS_DESTINATION_NOT_FOUND_MODE = false;
	this.IS_COUNTRY_STATE_AREA_MODE = false;
	this.SELECTED_COUNTRY_STATE_AREA = '';

	this.noDestinationFoundText = (noDestinationFoundText ? noDestinationFoundText : '');

	// need this as a variable for event handlers
	var thisObj = this;
	// the text input field
	this.inputObj = inputObj;
	// the code hidden field
	this.inputHiddenObj = inputHiddenObj;
	// current input text
	this.inputText = null;
	// current input product type
	this.product = product;
	// current available destinations (matching input text)
	this.possibleDestinationsArray = new Array();
	// current selected index among available destinations
	this.currentSelectedIdx = -1;
	this.currentSelectedIdxMouseEvent = -1; // needed for full browser support...
	// the div object for the possible destinations
	this.possibleDestinationsDivObj = document.getElementById(selectId);

	// make sure that the input field does not use autocomplete
	this.inputObj.setAttribute("autocomplete", "off");

	// select all text on focus...
    //  NOTE! Chrome and Safari seems to have some funny "after-on-focus"-event which deselects the text, using onmouseup
    //        for these browsers instead seems to be more acceptable...
    var isChromeOrSafari = (navigator.userAgent.toLowerCase().indexOf('chrome') > -1 || navigator.userAgent.toLowerCase().indexOf('safari') > -1);
    if (isChromeOrSafari)
        inputObj.onmouseup = function() { thisObj.inputObj.select(); }
    else
        inputObj.onfocus = function() { thisObj.inputObj.select(); }

	// -----------------------------------
	// Event handlers
	// -----------------------------------
	inputObj.onblur = function() {
		if (thisObj.isSelectionDivVisible())
			thisObj.selectDestination();
		thisObj.closeSelectionDiv();
	}

	inputObj.onkeypress = function(e) {
		var keyCode = thisObj.getKeyCode(e);
		switch(keyCode) {
			case KEY_ENTER:
				return false;
		}
	}

	inputObj.onkeydown = function(e) {
		var keyCode = thisObj.getKeyCode(e);
		switch(keyCode) {
			case KEY_TAB:
				thisObj.selectDestination();
				break;
			case KEY_ENTER:
				if (thisObj.isSelectionDivVisible()){
					thisObj.selectDestination();
					thisObj.closeSelectionDiv();
				}
				return false;
			case KEY_ESC:
				thisObj.closeSelectionDiv();
				break;
			case KEY_ARROW_UP:
				if (thisObj.currentSelectedIdx > 0)
					thisObj.currentSelectedIdx--;
				else if (thisObj.currentSelectedIdx == 0 && thisObj.possibleDestinationsArray.length > 0)
					thisObj.currentSelectedIdx = thisObj.possibleDestinationsArray.length-1;
				thisObj.highlightSelectedDestination();
				break;
			case KEY_ARROW_DOWN:
				if (thisObj.currentSelectedIdx < (thisObj.possibleDestinationsArray.length - 1))
					thisObj.currentSelectedIdx++;
				else if (thisObj.currentSelectedIdx == (thisObj.possibleDestinationsArray.length-1))
					thisObj.currentSelectedIdx = 0;
				thisObj.highlightSelectedDestination();
				break;
		}
	};

	inputObj.onkeyup = function(e) {
		var keyCode = thisObj.getKeyCode(e);
		switch(keyCode) {
			case KEY_ENTER:
				return false;
			case KEY_TAB:
			case KEY_ESC:
			case KEY_ARROW_UP:
			case KEY_ARROW_DOWN:
			case KEY_HOME:
			case KEY_SHIFT:
				return;
			default:
				if (this.value.length > 2) {
					thisObj.inputText = this.value;
					thisObj.findDestinations();
				} else
					thisObj.closeSelectionDiv();
		}
	};


	// -----------------------------------
	// Other misc event handlers
	// -----------------------------------
	this.getKeyCode = function(ev) {
		if (ev)
			return ev.keyCode;
		if (window.event)
			return window.event.keyCode;
	};

	this.getEventSource = function(ev) {
		if (ev)
			return ev.target;

		if (window.event)
			return window.event.srcElement;
	};

	this.cancelEvent = function(ev) {
		if (ev) {
			ev.preventDefault();
			ev.stopPropagation();
		}
		if (window.event)
			window.event.returnValue = false;
	}


	// -----------------------------------
	// Div functions
	// -----------------------------------
	this.showSelectionDiv = function() {
		this.possibleDestinationsDivObj.style.display = 'block';
		hideSelectBoxesUnderDiv(this.possibleDestinationsDivObj.id);
	};

	this.closeSelectionDiv = function() {
		displaySelectBoxesInPage();
		this.possibleDestinationsDivObj.style.display = 'none';
		this.currentSelectedIdx = -1;
		this.currentSelectedIdxMouseEvent = -1;
	};

	this.isSelectionDivVisible = function() {
		return (this.possibleDestinationsDivObj.style.display == 'block');
	};

	this.positionSelectionDiv = function() {
		var el = this.inputObj;
		var x = 0;
		var y = el.offsetHeight;

		while (el.offsetParent && el.tagName.toUpperCase() != 'BODY') {
			x += el.offsetLeft;
			y += el.offsetTop;
			// if a parent div is positioned absolute we need to substract the top and left to get the correct position
			if (el.tagName.toUpperCase() == 'DIV' && el.style.position.toUpperCase() == 'ABSOLUTE') {
				x -= parseInt(el.style.left);
				y -= parseInt(el.style.top);
			}
			el = el.offsetParent;
		}

		x += el.offsetLeft;
		y += el.offsetTop;

		this.possibleDestinationsDivObj.style.left = x + 'px';
		this.possibleDestinationsDivObj.style.top = y + 'px';
	};

	this.createSelectionDiv = function() {
		if (this.possibleDestinationsArray.length > 0 && this.possibleDestinationsArray[0].KEY == 'NO_DESTINATION_FOUND') {
			this.IS_DESTINATION_NOT_FOUND_MODE = true;
			this.createNoDestinationFoundDiv();
		} else {
			this.IS_DESTINATION_NOT_FOUND_MODE = false;
			var ul = document.createElement('ul');

			var divHeader = document.createElement('div');
			if (this.IS_COUNTRY_STATE_AREA_MODE) {
				divHeader.innerHTML = this.SELECTED_COUNTRY_STATE_AREA;
				divHeader.className = 'areaHeader';
			}
			this.possibleDestinationsDivObj.replaceChild(divHeader, this.possibleDestinationsDivObj.childNodes[0]);

			// NOTE! looping "i in [OBJECT_ARRAY]" does not work in Safari, changed for release 4.8
			//for (i in this.possibleDestinationsArray) {
			for (i=0;i < this.possibleDestinationsArray.length; i++) {
				var word = this.possibleDestinationsArray[i].COMPLETE_NAME;
				var destType = this.possibleDestinationsArray[i].TYPE;

				var li = document.createElement('li');
				var a = document.createElement('a');
				a.href="javascript:void(0)";
				a.innerHTML = word;
				li.appendChild(a);
				if (destType == 2 || destType == 3 || destType == 4)
					li.className = ((this.IS_COUNTRY_STATE_AREA_MODE ? 1 : 0) == i ? "areaSelected" : "areaNonSelected");
				else
					li.className = ((this.IS_COUNTRY_STATE_AREA_MODE ? 1 : 0) == i ? "selected" : "");

				ul.appendChild(li);
			}

			this.possibleDestinationsDivObj.replaceChild(ul,this.possibleDestinationsDivObj.childNodes[1]);

			ul.onmouseover = function(ev) {
				//Walk up from target until you find the LI.
				var target = thisObj.getEventSource(ev);
				while (target.parentNode && target.tagName.toUpperCase() != 'LI')
				{
					target = target.parentNode;
				}

				var lis = thisObj.possibleDestinationsDivObj.getElementsByTagName('LI');

				// NOTE! looping "i in [OBJECT_ARRAY]" does not work in Safari, changed for release 4.8
				//for (i in lis) {
				for (i=0; i < lis.length; i++) {
					var li = lis[i];
					if(li == target) {
						thisObj.currentSelectedIdx = i;
						thisObj.currentSelectedIdxMouseEvent = i;
						break;
					}
				}
				thisObj.highlightSelectedDestination(true);
			};

			/* NOTE! Using all click events here since different browser behaves differntly (and onclick is not working properly for some reason...) */
			ul.onmousedown = function(ev) {
				thisObj.selectDestination(true);
				thisObj.closeSelectionDiv();
				thisObj.cancelEvent(ev);
				return false;
			};
			ul.onmouseup = function(ev) {
				thisObj.selectDestination(true);
				thisObj.closeSelectionDiv();
				thisObj.cancelEvent(ev);
				return false;
			};
			ul.onclick = function(ev) {
				thisObj.selectDestination(true);
				thisObj.closeSelectionDiv();
				thisObj.cancelEvent(ev);
				return false;
			};

			this.possibleDestinationsDivObj.className = "possibleDestinationsList";
			this.possibleDestinationsDivObj.style.position = 'absolute';
		}
	};

	this.createNoDestinationFoundDiv = function () {
		if (this.noDestinationFoundText) {
			var ul = document.createElement('ul');
			var li = document.createElement('li');
			var i = document.createElement('span');
			i.innerHTML = this.noDestinationFoundText.replace('\$\{inputText\}', thisObj.inputText);
			li.appendChild(i);
			li.className = 'selected';
			ul.appendChild(li);

			this.possibleDestinationsDivObj.replaceChild(document.createElement('div'), this.possibleDestinationsDivObj.childNodes[0]);
			this.possibleDestinationsDivObj.replaceChild(ul, this.possibleDestinationsDivObj.childNodes[1]);
			this.possibleDestinationsDivObj.className = "possibleDestinationsList";
			this.possibleDestinationsDivObj.style.position = 'absolute';
		}
	}

	// -----------------------------------
	// Handling destinations functions
	// -----------------------------------
	this.selectDestination = function(isMouseEvent) {
		if (!this.IS_DESTINATION_NOT_FOUND_MODE) {
			selectedIdx = (this.currentSelectedIdx == -1 ? this.currentSelectedIdxMouseEvent : this.currentSelectedIdx);
			if (selectedIdx > -1) {
				if (this.possibleDestinationsArray[selectedIdx].TYPE != 0 && this.possibleDestinationsArray[selectedIdx].TYPE != 1) {
					// State, area or country
					this.SELECTED_COUNTRY_STATE_AREA = this.possibleDestinationsArray[selectedIdx].NAME;
					this.inputObj.value = '';
					this.inputHiddenObj.value = '';
					this.currentSelectedIdx = -1;
					this.currentSelectedIdxMouseEvent = -1;
					this.IS_COUNTRY_STATE_AREA_MODE = true;
					ajaxDestinationsByParent(this, this.possibleDestinationsArray[selectedIdx].KEY, this.possibleDestinationsArray[selectedIdx].NAME);
				} else {
					// City or airport
					this.inputObj.value = translateEntities(this.possibleDestinationsArray[selectedIdx].NAME);
					this.inputHiddenObj.value = this.possibleDestinationsArray[selectedIdx].KEY;
					this.closeSelectionDiv();
				}
			}
		}
	};

	this.highlightSelectedDestination = function(isMouseEvent) {
		if (!this.IS_DESTINATION_NOT_FOUND_MODE) {
			selectedIdx = (this.currentSelectedIdx == -1 ? this.currentSelectedIdxMouseEvent : this.currentSelectedIdx);
			var lis = this.possibleDestinationsDivObj.getElementsByTagName('LI');
			// NOTE! looping "i in [OBJECT_ARRAY]" does not work in Safari, changed for release 4.8
			//for (i in lis) {
			for (i=0;i<lis.length; i++) {
				var li = lis[i];
				// this is to prevent an annoying firefox bug
				if (!li)
					continue;
				if (li.className == 'areaHeader')
					continue;
				if (selectedIdx == i)
					li.className = (li.className.indexOf('area') > -1 ? 'areaSelected' : 'selected');
				else if (li && li.className)
					li.className = (li.className.indexOf('area') > -1 ? 'areaNonSelected' : '');
			}
		}
	};

	this.findDestinations = function() {
		// reset any previous selections
		this.inputHiddenObj.value = '';
		// Note! The ajaxDestinationsFromInput function will call the findDestinationsClosure function
		ajaxDestinationsFromInput(this);
		this.IS_COUNTRY_STATE_AREA_MODE = false;
	}

	this.findDestinationsClosure = function() {
		if (this.possibleDestinationsArray.length == 0 || this.inputText.length < 3)
			this.closeSelectionDiv();
		else {
			this.createSelectionDiv();
			this.positionSelectionDiv();
			this.showSelectionDiv();
			this.currentSelectedIdx = 0;
			this.currentSelectedIdxMouseEvent = 0;
			this.highlightSelectedDestination();
		}
	}
}

function translateEntities(str) {

	if (str.indexOf('&acute;') > -1)
		str = str.replace(/&acute;/g, '´');
	if (str.indexOf('&Aring;') > -1)
		str = str.replace(/&Aring;/g, 'Å');
	if (str.indexOf('&aring;') > -1)
		str = str.replace(/&aring;/g, 'å');
	if (str.indexOf('&Auml;') > -1)
		str = str.replace(/&Auml;/g, 'Ä');
	if (str.indexOf('&auml;') > -1)
		str = str.replace(/&auml;/g, 'ä');
	if (str.indexOf('&AElig;') > -1)
		str = str.replace(/&AElig;/g, 'Æ');
	if (str.indexOf('&aelig;') > -1)
		str = str.replace(/&aelig;/g, 'æ');
	if (str.indexOf('&Aacute;') > -1)
		str = str.replace(/&Aacute;/g, 'Á');
	if (str.indexOf('&aacute;') > -1)
		str = str.replace(/&aacute;/g, 'á');
	if (str.indexOf('&Agrave;') > -1)
		str = str.replace(/&Agrave;/g, 'À');
	if (str.indexOf('&agrave;') > -1)
		str = str.replace(/&agrave;/g, 'à');
	if (str.indexOf('&Acirc;') > -1)
		str = str.replace(/&Acirc;/g, 'Â');
	if (str.indexOf('&acirc;') > -1)
		str = str.replace(/&acirc;/g, 'â');
	if (str.indexOf('&Atilde;') > -1)
		str = str.replace(/&Atilde;/g, 'Ã');
	if (str.indexOf('&atilde;') > -1)
		str = str.replace(/&atilde;/g, 'ã');
	if (str.indexOf('&Ccedil;') > -1)
		str = str.replace(/&Ccedil;/g, 'Ç');
	if (str.indexOf('&ccedil;') > -1)
		str = str.replace(/&ccedil;/g, 'ç');
	if (str.indexOf('&Eacute;') > -1)
		str = str.replace(/&Eacute;/g, 'É');
	if (str.indexOf('&eacute;') > -1)
		str = str.replace(/&eacute;/g, 'é');
	if (str.indexOf('&Egrave;') > -1)
		str = str.replace(/&Egrave;/g, 'È');
	if (str.indexOf('&egrave;') > -1)
		str = str.replace(/&egrave;/g, 'è');
	if (str.indexOf('&Ecirc;') > -1)
		str = str.replace(/&Ecirc;/g, 'Ê');
	if (str.indexOf('&ecirc;') > -1)
		str = str.replace(/&ecirc;/g, 'ê');
	if (str.indexOf('&Euml;') > -1)
		str = str.replace(/&Euml;/g, 'Ë');
	if (str.indexOf('&euml;') > -1)
		str = str.replace(/&euml;/g, 'ë');
	if (str.indexOf('&Iacute;') > -1)
		str = str.replace(/&Iacute;/g, 'Í');
	if (str.indexOf('&iacute;') > -1)
		str = str.replace(/&iacute;/g, 'í');
	if (str.indexOf('&Igrave;') > -1)
		str = str.replace(/&Igrave;/g, 'Ì');
	if (str.indexOf('&igrave;') > -1)
		str = str.replace(/&igrave;/g, 'ì');
	if (str.indexOf('&Icirc;') > -1)
		str = str.replace(/&WWW;/g, 'Î');
	if (str.indexOf('&icirc;') > -1)
		str = str.replace(/&icirc;/g, 'î');
	if (str.indexOf('&Iuml;') > -1)
		str = str.replace(/&Iuml;/g, 'Ï');
	if (str.indexOf('&iuml;') > -1)
		str = str.replace(/&iuml;/g, 'ï');
	if (str.indexOf('&Ntilde;') > -1)
		str = str.replace(/&Ntilde;/g, 'Ñ');
	if (str.indexOf('&ntilde;') > -1)
		str = str.replace(/&ntilde;/g, 'ñ');
	if (str.indexOf('&Oacute;') > -1)
		str = str.replace(/&Oacute;/g, 'Ó');
	if (str.indexOf('&oacute;') > -1)
		str = str.replace(/&oacute;/g, 'ó');
	if (str.indexOf('&Ograve;') > -1)
		str = str.replace(/&Ograve;/g, 'Ò');
	if (str.indexOf('&ograve;') > -1)
		str = str.replace(/&ograve;/g, 'ò');
	if (str.indexOf('&Ocirc;') > -1)
		str = str.replace(/&Ocirc;/g, 'Ô');
	if (str.indexOf('&ocirc;') > -1)
		str = str.replace(/&ocirc;/g, 'ô');
	if (str.indexOf('&Otilde;') > -1)
		str = str.replace(/&Otilde;/g, 'Õ');
	if (str.indexOf('&otilde;') > -1)
		str = str.replace(/&otilde;/g, 'õ');
	if (str.indexOf('&Ouml;') > -1)
		str = str.replace(/&Ouml;/g, 'Ö');
	if (str.indexOf('&ouml;') > -1)
		str = str.replace(/&ouml;/g, 'ö');
	if (str.indexOf('&Oslash;') > -1)
		str = str.replace(/&Oslash;/g, 'Ø');
	if (str.indexOf('&oslash;') > -1)
		str = str.replace(/&oslash;/g, 'ø');
	if (str.indexOf('&OElig;') > -1)
		str = str.replace(/&OElig;/g, 'Œ');
	if (str.indexOf('&oelig;') > -1)
		str = str.replace(/&oelig;/g, 'œ');
	if (str.indexOf('&szlig;') > -1)
		str = str.replace(/&szlig;/g, 'ß');
	if (str.indexOf('&Scaron;') > -1)
		str = str.replace(/&Scaron;/g, 'Š');
	if (str.indexOf('&scaron;') > -1)
		str = str.replace(/&scaron;/g, 'š');
	if (str.indexOf('&Uacute;') > -1)
		str = str.replace(/&Uacute;/g, 'Ú');
	if (str.indexOf('&uacute;') > -1)
		str = str.replace(/&uacute;/g, 'ú');
	if (str.indexOf('&Ugrave;') > -1)
		str = str.replace(/&Ugrave;/g, 'Ù');
	if (str.indexOf('&ugrave;') > -1)
		str = str.replace(/&ugrave;/g, 'ù');
	if (str.indexOf('&Ucirc;') > -1)
		str = str.replace(/&Ucirc;/g, 'Û');
	if (str.indexOf('&ucirc;') > -1)
		str = str.replace(/&ucirc;/g, 'û');
	if (str.indexOf('&Uuml;') > -1)
		str = str.replace(/&Uuml;/g, 'Ü');
	if (str.indexOf('&uuml;') > -1)
		str = str.replace(/&uuml;/g, 'ü');
	if (str.indexOf('&Yacute;') > -1)
		str = str.replace(/&Yacute;/g, 'Ý');
	if (str.indexOf('&yacute;') > -1)
		str = str.replace(/&yacute;/g, 'ý');
	if (str.indexOf('&Yuml;') > -1)
		str = str.replace(/&Yuml;/g, 'Ÿ');
	if (str.indexOf('&yuml;') > -1)
		str = str.replace(/&yuml;/g, 'ÿ');
	if (str.indexOf('&#211;') > -1)
		str = str.replace(/&#211;/g, '\u00D3');
	if (str.indexOf('&#243;') > -1)
		str = str.replace(/&#243;/g, '\u00F3');
	if (str.indexOf('&#260;') > -1)
		str = str.replace(/&#260;/g, '\u0104');
	if (str.indexOf('&#261;') > -1)
		str = str.replace(/&#261;/g, '\u0105');
	if (str.indexOf('&#262;') > -1)
		str = str.replace(/&#262;/g, '\u0106');
	if (str.indexOf('&#263;') > -1)
		str = str.replace(/&#263;/g, '\u0107');
	if (str.indexOf('&#280;') > -1)
		str = str.replace(/&#280;/g, '\u0118');
	if (str.indexOf('&#281;') > -1)
		str = str.replace(/&#281;/g, '\u0119');
	if (str.indexOf('&#321;') > -1)
		str = str.replace(/&#321;/g, '\u0141');
	if (str.indexOf('&#322;') > -1)
		str = str.replace(/&#322;/g, '\u0142');
	if (str.indexOf('&#323;') > -1)
		str = str.replace(/&#323;/g, '\u0143');
	if (str.indexOf('&#324;') > -1)
		str = str.replace(/&#324;/g, '\u0144');
	if (str.indexOf('&#346;') > -1)
		str = str.replace(/&#346;/g, '\u015A');
	if (str.indexOf('&#347;') > -1)
		str = str.replace(/&#347;/g, '\u015B');
	if (str.indexOf('&#377;') > -1)
		str = str.replace(/&#377;/g, '\u0179');
	if (str.indexOf('&#378;') > -1)
		str = str.replace(/&#378;/g, '\u017A');
	if (str.indexOf('&#379;') > -1)
		str = str.replace(/&#379;/g, '\u017B');
	if (str.indexOf('&#380;') > -1)
		str = str.replace(/&#380;/g, '\u017C');

	return str;
}
