var SymbolSearch = function(elForm) {
	this.localCache = {};
	this.eventManager = new EventManager();
	this.query = "";
	this.issueType = "";
	
	this.setDestinationURL(this.DESTINATION_URL);
	this.setRequestURL(this.REQUEST_URL);
	this.setFinderURL(this.FINDER_URL);
	
	if (elForm || Element.get(this.DEFAULT_FORM_ID)) {
		// DOM has loaded
		this.setForm(elForm);
	} else {
		this.eventManager.add(window, "load", function() { this.setForm(elForm) }, this);
	}
}

SymbolSearch.prototype.DEFAULT_FORM_ID = "";
SymbolSearch.prototype.FORM_INPUT_SELECTOR = "";
SymbolSearch.prototype.FORM_INPUT_HIDDEN = "";

SymbolSearch.prototype.REQUEST_URL = "../../common/symbolLookup/getSymbols.asp";
SymbolSearch.prototype.DESTINATION_URL = "";
SymbolSearch.prototype.FUND_DESTINATION_URL = "?symbol=";
SymbolSearch.prototype.FINDER_URL = "../../symbolLookup/symbolLookup/symbolLookup.asp";
SymbolSearch.prototype.KEY_PRESS_WAIT = 0;

SymbolSearch.prototype.CSS_HIDDEN = "symbolSearchHidden";
SymbolSearch.prototype.CSS_SELECTED = "selected";
SymbolSearch.prototype.CSS_RESULTS = "symbolSearch";
SymbolSearch.prototype.CSS_ISSUE_NAME = "issueName";
SymbolSearch.prototype.CSS_GROUP_END = "symbolSearchGroupEnd";
SymbolSearch.prototype.CSS_FLAG = "wsod-flag";
SymbolSearch.prototype.CSS_FLAG_COUNTRY = "flag-";
SymbolSearch.prototype.CSS_MORE_LINK = "more";

SymbolSearch.prototype.ATTR_NO_RESULTS = "noresults";

SymbolSearch.prototype.KEY_CODE_UP = 38;
SymbolSearch.prototype.KEY_CODE_DOWN = 40;
SymbolSearch.prototype.KEY_CODE_ESC = 27;
SymbolSearch.prototype.KEY_CODE_ENTER = 13;

SymbolSearch.prototype.invalidChars = /\s/g;
SymbolSearch.prototype.countryPrefix = /^[a-z]{2};/i;

SymbolSearch.prototype.ISSUE_TYPES = {
	EQ: "EQ"
};

SymbolSearch.prototype.setFormElements = function(elForm, elInput) {
	this.DEFAULT_FORM_ID = elForm;
	this.FORM_INPUT_SELECTOR = elInput;
	this.FORM_INPUT_HIDDEN = elInput + '_hidden';
};

SymbolSearch.prototype.setForm = function(elForm) {
	this.clearInputEventHandlers();
	
	this.elForm = elForm || Element.get(this.DEFAULT_FORM_ID);
	this.elInput = Element.get(this.FORM_INPUT_SELECTOR);
	this.elHidden = Element.get(this.FORM_INPUT_HIDDEN);
	
	this.addInputEventHandlers();
};

SymbolSearch.prototype.addInputEventHandlers = function() {
	this.eventManager.add(this.elInput, "keyup", this.search, this, null, this.KEY_PRESS_WAIT);
	this.eventManager.add(this.elInput, "click", function(e) {
		e.cancel();
	});
};

SymbolSearch.prototype.clearInputEventHandlers = function() {
	if (this.elInput) {
		this.eventManager.remove(this.elInput);
	}
};

SymbolSearch.prototype.addResultEvents = function(noResults) {
	this.selectedRow = -1;
	
	if (!noResults) {
		//this.getOnNavResults().addElement(this.elInput);
		this.getOnHoverResults().addElement(this.elResultRows);
		this.getOnClickResults().addElement(this.elResultRows);
	}
	
	this.getOnHideResults().addElement(document);
	this.getOnSubmitResults().addElement(this.elInput);
};

