/**
	@author 		Al McNichol
	@lastmodified 	6.29.2009
	@version 		1.3
	
	Dependency:
	FilePath: /.element/js/libs/prototype-1.6.0.3.js
	
	Change History:
	06.17.2009 - created
	06.24.2009 - clean-up and added comments
	06.29.2009 - peer review changes
	06.30.2009 - combined filter logic to one function _getFilteredList()
	07.01.2009 - dynamically construct json filename based on year in url path
	07.02.2009 - optimization - clean up on DisplayException()
	
	
*/
/*******************************************************************************
 * Namespace: nbaFaTracker
 *******************************************************************************/
 window.nbaFaTracker = function(){}
 
/*******************************************************************************
 * Global Variables
 *******************************************************************************/
 window.nbaFaTrackerObj = null;
 
/*******************************************************************************
 * FreeAgentTracker Object, which is ultimately loaded with a scrubbed JSON.
 * Note: Depending on the columns to be displayed the JSON is re-factored to
 * only include the appropriate data elements. Some degradation in the load time
 * but much faster when diplayed, sorted, or filtered.
 *******************************************************************************/
nbaFaTracker.FreeAgentTracker = function()
{
	var metaData 		= null;
	var listHead 		= null;
	var listData 		= new Array();
	var listFoot 		= null;
	var listCache		= null;
	var listContainer 	= "";		
	var isActiveView	= false;
	var isActiveList	= false;
	
	this.loadJson 		= _loadJson;
	this.filterByView 	= _filterByView;
	this.filterByViewEx = _filterByViewEx;
	this.resetList 		= _resetList;
	this.filterDropdown	= _filterDropdown;
	this.writeTable		= _writeTable;
	
	
	/**
	* Loads json and sets up the data elements for display
	*
	* @param {Object} the json object
	* @param {String} the ID of the div container to display table
	*/
	function _loadJson(oJson, oListContainerDiv)
	{
		if( oJson != null && typeof oJson == 'object')
		{
			metaData 		= oJson.metaData;   //object
			listHead 		= oJson.listHead; 	//array
			listData 		= oJson.listData;   //arry of objects
			listContainer	= oListContainerDiv;//Div ID that will hold the listed table
			
			
			//_sortData(listData, 0) //this is used for sorting but not required for this implementation
			listCache = listData 	 //Add the list to Cache and display the original list
			_writeTable(listCache);	 //spit out the table
			
			
			//Setup and display updated date and filter selection DIVs
			$("nbaFatModDate").innerHTML = "Updated: " + metaData.lastModified;
			Element.show("nbaListFilters");			
			Element.show("nbaFatModDate");
			listViewHandler("view", "all");
			
		}else{
			nbaFaTracker.MsgLogger("loadJson(): Unable to load Json!");
		}
	}
	
	/**
	* method to display subset of data elements
	*
	* @param {string} oFilterType - filter type [view | list]
	* @param {String} oFilterSel - [all | available | signed]
	* @param {number} oCol - column to filter on
	* @param {String} oVal - value to filter by
	*/
	function _filterByView(oFilterType, oFilterSel, oCol, oVal)
	{
		if (listData.length > 0){
			listCache = _getFilteredList(listData, oCol, oVal, "eq")			
		}
		_writeTable(listCache);
		listViewHandler(oFilterType, oFilterSel);
	}
	
	/**
	* method to display subset of data elements - 
	* same as _filterByView() but value are compared not equal to
	*
	* @param {string} oFilterType - filter type [view | list]
	* @param {String} oFilterSel - [all | available | signed]
	* @param {number} oCol - column to filter on
	* @param {String} oVal - value to filter by
	*/
	function _filterByViewEx(oFilterType, oFilterSel, oCol, oVal)
	{
		if (listData.length > 0){
			listCache = _getFilteredList(listData, oCol, oVal, "neq")
		}
		_writeTable(listCache);
		listViewHandler(oFilterType, oFilterSel);
	}
	
	/**
	* method to display subset of data elements based on select 
	* HTML elements
	*
	* @param {object} oSelBox - HTML select object
	* @param {number} oCol - column to filter on
	*/
	function _filterDropdown(oSelBox, oCol)
	{
		var tempList 	= [];
		var oVal 	 	= oSelBox.options[oSelBox.selectedIndex].value;
			
		if (oVal != "none")
		{
			if (listCache.length > 0)
			{
				_writeTable(_getFilteredList(listCache, oCol, oVal, "eq"));				
			}else{
				_writeTable(listCache);
			}
		}
		listViewHandler("list", oSelBox.id);
	}
	
	/**
	* Get filtered list by assigning the data set to the listCache 
	*/
	function _getFilteredList(oListObj, oCol, oSearchVal, oOperand)
	{
		var tempList = [];
		
		if (oListObj.length > 0)
		{
			if (oOperand == "eq")
			{
				for (var rowIndex = 0; rowIndex < oListObj.length; rowIndex++)
				{
					var colKey = "col" + oCol;
					if ( (String(oListObj[rowIndex][colKey].rawVal)).toUpperCase() == (String(oSearchVal)).toUpperCase() ){
						tempList.push(oListObj[rowIndex]);
					}
				}
			}
			else //oOperand == "neq"
			{
				for (var rowIndex = 0; rowIndex < oListObj.length; rowIndex++)
				{
					var colKey = "col" + oCol;
					if ( (String(oListObj[rowIndex][colKey].rawVal)).toUpperCase() != (String(oSearchVal)).toUpperCase() ){
						tempList.push(oListObj[rowIndex]);
					}
				}
			}
		}
		return tempList;
	}
	
	/**
	* reset the list by assigning the data set to the listCache 
	*/
	function _resetList()
	{
		listCache = listData; 	//Refresh the cache with initially loaded info
		_writeTable(listCache);
		listViewHandler("view", "all");
	}
	
	/**
	* Generate the HTML table
	* HTML elements
	*
	* @param {object} oListData - array of objects to be constructed from
	*/
	function _writeTable(oListData)
	{
		nbaFaTracker.MsgLogger("WORKING...") //Provide feedback to user as renedering may take a few seconds
		
		window.setTimeout(function() //Delay processing slightly to allow time to display "Working..." verbiage
		{
			var rowColor = "#ffffff";
			var listHeadHTML = "";
			var listDataHTML = "";
					
			//Build the column heading
			listHeadHTML += '<tr  class="nbaFATHdrRowBG">';
				
			for(var i=0; i < listHead.length; i++)
			{
				listHeadHTML += '<td class="nbaFATpad">' + listHead[i] + '</td>';
			}
			listHeadHTML += '</tr>';
			
			//Build the Body
			listDataHTML += '<table class="nbaFATtbleSty">';
			listDataHTML += listHeadHTML;
			
			if (oListData.length > 0)
			{
					for (var rowIndex = 0; rowIndex < oListData.length; rowIndex++)
					{
						if (rowIndex%10 == 0 && rowIndex > 0)	{	listDataHTML += listHeadHTML;}
						listDataHTML += '<tr>';
						for (var colIndex = 0; colIndex < listHead.length; colIndex++)
						{
							listDataHTML += '<td class="nbaFATpad" bgcolor="' + ((rowIndex%2 == 0) ? "#ffffff" : "#f1f1f1") + '">' + eval("oListData[rowIndex].col" + colIndex + ".displayVal") + '</td>';
						}
						listDataHTML += '</tr>';
					}
			}else{
					listDataHTML += '<tr><td class="nbaFATpad" colspan="' + listHead.length + '">No information for selection!</tr>';
			}
			listDataHTML += '</table>'
			$(listContainer).innerHTML = listDataHTML;
		
		}, 1);
	}
	
	/**
	* Sorting feature - not being used but available
	*/
	function _sortData(oListData, oCol)
	{
		sortCol = oCol
		return oListData.sort(sortFunc)
	}
	
	/**
	* Sorting feature - not being used but available
	*/
	function sortFunc(object1, object2)
	{
		var colKey = "col" + sortCol;
		
		if (object1[colKey].rawVal < object2[colKey].rawVal){
				retVal=-1;
		}else if (object1[colKey].rawVal > object2[colKey].rawVal){
				retVal=1;
		}else{
				retVal=0;
		}
		return retVal;
	}
	
	/**
	* Reset select boxes based filter action
	*/
	function listViewHandler(oType, oSelected)
	{
		var HTMLelements = {
							 views:{
									 all:"nbaFatViewAll", 
									 available:"nbaFatViewAvailable", 
									 signed:"nbaFatViewSigned"
								   },
							 lists:[
									 "nbaOldTeam_selBox", 
									 "nbaNewTeam_selBox", 
									 "nbaPosition_selBox"											
									]
							};
		
		var viewHighlight = function (){
			
			for (var oViewKey in HTMLelements.views)
			{
				if ( String(oViewKey) == String(oSelected) ){
					//alert(".addClassName('activeLink') = " + oViewKey + " : " + oSelected );
					($(HTMLelements.views[oViewKey])).addClassName('nbaFatViewActive');	
				}else{
					//alert(".removeClassName('activeLink') = " + oViewKey + " : " + oSelected );
					($(HTMLelements.views[oViewKey])).removeClassName('nbaFatViewActive');
				}
			}
		};
		
		switch(String(oType))
		{
			case "view":
								
					//highlight selected view
					viewHighlight();
							
					//reset all select Elements
					for (var oListKey = 0; oListKey < HTMLelements.lists.length; oListKey++){
						$(HTMLelements.lists[oListKey]).selectedIndex = 0
					}
					
					//disable or enable dropdowns based on view selection
					switch(oSelected)
					{
						case "all": 		$(HTMLelements.lists[1]).disabled = true; break;
						case "available": 	$(HTMLelements.lists[1]).disabled = true; break;								
						case "signed": 
								for (var oListKey = 0; oListKey < HTMLelements.lists.length; oListKey++){
									$(HTMLelements.lists[oListKey]).disabled = false;
								}
								break;
						default:
							//do nothing
					}
					break;
					
			case "list":
					for (var oListKey = 0; oListKey < HTMLelements.lists.length; oListKey++)
					{
						if (String(HTMLelements.lists[oListKey]) != String(oSelected) ){
							$(HTMLelements.lists[oListKey]).selectedIndex = 0	
						}
					}
					break;
			default:
				//do nothing
		}
	}
}

