// type ahead option object and its attributes

/**
  * Internal call to intialize a new TypeAhead option
  */
function tao_init(value, idx, obj) {
	obj.text = value;
	obj.display = true;
	obj.index = idx;
	obj.hiliteRegions = new Array();
	
	obj.reset = tao_reset;
	obj.clearHilites = tao_clearHilites;
	obj.hiliteRegion = tao_hiliteRegion;
	obj.getDisplayNode = tao_getDisplayNode;	
}

function tao_hiliteRegion(startIndex, endIndex) {
	if (startIndex < 0 || startIndex > this.text.length ||
	    endIndex < 0 || endIndex > this.text.length ||
	    startIndex >= endIndex) {
		return;
	}
	
	for (var i = 0; i < this.hiliteRegions.length; i++) {
		// new region completely inside an existing region, just return
		if (startIndex >= this.hiliteRegions[i][0] && endIndex <= this.hiliteRegions[i][1]) {
			return;
		}
		// new region overlaps existing region, starts later and ends later
		else if (startIndex >= this.hiliteRegions[i][0] && startIndex <= this.hiliteRegions[i][1]) {
			this.hiliteRegions[i][1] = endIndex;
			return;
		}
		// new region overlaps existing regions, starts earlier and ends earlier 
		else if (endIndex >= this.hiliteRegions[i][0] && endIndex <= this.hiliteRegions[i][1]) {
			this.hiliteRegions[i][0] = startIndex;
			return;
		}
		// new region overlaps existing regions start and end times
		else if (startIndex <= this.hiliteRegions[i][0] && endIndex >= this.hiliteRegions[i][1]) {
			this.hiliteRegions[i][0] = startIndex;
			this.hiliteRegions[i][1] = endIndex;
			return;
		}
	}
	
	// new regions does not overlap existing region at all, create a new one 
	var region = new Array();
	region[0] = startIndex;
	region[1] = endIndex;
	this.hiliteRegions[this.hiliteRegions.length] = region;
}

function tao_clearHilites() {
	this.hiliteRegions = new Array();
}

function tao_getDisplayNode() {
	var node = document.createElement("span");
	if (this.hiliteRegions.length == 0) {
		node.appendChild(document.createTextNode(this.text));
	}
	else {
		node.appendChild(document.createTextNode(this.text.substring(0, this.hiliteRegions[0][0])));
		for (var i = 0; i < this.hiliteRegions.length; i++) {
			var bold = document.createElement("b");
			var boldText = this.text.substring(this.hiliteRegions[i][0], this.hiliteRegions[i][1]);
			bold.appendChild(document.createTextNode(boldText));
			node.appendChild(bold);
			var nextPos = (i + 1 >= this.hiliteRegions.length) ? -1 : this.hiliteRegions[i + 1][0];
			if (nextPos != -1) {
				var normalText = this.text.substring(this.hiliteRegions[i][1], nextPos);
				node.appendChild(document.createTextNode(normalText));
			}
		}
		var normalText = this.text.substring(this.hiliteRegions[this.hiliteRegions.length -1][1]);
		node.appendChild(document.createTextNode(normalText));	
	}
	return node;
}

function tao_reset() {
	this.display = true;
	this.clearHilites();
	this.hiliteNode = document.createTextNode(this.text);
}

/* 
 * The following match functions return a integer indicating the match strength.
 * This can be used by calling function to indicate how "good" a match is.  This
 * number should be between 0 (no match) and 5 (ultimate match).
 */
function tao_matchAirport(element) {
	var match = 0;
	if (element.value.length == 0) {
		return match;
	}
	this.clearHilites();
	var elemValLower = element.value.toLowerCase();
	var city = this.textInfo["city"].toLowerCase();
	var idx = 0;
	while((idx = city.indexOf(elemValLower, idx)) != -1) {
		if (idx == 0) { 
			this.hiliteRegion(idx, idx + elemValLower.length);
			match = Math.max(5, match);
		}
		else if (city.charAt(idx - 1) == '[') {
			this.hiliteRegion(idx, idx + elemValLower.length);
			match = Math.max(4, match);
		}
		else if (city.charAt(idx - 1) == '/') {
			this.hiliteRegion(idx, idx + elemValLower.length);
			match = Math.max(4, match);
		}
		else if (city.charAt(idx - 1) == ' ') {
			this.hiliteRegion(idx, idx + elemValLower.length);
			match = Math.max(4, match);
		}
		idx++;
	}
	var provMatchStart = this.textInfo["province"].toLowerCase().indexOf(elemValLower); 
	if (provMatchStart > -1) {
		this.hiliteRegion(provMatchStart + this.textInfo["provinceStartIdx"], 
		                  provMatchStart + elemValLower.length + this.textInfo["provinceStartIdx"]);
		match = Math.max(1, match);
	}
	var codeMatchStart = this.textInfo["code"].toLowerCase().indexOf(elemValLower);
	if (codeMatchStart > -1) {
		this.hiliteRegion(codeMatchStart + this.textInfo["codeStartIdx"], 
		                  codeMatchStart + elemValLower.length + this.textInfo["codeStartIdx"]);
		match = Math.max(2, match);
	}
	return match;
}

function tao_matchCaseSensitive(element) {
	var match = 0;
	this.clearHilites();	
	if (element.value.length > 0) {
		var currIdx = 0;
		while ((currIdx = this.text.indexOf(element.value, currIdx)) != -1) {
			this.hiliteRegion(currIdx, currIdx + element.value.length);
			currIdx += element.value.length;
			match = 1;
		}
	}
	return match;
}

function tao_matchCaseInsensitive(element) {
	var match = 0;
	this.clearHilites();	
	if (element.value.length > 0) {
		var currIdx = 0;
		var txtLower = this.text.toLowerCase();
		var elemValLower = element.value.toLowerCase();
		while ((currIdx = txtLower.indexOf(elemValLower, currIdx)) != -1) {
			this.hiliteRegion(currIdx, currIdx + elemValLower.length);
			currIdx += elemValLower.length;
			match = 1;
		}
	}
	return match;
}

function tao_splitAirportText(airportText) {
	var arr = new Array();
	var cityEndIdx = airportText.lastIndexOf(",");
	var provStartIdx = cityEndIdx + 2;
	var codeStartIdx = airportText.indexOf("(") + 1;
	var codeEndIdx = airportText.lastIndexOf(")");
	if (cityEndIdx = -1) {
		cityEndIdx = codeStartIdx - 2;
		provStartIdx = codeStartIdx - 2;
	}
	var city = airportText.substring(0, cityEndIdx);
	arr["city"] = city;
	var province = airportText.substring(provStartIdx, codeStartIdx - 2);
	arr["province"] = province;
	arr["provinceStartIdx"] = provStartIdx;
	var code = airportText.substring(codeStartIdx, codeEndIdx);
	arr["code"] = code;
	arr["codeStartIdx"] = codeStartIdx;
	return arr;
}

function TypeAheadAirportOption(value, idx) {
	tao_init(value, idx, this);
	this.textInfo = tao_splitAirportText(this.text);
	this.primaryMatch = tao_matchAirport;
	this.secondaryMatch = tao_matchCaseInsensitive;
}

function TypeAheadCaseInsensitiveOption(value, idx) {
	tao_init(value, idx, this);
	this.primaryMatch = tao_matchCaseInsensitive;
	this.secondaryMatch = null;
}

function TypeAheadCaseSensitiveOption(value, idx) {
	tao_init(value, idx, this);
	this.primaryMatch = tao_matchCaseSensitive;
	this.secondaryMatch = null;
}