SymbolSearch.prototype.removeResultEvents = function() {
	//this.getOnNavResults().removeAllElements();
	this.getOnHoverResults().removeAllElements();
	this.getOnClickResults().removeAllElements();
	this.getOnHideResults().removeAllElements();
	this.getOnSubmitResults().removeAllElements();
};

SymbolSearch.prototype.getOnNavResults = function() {
	var eventSource = this.eventManager.add(null, "keydown", this.navigate, this);
	
	this.getOnNavResults = function() {
		return eventSource;
	};
	
	return this.getOnNavResults();
};

SymbolSearch.prototype.getOnHoverResults = function() {
	var eventHandler = function(e, el) {
		this.highlightRow(el.rowIndex);
	};
	
	var eventSource = this.eventManager.add(null, "mouseover", eventHandler, this);
	
	this.getOnMouseOverResults = function() {
		return eventSource;
	};
	
	return this.getOnMouseOverResults();
};

SymbolSearch.prototype.getOnHideResults = function() {
	var eventSource = this.eventManager.add(null, "click", this.clearResults, this);

	this.getOnHideResults = function() {
		return eventSource;
	};
	
	return this.getOnHideResults();
};

SymbolSearch.prototype.getOnClickResults = function() {
	var eventSource = this.eventManager.add(null, "click", this.selectResult, this);
	
	this.getOnClickResults = function() {
		return eventSource;
	};
	
	return this.getOnClickResults();
};

SymbolSearch.prototype.getOnSubmitResults = function() {
	var eventSource = this.eventManager.add(null, "keypress", this.selectResult, this);
	
	this.getOnSubmitResults = function() {
		return eventSource;
	};
	
	return this.getOnSubmitResults();
};

SymbolSearch.prototype.setRequestor = function(requestor) {
	this.requestor = requestor;
};

SymbolSearch.prototype.setDestinationURL = function(URL) {
	this.destinationURL = URL;
};

SymbolSearch.prototype.setRequestURL = function(URL) {
	this.requestURL = URL;
};

SymbolSearch.prototype.setFinderURL = function(URL) {
	this.finderURL = URL;
};
SymbolSearch.prototype.setDivWidth = function(width) {
	this.divWidth = width;
};
SymbolSearch.prototype.setShowDir = function(dir) {
	this.showDir = dir;
};

SymbolSearch.prototype.highlightText = function(c) {
	var sTermArray = String(this.query).replace(this.countryPrefix, "").split(" ");
	var sTermLen = sTermArray.length;
	
	if (c.n.indexOf(" ")) {
		var coName = c.n.split(" ");
		var coNameLen = coName.length;
	} else {
		var coName = c.n;
		var coNameLen = 1;
	}
	
	if(sTermLen == 1){
		var replacement = '<b>$1</b>';
		var re = new RegExp("\\b(" + sTermArray + ")", "gi");
		c.d = String(c.s).replace(re, replacement);
		c.n = String(c.n).replace(re, replacement);
	} else {
		for (var i = 0; i < coNameLen; i++) {
			var coNamePart = coName[i];
			if(!coNamePart.length){
				continue;
			}
			for(var z = 0; z < sTermLen; z++){
				var term = sTermArray[z].replace(/\s/g, "");
				var termLen = term.length;
				if (termLen && term.toLowerCase() == coNamePart.toLowerCase().substring(0, termLen)) {
					coName[i] = '<b>' + coNamePart.substring(0, termLen) + '</b>' + coNamePart.substring(termLen);
					z = sTermLen;
				}
			}
			
			c.n = coName.join(' ');
		}
	}
	
	return c;
};

SymbolSearch.prototype.setIssueType = function(type) {
	this.issueType = type;
};

SymbolSearch.prototype.search = function(e, el){
	if (el.value == this.query) {
		return;
	} else if (!String(el.value).replace(this.invalidChars, "")) {
		this.query = el.value;
		this.clearResults();
	} else {
		this.abortActiveRequests();
		this.query = el.value;
		if (this.localCache[this.query + this.issueType]) {
			this.drawResults(this.localCache[this.query + this.issueType]);
		} else {
			this.requestor.load({
				url: this.requestURL,
				contentType: "text/javascript",
				data: {
					q: this.query,
					issueType: this.issueType,
					callback: "handleResults",
					context: "this"
				},
				context: this
			});
		}
	}
};