/*******************
* Utility to log error/status message to provide feedback to the actor
*
* @param {String} the ID of the div container to display message
*/
nbaFaTracker.MsgLogger = function(oErrMsg)
{
 	 $("nbaFatListContainer").innerHTML = '<div class="nbaFatStatusMsg">' + oErrMsg + '</div>';
}

/*******************
* Class to wrap prototype Ajax.Updater to provide a more elegant approach 
* to error handle and reporting.
*
* @param {String} url - the path to file
* @param {object} options - name value pair of options
*/
nbaFaTracker.AjaxRequester = Class.create(Ajax.Request, {
  initialize: function($super, url, options) {
    $super(url,nbaFaTracker.AjaxOptions(options));
  }
})


/*******************
* Option object to pass to nbaFaTracker.AjaxRequester wrapper 
* 
* @param {object} options - name value pair of options
*/
nbaFaTracker.AjaxOptions = function (options) {
  return Object.extend({
     asynchronous:false,
     //evalScripts:true,
     //evalJSON:true,
     //contentType:"application/json",
     onLoading: function(request){
     	//Element.hide('nbaListFilters');
     },
     onException: function(request,exception) {
       nbaFaTracker.MsgLogger('onException(): Unexpected Exception: "' + exception + '" was thrown accessing | ' + request.url);
       return false
     },
     onFailure: function(t) {
       nbaFaTracker.MsgLogger('onFailure(): Unexpected Error: ' + t.status + ': ' + t.statusText);
       return false
     },
     on404: function(t) {
       nbaFaTracker.MsgLogger('on404(): ' + t.status + ' | JSON File Requested ' + t.statusText);
       return false
     },
     onComplete:function(t){
     	//window.setTimeout('Element.hide("nbaAjaxLoading");', 100);
     },
     onSuccess: function(t){
     	try{
     		nbaFaTracker.AjaxResponse(t.responseText.evalJSON());
     	}catch(eRR){
     		nbaFaTracker.MsgLogger('onSuccess(): SyntaxError: Badly formated JSON string!');
     	}
     	return true;
    }
  }, options || {});
}

