nfl.namespace('nfl.data');

nfl.data.livefilter	= Class.create();
nfl.data.livefilter.prototype	= {
	initialize: function(searchBox){
		this.__boundObject		= searchBox;
		this.__defaultValue		= this.__boundObject.value;
		this.__hasFocused		= false;
		Event.observe(this.__boundObject,'keypress',this.onKeyPress.bindAsEventListener(this));
		Event.observe(this.__boundObject,'focus',this.onFocus.bind(this));
		Event.observe(this.__boundObject,'blur',this.onBlur.bind(this));
	},
	onFocus: function(e){
		/* this is really dumb, but since we can't use event.stopObserving in this instance
		 * use a simple flag check (I KNOW I KNOW)
		 */
		if(!this.__hasFocused){
			nfl.log("livefilter: onFocus");
			this.__boundObject.value	= "";
			this.__boundObject.removeClassName("activesearch-displaymessage");
			this.__hasFocused			= true;
		}
	},
	onKeyPress: function(e){
		var evt					= (e) ? e : window.event;
		var currKeyCode;
		var currKeyChar;
		if(window.event){
			currKeyCode = e.keyCode;
		}
		else if(e.which){
			currKeyCode = e.which;
		}
		var currKeyChar			= String.fromCharCode(currKeyCode);
		var currTotalVal		= (Event.element(e).value).strip().toUpperCase();
		nfl.log("livefilter.onKeyPress: currKeyChar = "+ currKeyChar);
		if(("abcdefghijklmnopqrstuvwxyz0123456789").indexOf(currKeyChar.toLowerCase()) > -1){
			var currTotalVal	= (Event.element(e).value + currKeyChar).strip().toUpperCase();
		}else{
			 if(currKeyCode == 8){
			 	var currTotalVal	= currTotalVal.substring(0, currTotalVal.length - 1);
			 }
		}
		document.fire("livefilter:change",{value:currTotalVal});
	},
	onBlur: function(){
		document.fire("livefilter:blur",this.__boundObject.value);
	},
	reset: function(){
		this.__boundObject.value	= this.__defaultValue;
		this.__boundObject.addClassName("activesearch-displaymessage");
		this.__hasFocused			= false;
	}
}