SymbolSearch.prototype.handleResults = function(query, results, showMoreLink) {
	var cachedNodes = [];
	if(Element.parseSelector('div.symbolSearchHidden', '', 'first')){
		Element.parseSelector('div.symbolSearchHidden', '', 'first').className = 'symbolSearch';
	}
	var elTable = Element.create("table");
	
	var resultType = ['Symbol Results', 'Company Results', 'Symbol Starts With'];
	
	for (var i=0,group; i<results.length; i++) {
		group = results[i];
		if (group.length) {
			var elTbody = Element.create("tbody");
			var tr = Element.create('tr', {'class':'header-cell'}, null, elTbody);
			for (var j=0,c; j<group.length; j++) {
				c = this.highlightText(group[j]);
				if(j == 0){
					if(c.lt == 'Symbol.5.0'){
						Element.create('td', {colspan:3}, resultType[0], tr);
					}else if(c.lt == 'IssueNameFast.5.0'){
						Element.create('td', {colspan:3}, resultType[1], tr);
					}else{
						Element.create('td', {colspan:3}, resultType[2], tr);
					}
				}
				
				var elRow = Element.create("tr", { symbol: c.s, name: c.dn }, [
					Element.create("td", { "class": this.CSS_ISSUE_NAME }, c.n),
					Element.create("td", {'class':'light'}, c.c)
				], elTbody);
				
				if (group.length-1 == j && (results.length -1 != i || showMoreLink)) {
					Element.addClass(elRow, this.CSS_GROUP_END);
				}

			}
			Element.addChild(elTable, elTbody);
		}
	}
	if (!elTable.childNodes.length) {
		Element.create("tbody", null, [
			Element.create("tr", { "class": this.CSS_GROUP_END }, [
				Element.create("td", null, "No securities were found for \"<b>" + query + "</b>\".")
			])
		], elTable);
		elTable.setAttribute(this.ATTR_NO_RESULTS, "true");
	}
	
	cachedNodes.push(elTable);
	this.localCache[query + this.issueType] = cachedNodes;
	
	this.drawResults(cachedNodes);
	
};

SymbolSearch.prototype.createResultsContainer = function() {
	this.elResults = Element.create("div", { "class": this.CSS_HIDDEN }, null, document.body);
	if(this.divWidth) {
		this.elResults.style.width = this.divWidth + 'px';
	}
	Element.addClass(this.elResults, this.CSS_RESULTS);
};

SymbolSearch.prototype.drawResults = function(cachedNodes) {
	this.clearResults();
	
	if (!this.elResults) {
		this.createResultsContainer(); 
	}

	for (var i=0; i<cachedNodes.length; i++) {
		Element.addChild(this.elResults, cachedNodes[i]);
	}
	
	this.elResultRows   = Element.parseSelector("tr", this.elResults);
	this.elMoreLink     = Element.parseSelector("tr." + this.CSS_MORE_LINK + " a", this.elResults, "first");
	
	this.addResultEvents(cachedNodes[0].getAttribute(this.ATTR_NO_RESULTS));
	
	var pos     = Element.getXY(this.elInput);
	var size    = Element.getSize(this.elInput);
	
	Element.removeClass(this.elResults, this.CSS_HIDDEN);
	
	var resultsSize = Element.getSize(this.elResults);
	
	if(this.showDir == 'up') {
	    var y = (pos.y - resultsSize.height);
	} else {
	    var y = pos.y + size.height + 1;
	}
	
	Element.setXY(this.elResults, pos.x - 2, y);
	
	WCH.Apply(this.elResults, null, true);
};