/******************
* AjaxResponse() - If json retrieval was successful then this is the response
* handler, which basically scrubbed the json (normalize the data based on required
* display columns) and then load it into the Fatracker Object 
* 
* @param {object} json - returned from Ajax call
*/
nbaFaTracker.AjaxResponse = function(oRawJSON)
{
	var oCleanJSON = null;
		oCleanJSON = nbaFaTracker.JsonScrub(oRawJSON)
		nbaFaTrackerObj.loadJson(oCleanJSON, "nbaFatListContainer")
		return true;
}

/*******************
* Scrub JSON based on expected columns and list layout.
* 
* @param {object} json - returned from Ajax response
*/
nbaFaTracker.JsonScrub = function(jsonObj)
{
 	var colIndex = 0;
 	var rowIndex = 0;  
 	var tmpJson = {};
 	
 	//Construct the table column titles
 	tmpJson.metaData = jsonObj.metaData;
 	tmpJson.listHead = [
							jsonObj.listHead.col1, //col[0]Player
							jsonObj.listHead.col2, //col[1]Staus
							jsonObj.listHead.col3, //col[2]Exp./Type
							jsonObj.listHead.col4, //col[3]Old Team
							jsonObj.listHead.col5, //col[4]New Team
							jsonObj.listHead.col6, //col[5]Position
							jsonObj.listHead.col7, //col[6]Age
							jsonObj.listHead.col8, //col[7]years
							"More"				   //col[8]More
					 	];
 						
 	//Construct related column values
 	tmpJson.listData = [];
	for (rowIndex = 0; rowIndex < jsonObj.listData.length; rowIndex++)
	{	
		var objArry	 = new Array();
		for (var dataKey in jsonObj.listData[rowIndex])
		{
			switch(dataKey)
			{
				case "col1": objArry.push({"rawVal":jsonObj.listData[rowIndex].col1, "displayVal":nbaFaTracker.DisplayException("col1", jsonObj.listData[rowIndex])}); break;
				case "col2": objArry.push({"rawVal":jsonObj.listData[rowIndex].col2, "displayVal":jsonObj.listData[rowIndex].col2}); break;
				case "col3": objArry.push({"rawVal":jsonObj.listData[rowIndex].col3, "displayVal":jsonObj.listData[rowIndex].col3}); break;
				case "col4": objArry.push({"rawVal":jsonObj.listData[rowIndex].col4, "displayVal":jsonObj.listData[rowIndex].col4}); break;
				case "col5": objArry.push({"rawVal":jsonObj.listData[rowIndex].col5, "displayVal":jsonObj.listData[rowIndex].col5}); break;
				case "col6": objArry.push({"rawVal":jsonObj.listData[rowIndex].col6, "displayVal":jsonObj.listData[rowIndex].col6}); break;
				case "col7": objArry.push({"rawVal":jsonObj.listData[rowIndex].col7, "displayVal":jsonObj.listData[rowIndex].col7}); break;
				case "col8": objArry.push({"rawVal":jsonObj.listData[rowIndex].col8, "displayVal":jsonObj.listData[rowIndex].col8}); break;
				//case "col9": objArry.push({"rawVal":jsonObj.listData[rowIndex].col9, "displayVal":jsonObj.listData[rowIndex]}); break;
				default://do nothing							
			}
		}
		//Add data for more column
		objArry.push({"rawVal":"nothing", "displayVal":nbaFaTracker.DisplayException("more", jsonObj.listData[rowIndex])});
		
		tmpJson.listData[rowIndex] = {
										"col0":objArry[0],
										"col1":objArry[1],
										"col2":objArry[2],
										"col3":objArry[3],
										"col4":objArry[4],
										"col5":objArry[5],
										"col6":objArry[6],
										"col7":objArry[7],
										"col8":objArry[8]
							 		 }
	
	}
	return tmpJson; 	
}