nfl.data.dataset	= Class.create();
nfl.data.dataset.prototype	= {
	initialize: function(object){
		//Object.Event.extend(this);
		
		this.__dataset			= object;
		this.__filters			= [{field: "positionGroup", criteria: "QB", operator: "startsWith"}];
		this.__filteredDataSet	= null;
		this.itemsPerPage		= 500;
		this.currentPage		= 1;
		this.__databoundobject	= null;
		this.__boundObjects		= [];
		this.__sortBy			= null;
		this.__isDirty			= true;
		//this.__sortBy				= {field: "lastName",direction:"descending"};
		
		this.__headerData		= {}
		this.templates			= {};
		this.templates.body		= "<table id=\"#{objid}\" class=\"#{objclass}\" cellspacing=\"#{objcellspacing}\" cellpadding=\"#{objcellpadding}\" width=\"#{objwidth}\">#{header}<tbody>#{rows}</tbody></table>";
		this.templates.header	= "<tr></tr>";
		this.templates.row		= "<tr></tr>";
		this.templates.toggle	= "#{toggleicon}";
	},
	bindTo: function(obj){
		this.__databoundobject	= obj;
	},
	bind: function(){
		var __outputResult				= {};
		var __rowTemplate				= new Template(this.templates.row);
		var __resultTemplate			= new Template(this.templates.body);
		__outputResult.objid			= (typeof this.__databoundobject.id != 'undefined') ? this.__databoundobject.id : "data-grid-table";
		__outputResult.objclass			= (typeof this.__databoundobject.className != 'undefined') ? this.__databoundobject.className : "data-grid-table";
		__outputResult.objcellspacing	= (this.__databoundobject.hasAttribute("cellspacing")) ? this.__databoundobject.getAttribute("cellspacing") : "0";
		__outputResult.objcellpadding	= (this.__databoundobject.hasAttribute("cellpadding")) ? this.__databoundobject.getAttribute("cellpadding") : "0";
		__outputResult.objwidth			= (this.__databoundobject.hasAttribute("width")) ? this.__databoundobject.getAttribute("width") : "100%";
		__outputResult.header			= this.templates.header;
		__outputResult.rand				= (Math.ceil(Math.random()*1) * 1000);
		__outputResult.rowClass			= (typeof this.templates.rowClass != 'undefined')? this.templates.rowClass:"data-row";
		__outputResult.rowClassAlt		= (typeof this.templates.rowClassAlt != 'undefined')? this.templates.rowClassAlt:"data-row-alt";
		__outputResult.toggle			= new Template(this.templates.toggle);
		
		/* start row output template iteration */
		__outputResult.rows				= "";
		var rowAlt						= false;
		for(var fdIndex=0, len=this.size(); fdIndex < len; ++fdIndex){
			var key	= this.__filteredDataSetKeys[fdIndex];
			var resetCalculatedFields = false;
			this.__filteredDataSet[key].objid		= __outputResult.objid;
			if(typeof this.__filteredDataSet[key].rowclass == 'undefined' || this.__filteredDataSet[key].rowclass == null){
				this.__filteredDataSet[key].rowclass	= rowAlt? __outputResult.rowClassAlt : __outputResult.rowClass;
				resetCalculatedFields = true;
			}
			if(typeof this.__filteredDataSet[key].toggle != "undefined" && this.__filteredDataSet[key].toggle != false){
				this.__filteredDataSet[key].toggle		= __outputResult.toggle.evaluate(this.__filteredDataSet[key]);
			}else{ this.__filteredDataSet[key].toggle = "";}
			rowAlt = rowAlt? false:true;
			__outputResult.rows			+= __rowTemplate.evaluate(this.__filteredDataSet[key]);
			if(resetCalculatedFields){
				this.__filteredDataSet[key].rowclass = null;
			}
		}
		/* end row output template iteration */
		var result						= __resultTemplate.evaluate(__outputResult);
		
		//nfl.log("dataset.bind:\n\r"+ result);
		if(this.size() > 0){
			this.__databoundobject.up().removeClassName("no-results");
			this.__databoundobject.replace(result);
			this.__databoundobject	= $(__outputResult.objid);
		}else{
			this.__databoundobject.up().addClassName("no-results");
		}
		delete __outputResult; delete result; delete __rowTemplate; delete __resultTemplate;
		//return result
	},
	/*
	 * filterBy
	**/
	filterBy: function(field,operator,criteria){
		/* TODO - make filters append to the filter array */
		if(this.__filters.length >= 0 && this.__filters[0].field != field || this.__filters[0].criteria != criteria || this.__filters[0].operator != operator){ this.__isDirty = true; nfl.log("isDirty flag set to true"); }
		//this.__filters		= [];
		this.__filters[0]	= {"field": field, "criteria": criteria, "operator": operator};
		nfl.log("filterBy: {field: "+ this.__filters[0].field +", criteria: "+ this.__filters[0].criteria +", operator: "+ this.__filters[0].operator +"}");
	},
	filter: function(){
		
		if(this.__isDirty){
			this.__filteredDataSet		= {};
			this.__sortArray			= [];
			this.__sortAssocArray		= [];
			this.__filteredDataSetSize	= 0;
			this.__filteredDataSetKeys	= [];
			for(var key in this.__dataset) {
				var rowKey		= key;
				var rowItem		= this.__dataset[key];
				var appendRow	= true;
				for(var f=0,flen=this.__filters.length;f<flen;++f) {
					/* check for filter match */
					
					if(typeof rowItem != "undefined" && rowItem != null && typeof this.__filters[f] != "undefined" && this.__filters[f] != null){
						//nfl.log("filter: filtering by "+ this.__filters[f].criteria +" on "+ this.__filters[f].field);
						if(typeof rowItem[this.__filters[f].field] != "undefined"){
							if(rowItem[this.__filters[f].field] != null){
								//if(this.__filters[f].field == "positionGroup" && this.__filters[f].criteria.indexOf("SPECIALISTS") > -1){ alert("looking for specialists:\n\rthis.__filters[f].criteria.indexOf(\"SPECIALISTS\") = "+this.__filters[f].criteria.indexOf("SPECIALISTS")+"\n\r\""+this.__filters[f].criteria+"\" == \"SPECIALISTS\"? "+(this.__filters[f].criteria == "SPECIALISTS"));}
								if(this.__filters[f].operator == '='){
									if(typeof rowItem[this.__filters[f].field] == "number" && rowItem[this.__filters[f].field] != this.__filters[f].criteria){ appendRow = false; }
									if(typeof rowItem[this.__filters[f].field] == "string" && rowItem[this.__filters[f].field].toUpperCase() != this.__filters[f].criteria.toUpperCase()){ appendRow = false; }
								}
								if(this.__filters[f].operator == 'startsWith'){
									if(rowItem[this.__filters[f].field].toUpperCase().indexOf(this.__filters[f].criteria.toUpperCase()) != 0){ appendRow = false; }
								}
								//nfl.log("tested "+ rowItem[this.__filters[f].field] +" against '"+ this.__filters[f].operator +"' on "+ this.__filters[f].criteria +" which is of type \""+ (typeof rowItem[this.__filters[f].field])+"\"");
							}else{
								/* field is null, automatically fail */
								//nfl.log("rowItem["+this.__filters[f].field+"] is null");
								appendRow = false; break;
							}
						}else{
							/* does not have property, criteria check fail */
							//nfl.log("typeof rowItem["+ this.__filters[f].field +"] = "+ (typeof rowItem[this.__filters[f].field]));
							appendRow = false; break;
						}
					}else{
						/* row has either been removed or never existed */
						appendRow = false; break;
					}
				}
				if(appendRow){
					/* row matches all filters, append to filtered results */
					this.__filteredDataSet[rowKey]	= rowItem;
					this.__filteredDataSetSize++;
					this.__filteredDataSetKeys[this.__filteredDataSetKeys.length]	= key;
					/* now add the sort field to the sortArray if applicable*/
					if(this.__sortBy != null){
						this.__sortArray[this.__sortArray.length]	= rowItem[this.__sortBy.field];
						this.__sortAssocArray[rowItem[this.__sortBy.field]]	= rowKey;
					}
					//nfl.log("Added this.__filteredDataSet["+ rowKey +"] = "+ this.__filteredDataSet[rowKey]);
				}
			}
			if(this.__sortBy != null){
				//nfl.log("this.__sortArray.length = "+ this.__sortArray.length +"\n\rthis.__sortArray = "+ this.__sortArray.join(",\n\r"));
				var sortedFilteredDataSet	= {};
				this.__filteredDataSetKeys	= [];
				this.__sortArray.sort(this.__sortBy.sortFunction);
				//this.__sortArray.sortBy(this.__sortBy.sortFunction);
				var strDebug = "sortedFilteredDataSet: \n\r";
				//nfl.log("filter.sortArray: "+ this.__sortArray.join(",\n\r"));
				for(var index=0, len=this.__sortArray.length; index < len; ++index) {
					var itemSortKey = this.__sortArray[index];
					var rowKey		= this.__sortAssocArray[itemSortKey];
					strDebug	+=("adding this.__filteredDataSet["+rowKey+"] to sortedFilteredDataSet["+ rowKey+"]\n\r"); 
					sortedFilteredDataSet[rowKey]	= this.__filteredDataSet[rowKey];
					this.__filteredDataSetKeys[this.__filteredDataSetKeys.length]	= rowKey;
				}
				
				//nfl.log(strDebug);
				this.__filteredDataSet		= sortedFilteredDataSet;
			}
			this.__isDirty	= false;
		}else{ nfl.log("filter: NOT isDirty. skipping sort/filter procedure.."); }
	},
	sortBy: function(fieldname,rowKeyPropName,sortfunction){
		this.__sortBy	= {field: fieldname,rowkey:rowKeyPropName, sortFunction:sortfunction};
	},
	sort: function(){
		var sortArray	= [];
		
	},
	total: function(){},
	size: function(){
		if(this.__filters.length > 0){
			return this.__filteredDataSetSize
		}else{
			return this.__dataSetSize.length;
		}
	},
	/*
	 * inspect
	 * return string contents of internal dataset
	 */
	inspect: function(){
		var retStr		= "{\n\r";
		var increment1	= 0;
		//var objKeys	= Object.keys(this.__dataset);
		var objVals		= Object.values(this.__dataset);
		
		for(var key in this.__dataset) {
			var rowKey		= key;
			var rowItem		= this.__dataset[key];
			var rowItemKeys	= Object.keys(rowItem);
			var rowItemVals	= Object.values(rowItem);
			var increment2	= 0;
			
			retStr	+= ("\t"+rowKey+":{ ");
			for(var propKey in rowItem) {
				retStr	+= (propKey+": "+rowItem[propKey]);
				if(increment2 < (rowItemVals.length - 1)){
					retStr	+= ", ";
				}
				increment2++
			}
			retStr	+= ("}");
			if(increment1 < (objVals.length - 1)){
				retStr	+= ",";
			}
			retStr	+= ("\n\r");
			increment1++;
		}
		retStr	+= "}\n\r";
		return retStr;
	}
}