SymbolSearch.prototype.clearResults = function() {
	
	if (!this.elResults) {
		this.createResultsContainer();
	}
	
	if (this.elResultRows && this.elResultRows.length) {
		Element.removeClass(this.elResultRows, this.CSS_SELECTED);
	}
    
    	
	var existingSearches = Element.parseSelector('.symbolSearch',document.body);
    for(var i = 0; i < existingSearches.length; i++) {
        Element.addClass(existingSearches[i], this.CSS_HIDDEN);
    }
    
	//Element.addClass(this.elResults, this.CSS_HIDDEN);
	Element.removeChildNodes(this.elResults);
	this.removeResultEvents();
	WCH.Discard(this.elResults);
};

SymbolSearch.prototype.buildMoreLink = function() {
	var URL = this.finderURL + "?textIn=" + this.query + '&issueType=All';
	return URL;
};

SymbolSearch.prototype.navigate = function(e) {
	switch (e.nativeEvent.keyCode) {
		case this.KEY_CODE_DOWN :
			e.cancel();
			var rowIdx = Math.min(this.selectedRow + 1, this.elResultRows.length-1);
			
			if (this.elResultRows[rowIdx]) {
				if (this.elResultRows[rowIdx].className == 'header-cell') {
					rowIdx += 1;
				}
			}
			
			this.highlightRow(rowIdx);
			break;
		
		case this.KEY_CODE_UP :
			e.cancel();
			var rowIdx = Math.max(this.selectedRow - 1, -1);
			
			if (this.elResultRows[rowIdx]) {
				if (this.elResultRows[rowIdx].className == 'header-cell') {
					rowIdx -= 1;
				}
			}
			
			this.highlightRow(rowIdx);
			break;
		
		case this.KEY_CODE_ESC :
			e.cancel();
			this.clearResults();
			break;
	}

};

SymbolSearch.prototype.highlightRow = function(rowIdx) {
	if (this.selectedRow != rowIdx) {
		if (this.elResultRows[this.selectedRow]) {
			Element.removeClass(this.elResultRows[this.selectedRow], this.CSS_SELECTED);		
		}
		
		if (this.elResultRows[rowIdx]) {
			Element.addClass(this.elResultRows[rowIdx], this.CSS_SELECTED)
		}
		
		this.selectedRow = rowIdx;
	}

};

SymbolSearch.prototype.selectResult = function(e) {
	//if ("click" == e.nativeEvent.type || this.KEY_CODE_ENTER == e.nativeEvent.keyCode) {
	if ("click" == e.nativeEvent.type) {
		e.cancel();

		if (this.selectedRow == -1) {
			// only one result, go to it
			if (this.elResultRows && 1 == this.elResultRows.length) {
				var passSymbol = this.elResultRows[0].getAttribute("symbol");
				var passName = this.elResultRows[0].getAttribute("name");
				if ("-32768" != this.elResultRows[0].getAttribute("symbol")) {
					passSymbol = this.elResultRows[0].getAttribute("symbol");
					passName = this.elResultRows[0].getAttribute("name");
				}
				this.go(passSymbol, passName);
			} else {
				//multiple results, just submit the form?
				this.go(this.query);
			}
		} else {
			if (Element.hasClass(this.elResultRows[this.selectedRow], this.CSS_MORE_LINK)) {
				window.location = this.elMoreLink.href;
			} else {
				var passSymbol = this.elResultRows[this.selectedRow].getAttribute("symbol");
				var passName = this.elResultRows[this.selectedRow].getAttribute("name");
				if ("-32768" != this.elResultRows[this.selectedRow].getAttribute("symbol")) {
					passSymbol = this.elResultRows[this.selectedRow].getAttribute("symbol");
					passName = this.elResultRows[this.selectedRow].getAttribute("name");
				}
				this.go(passSymbol, passName);
			}
		}
	}
};

SymbolSearch.prototype.go = function(symbol, name){
    if (symbol) {
        this.query = symbol;
        this.elInput.value = name;
        this.elInput.style.color = 'black';
		this.elHidden.value = symbol;
    }
    this.clearResults();
};

SymbolSearch.prototype.abortActiveRequests = function() {
	this.requestor.abortRequests();
};