SG.namespace("SG.cal.autocomplete");

SG.cal.autocomplete.CONTAINER = "autoCompContainer_";

/**
 * @namespace SG.cal.autocomplete
 * @class AutoComplete
 * @method AutoComplete
 * @description Creates new AutoComplete object
 */
SG.cal.autocomplete.AutoComplete = function(id, data, conf, additionalFieldId) {
	if (SG.cal.autocomplete[id]) {
		SG.log.info("AC '" + id + "' already exists and will be destroyed");
		SG.cal.autocomplete[id].destroy();
	} else {
	    YAHOO.util.Event.purgeElement(id, true);
	    YAHOO.util.Event.purgeElement(SG.cal.autocomplete.CONTAINER + id, true);
	}
	SG.log.info("Creating new AC '" + id + "'");

	this.additionalFieldId = additionalFieldId;

	this.conf = conf;

	var dataSource;
	var dataRetrievalAction = this.conf.dataRetrievalAction;
	if (dataRetrievalAction && dataRetrievalAction != "") {
		var start = dataRetrievalAction.indexOf('?');
		var action = dataRetrievalAction.substring(0, start);
		var additionalParameters = dataRetrievalAction.substring(start + 1, dataRetrievalAction.length);

		dataSource = new YAHOO.util.XHRDataSource(action);
		dataSource.scriptQueryAppend = additionalParameters;
		dataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
		dataSource.connMethodPost = true;
	} else {
		dataSource = new YAHOO.widget.DS_JSArray(data);
	}
	dataSource.responseSchema = {
		resultsList :"values",
		fields : [ "result", "addInfo", "key" ]
	};
	dataSource.queryMatchContains = this.conf.queryMatchContains;
	dataSource.queryMatchCase = this.conf.queryMatchCase;
	dataSource.maxCacheEntries = this.conf.maxCacheEntries;

	var elInput = id;
	var elContainer = SG.cal.autocomplete.CONTAINER + id;
	var oDataSource = dataSource;
	var oConfigs = this.conf;
	this.doBeforeQuery = this.conf.doBeforeQuery;

	this.constructor.superclass.constructor.call(this, elInput, elContainer, oDataSource, oConfigs);

	if (!SG.cal.util.isEmpty(this.conf.onClickFn)) {
		var fn = eval(this.conf.onClickFn);
		if (SG.cal.util.isFunction(fn)) {
			this.selectItemFn = fn;
		}
	}
	this.autoHighlight = false;
}

YAHOO.extend(SG.cal.autocomplete.AutoComplete, YAHOO.widget.AutoComplete, {

	additionalFieldId :null,
	conf :null,
	even :true,

	/**
	 * @namespace SG.cal.autocomplete
	 * @class AutoComplete
	 * @method AutoComplete
	 * @description Format result
	 */
	formatResult : function(oResultItem, sQuery) {
		var fn = eval(this.conf.formatFn);
		if (SG.cal.util.isFunction(fn)) {
			return fn(oResultItem, sQuery);
		} else {
			var evenodd = this.even ? "even" : "odd";
			this.even = !this.even;

			var result = oResultItem[0];
			var addInfo = oResultItem[1];

			var aMarkup = [ "<div class='autoComp-result-" + evenodd + "'>", result, addInfo, "</div>" ];
			return (aMarkup.join(""));
		}
	},

	/**
	 * @namespace SG.cal.autocomplete
	 * @class AutoComplete
	 * @method AutoComplete
	 * @description updates value of item
	 */
	_updateValue : function(oItem) {
		this.constructor.superclass._updateValue.call(this, oItem);

		var key = oItem._oResultData[2];
		if (this.additionalFieldId && this.additionalFieldId != "" && this.additionalFieldId != "null" && key
				&& key != "") {
			document.getElementById(this.additionalFieldId).value = key;
		}
	},

	/**
	 * @namespace SG.cal.autocomplete
	 * @class AutoComplete
	 * @method AutoComplete
	 * @description Populates list
	 */
	_populateList : function(sQuery, oResponse, oPayload) { // (sQuery,
		// aResults, oSelf)
		// {
		if (oResponse && oResponse.results) {
			var index = oResponse.results.length;

			if (index > 0 && oResponse.results[index - 1].result == "#more") {
				this.setFooter(oResponse.results[index - 1].addInfo);
				index--;
			} else {
				this.setFooter();
			}

			this.even = index % 2 == 0 ? false : true;

			this.constructor.superclass._populateList.call(this, sQuery, oResponse, oPayload);
		}
	},

	_selectItem : function(elListItem) {
		this.constructor.superclass._selectItem.call(this, elListItem);
		if (this.selectItemFn) {
			this.selectItemFn(elListItem);
		}
	}
});