/*******************
* Handles any data particulars like making the player's name withing
* Player colum hyper-linked with url information from the Player URL column
* 
* @param {string} column being affected
* @param {number} index into the array of objects
* @param {object} the array of objects
*/
nbaFaTracker.DisplayException = function(oCol, oDataRowObj)
{
	var retVal = "";
	switch(oCol){
		case "col1":
				var colPlayer 		= oDataRowObj.col1;
				var colPlayerUrl  	= oDataRowObj.col0;
					retVal 			= '<a href="http://www.nba.com' + colPlayerUrl + '">' + colPlayer + '</a>';
				break;
		case "more":
				var seperator		= "&nbsp;|&nbsp;"
				var storyHeadline 	= oDataRowObj.col9;
				var storyUrl  		= oDataRowObj.col10;
				var videoHeadline 	= oDataRowObj.col11;
				var videoUrl  		= oDataRowObj.col12;
				var videoAnchor		= (videoHeadline != "---") ? ('<a href="' + videoUrl + '">Video</a>') : "";
				var storyAnchor		= (storyHeadline != "---") ? ('<a href="' + storyUrl + '">Read...</a>') : "";
				
				if (videoAnchor != "" && storyAnchor != ""){
					retVal = (new String()).concat(videoAnchor,seperator,storyAnchor);
				}else{
					retVal = (new String()).concat(videoAnchor,storyAnchor);
				}
				break;
		default: //do nothing
	}
	return retVal;
}

/*******************
* nbaTracker_init() | Initialization after the page is loaded
*/
var nbaTracker_init = function(){
	
	//Create the FaTracker object
	nbaFaTrackerObj = new nbaFaTracker.FreeAgentTracker();
	
	//determine the year based on URL path (e.g. http://www.nba.com/freeagents/2009/)
	var locHref	= (String(window.location.href)).split("/");
	var jsonYr	= locHref[locHref.length-2]; //the last backslash in the string will cause an extra index in the array
	
	//Get the JSON
	var jsonDir  = "/.element/json/1.1/sect/freeagents/";
	var jsonFile = "freeagents" + jsonYr + ".json"
	var jsonPath = jsonDir + jsonFile;
	
	var AjaxObjt = new nbaFaTracker.AjaxRequester(jsonPath, {method: 'get'});
}
