/**
 * This class represent database recordset.
 * @package DHL::DB
 * @author Inoveo technologie inc.
 */
if (DHL == undefined) var DHL = {};
if (DHL.DB == undefined) DHL.DB = {};
(DHL.DB.RECORDSET = function () {

	this.aHeader;
	this.aHeaderByName;
	this.aData;
	this.aOriginalData;
	this.iRecordCount = 0;

	this.iCurrentRow = 0;
	this.iCurrentOriginalRow = 0;

	this.oEventListener = new Object();

	/**
	 * Wakeup instance using specified key pair object
	 * @param Object aData (associative array)
	 */
	DHL.DB.RECORDSET.prototype.__wakeUp = function __wakeUp(aData) {
		this.aHeader = aData['arrHeader'];
		if(this.aHeader.length) {
			this.aHeaderByName = new Object();
			//same as a header inversed
			for(var intIndex =0; intIndex < this.aHeader.length; intIndex++) {
				this.aHeaderByName[this.aHeader[intIndex]] = intIndex;
			}
		}
		else {
			this.aHeaderByName = aData['arrHeaderByName'];
		}
		this.aOriginalData = aData['arrData'];
		this.aData = aData['arrData'];
		this.iRecordCount = aData['intRecordCount'];
	}

	/**
	 * Add a listener function on specified event.
	 * @param string sEvent
	 * @param function fn
	 * @return integer listener id
	 */
	DHL.DB.RECORDSET.prototype.addListener = function(sEvent, fn) {
		if (typeof(this.oEventListener[sEvent]) == 'undefined') {
			this.oEventListener[sEvent] = new Array();
		}
		return this.oEventListener[sEvent].push(fn);
	}
	
	/**
	 * Add a listener function on specified event.
	 * @param integer listener id
	 * @return boolean
	 */
	DHL.DB.RECORDSET.prototype.removeListener = function(iId) {
		this.oEventListener[sEvent][iId] = null;
	}

	/**
	 * Notify all listener of specified event
	 * @param string sEvent
	 * @return boolean
	 */
	DHL.DB.RECORDSET.prototype.notifyListener = function(sEvent) {
		for(i in this.oEventListener[sEvent]) {
			this.oEventListener[sEvent][i](this);
		}
	}

	/**
	 * Apply a filter on current recordset.
	 * @param function
	 * @return boolean
	 */
	DHL.DB.RECORDSET.prototype.applyFilter = function(fnFilter) {
		var iNewRow = 0, iRow = 0, iCol = 0;
		var aRow = new Object();
		this.aData = new Array();
		for(iRow in this.aOriginalData) {
			for(iCol in this.aHeader) {
				aRow[this.aHeader[iCol]] = this.aOriginalData[iRow][iCol];
			}
			if (fnFilter(aRow)) {
				this.aData[iNewRow++] = this.aOriginalData[iRow];
			}
		}
		this.iRecordCount = iNewRow;
		this.iCurrentRow = 0;
		
		if(this.strSortFieldName) {
			this.sortData(this.strSortFieldName, this.fnSortCallback);
		}
		this.notifyListener(DHL.DB.RECORDSET.evFilterChange);
	}

	/**
	 * This method will sort the array with a user defined function
	 * @param function
	 * 
	 */
	DHL.DB.RECORDSET.prototype.sortData = function sortData(strFieldName, fnSort) {
		if(fnSort) {
			this.strSortFieldName = strFieldName;
			this.fnSortCallback = fnSort;
			
			var me = this;
			this.aData.sort(function(arrRow1, arrRow2) {
				return me.fnSortCallback(
					arrRow1[me.aHeaderByName[me.strSortFieldName]], 
					arrRow2[me.aHeaderByName[me.strSortFieldName]]
				);
			});
		}
	}

	/**
	 * Get the number of records in this record set.
	 * @return integer
	 */
	DHL.DB.RECORDSET.prototype.getRecordCount = function() {
		return this.iRecordCount;
	}

	/**
	 * Move internal cursor to specified row.
	 * @param integer iIndex
	 */
	DHL.DB.RECORDSET.prototype.seek = function(iIndex) {
		if (iIndex == undefined) { iIndex = 0; }
		this.iCurrentRow = iIndex;
	}

	/**
	 * Fetch next entry and return as key pair.
	 * @return object
	 */
	DHL.DB.RECORDSET.prototype.fetch = function() {
		var aRow = new Object();
		if (this.iCurrentRow >= this.iRecordCount) {
			return null;
		}
		for(i in this.aHeader) {
			aRow[this.aHeader[i]] = this.aData[this.iCurrentRow][i];
		}
		this.iCurrentRow++;
		return aRow;
	}
	
	DHL.DB.RECORDSET.prototype.setField = function(strHeaderName, varValue) {
		this.aOriginalData[this.iCurrentOriginalRow][this.aHeaderByName[strHeaderName]] = varValue;
	}
	
	DHL.DB.RECORDSET.prototype.next = function() {
		var blnReturn = false;
		if (this.iCurrentOriginalRow < this.iRecordCount-1) {
			this.iCurrentOriginalRow++;
			blnReturn = true;
		}
		return blnReturn;
	}
	
	DHL.DB.RECORDSET.prototype.previous = function() {
		var blnReturn = false;
		if (this.iCurrentOriginalRow > 0) {
			this.iCurrentOriginalRow--;
			blnReturn = true;
		}
		return blnReturn;
	}

	DHL.DB.RECORDSET.prototype.addField = function(strFieldName) {
		var blnAlreadyThere = false;
		for(var intI = 0; intI < this.aHeader.length && !blnAlreadyThere; intI++) {
			if(this.aHeader[intI] == strFieldName) {
				blnAlreadyThere = true;
			}
		}

		if(!blnAlreadyThere) {
			this.aHeader.push(strFieldName);
			this.aHeaderByName[strFieldName] = this.aHeader.length-1; 

			if(this.aOriginalData.length) {
				this._addField(this.aOriginalData, strFieldName);
			}

			if(this.aData.length) {
				this._addField(this.aData, strFieldName);
			}
		}
	}

	DHL.DB.RECORDSET.prototype._addField = function (aData, strField) {
		for(var intI =0 ; intI < aData.length; intI++) {
			aData[intI].push("");
		}
	}



	if (DHL.DB.RECORDSET.prototype.className == undefined) {
		var aInstance = new Object();

		DHL.DB.RECORDSET.wakeup = function(aData) {
			oRecordset = new DHL.DB.RECORDSET();
			oRecordset.__wakeUp(aData);
			return oRecordset;
		}

		DHL.DB.RECORDSET.evFilterChange = 'filterChange';

		DHL.DB.RECORDSET.prototype.className = 'DHL.DB.RECORDSET';
		DHL.DB.RECORDSET.prototype.jsClass = DHL.DB.RECORDSET;

		DHL.DB.RECORDSET.SORTORDERDESCENDANT = 'DHL.DB.RECORDSET';
		DHL.DB.RECORDSET.SORTORDERASCENDANT = 'DHL.DB.RECORDSET';
	}
	
})();