/**
 * @namespace SG.cal.autocomplete
 * @class AutoComplete
 * @method doQuery
 * @description queries an object
 */
SG.cal.autocomplete.doQuery = function(oCallbackFn, sQuery, oParent) {
	if (oParent.doBeforeQuery) {
		var fn = eval(oParent.doBeforeQuery);
		if (SG.cal.util.isFunction(fn)) {
			var abortQuery = fn(oParent);
			if (abortQuery == true) {
				return;
			}
		}
	}
	var isXML = (this.responseType == YAHOO.widget.DS_XHR.TYPE_XML);
	var sUri = this.scriptURI;

	var oResponse = null;

	var oSelf = this;
	/*
	 * Sets up ajax request callback
	 * 
	 * @param {object} oReq HTTPXMLRequest object @private
	 */
	var responseSuccess = function(oResp) {
		// Response ID does not match last made request ID.
		if (!oSelf._oConn || (oResp.tId != oSelf._oConn.tId)) {
			oSelf.dataErrorEvent.fire(oSelf, oParent, sQuery, YAHOO.widget.DataSource.ERROR_DATANULL);
			return;
		}
		if (!isXML) {
			oResp = oResp.responseText;
		} else {
			oResp = oResp.responseXML;
		}
		if (oResp === null) {
			oSelf.dataErrorEvent.fire(oSelf, oParent, sQuery, YAHOO.widget.DataSource.ERROR_DATANULL);
			return;
		}

		var aResults = oSelf.parseResponse(sQuery, oResp, oParent);
		var resultObj = {};
		resultObj.query = decodeURIComponent(sQuery);
		resultObj.results = aResults;
		if (aResults === null) {
			oSelf.dataErrorEvent.fire(oSelf, oParent, sQuery, YAHOO.widget.DataSource.ERROR_DATAPARSE);
			aResults = [];
		} else {
			oSelf.getResultsEvent.fire(oSelf, oParent, sQuery, aResults);
			oSelf._addCacheElem(resultObj);
		}
		oCallbackFn(sQuery, aResults, oParent);
	};

	var responseFailure = function(oResp) {
		oSelf.dataErrorEvent.fire(oSelf, oParent, sQuery, YAHOO.widget.DS_XHR.ERROR_DATAXHR);
		return;
	};

	if (YAHOO.lang.isNumber(this.connTimeout) && (this.connTimeout > 0)) {
		oCallback.timeout = this.connTimeout;
	}

	if (this._oConn) {
		this.connMgr.abort(this._oConn);
	}

	var postParam = this.scriptQueryParam + "=" + sQuery;
	if (this.scriptQueryAppend.length > 0) {
		postParam += "&" + this.scriptQueryAppend;
	}
	if (oParent.dynamicParams) {
		for ( var param in oParent.dynamicParams) {
			postParam += "&" + param + "=" + oParent.dynamicParams[param];
		}
	}
	var overrides = {
		success :responseSuccess,
		failure :responseFailure
	}
	oSelf._oConn = SG.util.async.post(sUri, null, overrides, postParam);
};
