
var rows = 0;

// No. of cols is fixed. 
var cols = 3; 

var widgetCount = 0;

//current item selected in widget manager list
var currListClick=0;

//current category selected in widget manager
var currentManCat=1;

//Widget IDs
var widgetList= [];

//Widget Object, structure for widgetList
var widgetItem = new Object();
var syncState = true;

// Div containers for each player - array of {widgetHolder Ids}
var widgetHolders =[];

var slots = [],
	Event = YAHOO.util.Event, DDM = YAHOO.util.DDM;

var removedInstanceIDs = []; 

// Position where the widget should be added.
var addWidgetPosition = -1;

var sectionID = 0;

var rowIDs = [];
var rowStates = [];
var lastRowID = -1;

var widgetAddIsBusy = false;

var SECTION_HOME = 1, 
	SECTION_LOCAL = 2,
	SECTION_NEWS = 3,
	SECTION_ENTERTAINMENT = 4,
	SECTION_SPORTS = 5,
	SECTION_MUSIC = 6,
	SECTION_PHOTOS = 7,
	SECTION_GAMES = 8;

var ROW_STATE_COLLAPSED=0,ROW_STATE_EXPANDED=1;

var MAX_WIDGET_ROWS = 35;
var MAX_EXPANDED_WIDGET_ROWS = 5;

var sectionNames = new Array("None", "Home", "Local", "News", "Entertainment", "Sports", "Music", "Photos", "Games");

var widgetPreviews = new Array();


function escapeHTML (input) {
	var result = "";

	for( i=0; i<input.length; i++) {
		result += "&#"+input.charCodeAt(i)+";";
	}

	return result;
}

function unescapeHTML (input) {

	var result = input.replace(/&([a-zA-Z0-9]+);/g,
		function(wholematch, parenmatch1) {
			if( parenmatch1.charAt(0) == '#' )
				return String.fromCharCode(parseInt(parenmatch1.substring(1)));
			else {
				switch (parenmatch1)
				{
					case "lt":
						return "<";
					case "gt":
						return ">";
					case "amp":
						return "&";
					case "quot":
						return "'";
				};
			}
		}
	);

	return result;
}


function widgetsValidateLogIn() {
	if( widgetsIsLoggedIn == false ) {
		alert("You must be logged in to use this feature. Please log in. ");
		ssoLogin();
		return false;
	}
	else
		return true; 

}


function addWidget(widgetID,widgetURI) {
	if( widgetAddIsBusy == true ) {
		alert("Please wait until the previous widget has been added.")
		return;
	}

	if( widgetCount >= 105 ) {
		alert("You cannot add anymore widgets to this page.");
		return;
	}

	if( widgetsValidateLogIn() == false) 
		return;

	// Determine position to add widget and add an additional row if required. 
	if( addWidgetPosition == -1 ) 	{
		// Find the first empty slot. If all slots are filled, add a new row.
		for(var i=0; i<rows*cols; i++) {
			if(! slots[i].player )
			{
				addWidgetPosition = i;
				break;
			}
		}
		// Add new row if needed
		if( addWidgetPosition == -1)
		{
			addWidgetPosition = rows*cols;
			createNewRow();
		}
	} 

	var r = parseInt(addWidgetPosition / cols);
	var c = addWidgetPosition % cols;

	// Check if the row is collapsed and expand if needed. 
	if( document.getElementById('wcHolder_'+rowIDs[r]).style.display == "none" ) {
		collapseExpandRow(rowIDs[r], 'wcHolder_'+rowIDs[r], false);
	}



	toggleWidgetSlotBusy( r, c, true);

	YAHOO.example.Local_XML = new function() {
        this.connectionCallback = {
			success: function(o) {
				
				toggleWidgetSlotBusy( r, c, false);
				
			
				var status = ""; 
				if( o.getResponseHeader['X-status'] )
					status = o.getResponseHeader['X-status']; 
				else if( o.getResponseHeader['X-Status'] )
					status = o.getResponseHeader['X-Status'];

				if( status.indexOf("success") >= 0 ){

					index = widgetCount;
					widgetCount ++; 

					widgetList[index] = new Object();
					
					widgetList[index].widget_id = widgetID;
					widgetList[index].widget_url = replaceURLSizeParams(widgetURI);
					
					widgetList[index].widget_instance_id = o.responseText; // Get from response
					
					widgetList[index].widget_iframe_src= "widgets/container.jsp?id="+widgetList[index].widget_id+"&uri="+escape(widgetList[index].widget_url)+"&instanceID="+widgetList[index].widget_instance_id;
					widgetList[index].widget_position_favorites = -1;
					
					widgetList[index].row = parseInt(addWidgetPosition / cols);
					widgetList[index].col = addWidgetPosition % cols;

					setPlayerDivHTML(index, widgetList[index].widget_instance_id, ROW_STATE_EXPANDED);
					
					setPlayersToSlots(index, widgetList[index].widget_instance_id);
					
					addEmptyWidgetSlots();
					
					//toggleWidgetManager();
					// TODO: Is this needed? 
					////updateWidgetMatrix();
				}

				addWidgetPosition = -1;
            },
            failure: function(o) {
				//addWidgetPosition = -1;

				toggleWidgetSlotBusy( r, c, false);
				//toggleWidgetManager();
				alert("Unable to add widget at this time. Please try again later.");
	        }
        };

        this.getXML = YAHOO.util.Connect.asyncRequest("POST",
                "AddWidget",
                this.connectionCallback,
				"WidgetID="+widgetID+"&WidgetURI="+escape(widgetURI)+"&Section="+sectionID+"&Position="+addWidgetPosition);
    };
	
}




function returnEmptyWidget(playerindex){
	var emptyHTML = '<img onClick="toggleWidgetManager(\''+slots[playerindex].id+'\')" alt="" border="0" height="212" src="'+cdnUrl+'images/widgets/blank_widget.jpg" width="284" /><img src="'+cdnUrl+'images/widgets/handle.png" id="h' + playerindex +'" class="handle" style="display:none; padding-top: 8px;" />';
	return emptyHTML;
}

function hideName(anchor,row){
	if( widgetsIsLoggedIn == false ) {
		return;
	}
	var idToUse="newName_"+row;
	document.getElementById(idToUse).value=unescapeHTML( anchor.innerHTML );
	anchor.innerHTML="";
}

function changeName(row){
	if ( widgetsValidateLogIn() == false ) 
		return;

	var idToUse="inputName_"+row;
	document.getElementById(idToUse).style.display="inline";
}

function UpdateRow(rowNumber, rowName, rowState) {
	YAHOO.example.Local_XML = new function() {
        this.connectionCallback = {
			success: function(o) {
            },
            failure: function(o) {
	        }
        };

        this.getXML = YAHOO.util.Connect.asyncRequest("POST",
                "UpdateRow",
                this.connectionCallback,
				"Section="+sectionID+"&RowNumber="+rowNumber+"&RowName="+escape(rowName)+"&RowState="+rowState);
    };
}
function saveName(rowID){
	var idToUse="inputName_"+rowID;
	document.getElementById(idToUse).style.display="none";
	var nameIdToUse="nameLink_"+rowID;
	var valueIdToUse="newName_"+rowID;

	var rowName = document.getElementById(valueIdToUse).value;
	var rowNumber = parseInt(arrayIndexOf(rowIDs, rowID));

	if( rowName.length <= 0 ) {
		document.getElementById(nameIdToUse).innerHTML = "Name Row";
		return; 
	}
	
	rowName = escapeHTML (rowName);
	document.getElementById(nameIdToUse).innerHTML =  rowName ;

	UpdateRow(rowNumber, rowName, getRowState(rowNumber));
}

function saveRow(rowID, rowState){
	var nameIdToUse="nameLink_"+rowID;

	var rowName = document.getElementById(nameIdToUse).innerHTML;
	var rowNumber = parseInt(arrayIndexOf(rowIDs, rowID));

	if( rowName.length <= 0 ) {
		document.getElementById(nameIdToUse).innerHTML = "Name Row";
		return; 
	}
	rowName = escapeHTML (rowName);

	UpdateRow(rowNumber, rowName, rowState);
}

function deleteRow(rowID) {
	if ( widgetsValidateLogIn() == false ) 
		return;

	var answer = confirm("Are you sure you wish to delete this entire row?");
	if (answer == true){
		var row = arrayIndexOf(rowIDs, rowID); 
		for(var i=widgetCount-1; i>=0; i--)
			if( widgetList[i].row == row )
				removeWidget( widgetList[i].widget_instance_id, false);

		for(var i=0; i < cols; i++)
		{
			var slotDiv=document.getElementById(slots[row*cols+i].id);
			slotDiv.innerHTML='';
			slotDiv.style.height='0px';
		}


		slots = remove(slots, row*cols, row*cols+cols-1);

			
		var holderToRemove=document.getElementById('wcHolder_'+rowID);
		holderToRemove.style.height='0px';
		var d=document.getElementById('totalWidgetArea');
		var widgetRowToRemove=document.getElementById('widgetRow_'+rowID);
		d.removeChild(widgetRowToRemove);

		// Move widgets up. 
		for( var i=0; i < widgetCount; i++) {
			if( widgetList[i].row > row ) {
				YAHOO.util.DDM.moveToEl(widgetList[i].player.id, widgetList[i].player.slot.id);
				widgetList[i].row --; 
			}
		}

		rowIDs = remove(rowIDs, row);

		rows --;
		
		for( var i=0; i< rows*cols; i++)
			if( slots[i].row > row )
				slots[i].row --;
		
		saveCanvas(row);

		if( rows < MAX_WIDGET_ROWS ) {
			document.getElementById("widgetsAddMoreAnchor").style.display = "block";
			return;
		}
  }
}


function createNewRowHTML(rowState){
	var rowIndex = rowIDs.length;
	rowIDs[rowIndex] = lastRowID + 1;
	lastRowID = lastRowID + 1;

	var collapseExpandTxt; 
	var style;

	if( rowState == ROW_STATE_COLLAPSED ) {
		collapseExpandTxt = "Expand Row";
		style = '"height: 237px; _height: 252px; overflow: hidden; left: 0px; display: none;"';
	} else {
		collapseExpandTxt = "Collapse Row";
		style = '"height: 237px; _height: 252px; overflow: hidden; left: 0px;"';
	}

	// Collapse a row if the no. of rows increases. 
	if( rowState == ROW_STATE_EXPANDED ) {
		collapseExtraRow(rowIndex);
	}

	var rowHTML = '<div class="widgetsLinks" id="widgetLinkArea_'+lastRowID+'"><div class="widgetsLinksCenter">';
		rowHTML += '<div class="widgetsLinksLeft"><a id="nameLink_'+lastRowID+'" href="javascript:changeName('+lastRowID;
		rowHTML += ')" onclick="hideName(this,'+lastRowID+')">Name Row</a><div id="inputName_'+lastRowID;
		rowHTML += '" class="nameInput"><input type="text" class="inputSize" id="newName_'+lastRowID+'" maxlength="64"><input type="button" ';
		rowHTML += 'name="changeName_'+lastRowID+'" class="inputSize" value="Submit" onClick="saveName('+lastRowID+')"></div></div>';
		rowHTML += '<div class="widgetsLinksRight"><a id="wcHolder_'+lastRowID+'_a" href="javascript: collapseExpandRow('+ lastRowID +', \'wcHolder_'+lastRowID;
		rowHTML += '\',true);" >'+collapseExpandTxt+'</a> | <a href="javascript:deleteRow('+lastRowID+')">Delete Row</a></div></div></div>';
		//rowHTML += '<div class="widgetsLinksRight"><a href="javascript:deleteRow('+lastRowID+')">Delete Row</a></div></div></div>';

		//rowHTML += '<div class="widgetsLinksRight"> <a href="javascript:deleteRow('+rows+')">Delete Row</a></div></div></div>';
	    rowHTML += '<div class="widgetsDisplay" id="wcHolder_'+lastRowID+'" style='+style+'>';
		rowHTML += '<div class="widgetslots">';
		for(var i=0;i<cols;i++){
			rowHTML += returnSlotLineHTML((lastRowID*cols)+i);//returnSlotLineHTML((rows*cols)+i)
		}
		rowHTML += '</div></div><div class="clearBoth"></div>';


	var div = document.createElement("div");
	div.id = "widgetRow_" + lastRowID;
	div.innerHTML = rowHTML;

	document.getElementById("totalWidgetArea").appendChild(div);

	// Add widget holder
	var widgetHolderHTML = ""
	for(var i=0;i<cols;i++) {
		index = rows*cols + i;
		widgetHolderHTML += "<div id='widgetHolder_"+index+"' style='display: none;'></div>";
	}
	var div2 = document.createElement("div");
	div2.innerHTML = widgetHolderHTML;
	document.getElementById("totalWidgetArea").appendChild(div2);

	rows++;

	//htmlToChange=document.getElementById("totalWidgetArea").innerHTML;
	//document.getElementById("totalWidgetArea").innerHTML=htmlToChange+rowHTML;
	
	


}

function returnSlotLineHTML(slotIndex){
	var slotHTML ='<div class="widgetsItem"><div id="slot_'+slotIndex+'" class="slot"></div></div>';
	return slotHTML;
}

function swapIds(id1,id2){
	var el1=document.getElementById(id1);
	var el2=document.getElementById(id2);
	var temp=el1.id;
	el1.id=el2.id;
	el2.id=temp;
	var firstIdToSwap=id1.match(/[0-9]/);
	var secondIdToSwap=id2.match(/[0-9]/);
	var tempIdSwap=widgetList[firstIdToSwap];
	widgetList[firstIdToSwap]=widgetList[secondIdToSwap];
	widgetList[secondIdToSwap]=tempIdSwap;
	return;
}


function showBigger(imgToResize){
	imgToResize.width='150';
	imgToResize.height='140';
	imgToResize.style.position='relative';
	imgToResize.style.left='-10px';
	imgToResize.style.zIndex=100;
}
function showSmaller(imgToResize){
	imgToResize.width='75';
	imgToResize.height='70';
	imgToResize.style.position='relative';
	imgToResize.style.zIndex=0;
}

function changeWidgetManager(hide,show){
	document.getElementById(hide).style.display='none';
	document.getElementById(show).style.display='block';
}

function clickedWI(divElem){
	var idArray=divElem.id.split('_');
	if (currListClick){
		var wli=document.getElementById('widgetListItem_'+currListClick);
		wli.style.color='#ffffff';
	}
	var wli=document.getElementById('widgetListItem_'+idArray[1]);
	wli.style.color='#7BC143';
	currListClick=idArray[1];

	var newHTMLForPreviews='<div class="previewStyle"><br /><br /><img src="';
	newHTMLForPreviews += widgetPreviews[idArray[1]];
	newHTMLForPreviews+='" width="120" height="90"></div>';

	document.getElementById("widgetPreview_blank").innerHTML = newHTMLForPreviews;
}

function toggleWidgetManager(slotID){
		
	// If not logged in, and widget manager is being opened by clicking on an empty widget slot, show an error.  
	if(slotID && (widgetsValidateLogIn() == false) ) 
		return;
	
	if( slotID ) {
		for( var i=0; i<slots.length; i++ ) {
			if( slots[i].id == slotID ) {
				addWidgetPosition = i;
				break;
			}
		}
	}
	
	// If user clicked on a slot, move to the widget manager.
	if( slotID )
		location.href="#widgetManagerStart";
}

function changeCat(divElement, type, category){
	document.getElementById("subCanvasArea_list").innerHTML = '<img alt="" border="0" src="'+cdnUrl+ 'images/widgets/ajax-loader-2.gif" style="position:absolute; left:490px; top:130px" />';
	
	if( divElement != null ) {
		var idArray=divElement.id.split('_');
		var categoryToUse=idArray[1];
		var oldDivElement=document.getElementById('widgetCat_'+currentManCat);
		oldDivElement.className='widgetManCat';
		currentManCat=categoryToUse;
		divElement.className='widgetManHead';
	}
	
	//document.getElementById("subCanvasArea_list").innerHTML='';
	
	if( type == "first" ) {
		document.getElementById("categoryModule").innerHTML='';
	}

	var newHTMLForList='<div id="listingModule"><div class="bd">';
	//var newHTMLForPreviews='';

	YAHOO.example.Local_XML = new function() {
        this.connectionCallback = {
            success: function(o) {
				var xmlDoc = o.responseXML.documentElement;
				var requestType = xmlDoc.getElementsByTagName("Type")[0].childNodes[0].nodeValue;

				if( requestType == "first") {
					currentManCat = 0;
					var newHTMLForCategories = '<div class="bd">';
					var categories = xmlDoc.getElementsByTagName("Category");
					var i = 0;
					for(i=0;i<categories.length;i++){
						var categoryName = categories[i].childNodes[0].nodeValue;
						newHTMLForCategories += "<div id='widgetCat_"+i+"' onclick='changeCat(this, \"category\",\""+categoryName+"\")' ";
						if( i == 0 )
							newHTMLForCategories += "class='widgetManHead'"; 
						else
							newHTMLForCategories += "class='widgetManCat'"; 
						newHTMLForCategories += ">"+categoryName+"</div>";
					}
					newHTMLForCategories += "<div id='widgetCat_"+i+"' onclick='changeCat(this, \"all\",\"\")' ";
					if( i == 0 )
						newHTMLForCategories += "class='widgetManHead'"; 
					else
						newHTMLForCategories += "class='widgetManCat'"; 
					newHTMLForCategories += ">All</div>";		
					newHTMLForCategories += "</div>";

					document.getElementById("categoryModule").innerHTML = newHTMLForCategories;
				}
				var widgets=xmlDoc.getElementsByTagName("Widget");

				widgetPreviews = new Array();
				for(var i=0;i<widgets.length;i++){
					widgetIdToUse=widgets[i].getElementsByTagName("WidgetID")[0].childNodes[0].nodeValue;
					widgetUriToUse=widgets[i].getElementsByTagName("WidgetURI")[0].childNodes[0].nodeValue;
					widgetTitle=widgets[i].getElementsByTagName("Title")[0].childNodes[0].nodeValue;
					
					/*
					newHTMLForPreviews+='<div id="widgetPreview_'
					newHTMLForPreviews+=i;
					newHTMLForPreviews+='" class="widgetPreview"><div class="previewStyle"><br /><br /><img src="';
					
					if( widgets[i].getElementsByTagName("Thumbnail")[0].childNodes[0] ) {
						newHTMLForPreviews += widgets[i].getElementsByTagName("Thumbnail")[0].childNodes[0].nodeValue;
					}
					newHTMLForPreviews+='" width="120" height="90"></div></div>';
					*/
					widgetPreviews[i] = widgets[i].getElementsByTagName("Thumbnail")[0].childNodes[0].nodeValue;

					newHTMLForList+='<div class="widgetListItem" id="widgetListItem_';
					newHTMLForList+=i;
					newHTMLForList+='"><div id="widgetListTitle_'
					newHTMLForList+=i;
					newHTMLForList+='" class="widgetListTitle" onclick="clickedWI(this)">'
					newHTMLForList+=widgetTitle;
					newHTMLForList+='</div><div class="widgetListAdd" id="widgetListAdd_'
					newHTMLForList+=i;
					newHTMLForList+='"><a href="#" class="widgetListAdd" onclick="javascript:addWidget(\''+widgetIdToUse+'\',\''+widgetUriToUse+'\');return false;" >+ Add</a></div></div>';
				}
				//newHTMLForPreviews+='<div id="widgetPreview_blank'
				//newHTMLForPreviews+='" class="widgetPreview" style="display:block"><div class="previewStyle"></div></div>';
				newHTMLForList+='</div></div>';
				currListClick=0;
				
				//document.getElementById("subCanvasArea_list").innerHTML=newHTMLForPreviews+newHTMLForList;
				document.getElementById("subCanvasArea_list").innerHTML = newHTMLForList;

			},
            failure: function(o) {
				document.getElementById("subCanvasArea_list").innerHTML = "";
				YAHOO.log("Failure. Code:"+o.status + ", text:"+ o.statusText);
				alert("Unable to load widgets at this time. Please try again later.");
            }
        };

        this.getXML = YAHOO.util.Connect.asyncRequest("GET",
                "GetWidgetsFromCMS?type="+type+"&category="+category, 
                this.connectionCallback);
       };
}



// Since IE does not have indexOf
function arrayIndexOf(arr, element)
{
	var len = arr.length;

	for(var i=0;i<len;i++)
		if(arr[i] == element)
			return i;

	return -1;
}


// Finds val and removes it from the array
function removeByVal (array, val) {		

	var index = arrayIndexOf(array, val);
	if( index != -1)
		new_arr = remove(array, index);
	else 
		new_arr = array;

	return new_arr;
}

// Removes elements from the array. The new array is returned. 
function remove (array, from, to) {		
	var len = array.length;
	var new_arr = [];
	var new_to; 
	if( ! to )
		new_to = from;
	else
		new_to = to;

	var index = 0;

	for(var i=0; i<len; i++)
	{
		if(i < from || i > new_to)
		{
			new_arr[index] = array[i];
			index ++;
		}
	}

	return new_arr;
}

// Find a widget in the widget list based on its ID.
function findWidgetIndex(id)
{
	var len = widgetList.length;

	for(var i=0;i<len;i++)
	{	
		if(widgetList[i].widget_instance_id == id)
			return i;
	}

	return -1;
}

function getAddFavoritesHref(instanceID) 
{
	return "<a href='#' onclick=\"javascript:addWidgetToFavorites('"+instanceID+"'); return false;\">+ Add to Favorites&nbsp;</a>";
}



function addWidgetToFavorites(instanceID)
{
	if ( widgetsValidateLogIn() == false ) 
		return;

	var index = parseInt( findWidgetIndex( instanceID ) );

	widgetList[index].widget_position_favorites = 1;

	YAHOO.CLWRWidget.Favorites.addWidget( instanceID );
}


function getAddFavoritesLink( widgetIndex )
{
	if( widgetList[widgetIndex].widget_position_favorites == -1) {
		return "<div id='addToFavorites_"+widgetList[widgetIndex].widget_instance_id+"' class='widgetFooterLeft'>" + getAddFavoritesHref(widgetList[widgetIndex].widget_instance_id) + "&nbsp;</div>";
	} else {
		//return "<div id='addToFavorites_"+widgetList[widgetIndex].widget_instance_id+"' class='widgetFooterLeft'>+ Add to Favorites&nbsp;</div>";
		return "<div id='addToFavorites_"+widgetList[widgetIndex].widget_instance_id+"' class='widgetFooterLeft'></div>";
	}
}

function getPlayerIFrame(widgetItem) {
	return "<iframe id='iframe"+widgetItem.widget_instance_id+"' src='"+widgetItem.widget_iframe_src+"' class='container' frameborder='0' scrolling='no'></iframe>";
}

// Sets the player's HTML to the innerHTML of a Widget Holder. 
function setPlayerDivHTML(widgetIndex, instanceID, state)
{
	var widgetItem = widgetList[widgetIndex]; 

	var playersHTML = "";
	playersHTML = playersHTML + "<div id='p"+instanceID+"' class='player'";
	if( state == ROW_STATE_COLLAPSED )
		playersHTML = playersHTML + " style='display:none' "; 
	playersHTML = playersHTML + ">";
	//playersHTML = playersHTML + "<div class='widgetLinksFooter'><div id='h" + widgetIndex +"' class='handle'>Move</div>";
	//playersHTML = playersHTML + "<div style='position:absolute;right:0px;'>" + getAddFavoritesLink(widgetIndex) + " | <a href='#' onclick=\"javascript:removeWidget('"+widgetItem.widget_instance_id+"', true); return false;\" >Delete</a></div></div>";

	playersHTML = playersHTML + "<div class='widgetLinksFooter'>" + getAddFavoritesLink(widgetIndex) ;
	playersHTML = playersHTML + "<div class='widgetFooterRight'><div id='h" + widgetIndex +"' class='handle'>Move&nbsp;</div> | <a href='#' onclick=\"javascript:removeWidget('"+widgetItem.widget_instance_id+"', true); return false;\" >&nbsp;Delete</a></div></div>";

	if( state == ROW_STATE_EXPANDED ) {
		playersHTML = playersHTML + getPlayerIFrame(widgetItem);
	}
	playersHTML = playersHTML + "</div>";
	
	var widgetHolderId = getEmptyHolder();

	var playerSlotDiv = document.getElementById(widgetHolderId);

	playerSlotDiv.innerHTML = playersHTML;
	playerSlotDiv.style.display = 'block';

	widgetHolders[widgetIndex] = widgetHolderId;
}

// Find an empty widget holder, to which a player can be added. 
function getEmptyHolder()
{
	for(var i=0;i<rows*cols;i++)
	{
		// If the widget holder id is not found in the widgetHolders list, that widget holder is usable
		var pos = arrayIndexOf(widgetHolders, "widgetHolder_"+i);

		if(pos == -1)
			return "widgetHolder_"+i;
	}
	
	// all holders are full
	return null;
}

// Toggles the busy image in a widget slot . 
function toggleWidgetSlotBusy(r,c,isBusy)
{
	widgetAddIsBusy = isBusy;

	var index = r*parseInt(cols)+c;
	var slotDiv = document.getElementById(slots[index].id);
	if(!slots[index].player)
	{
		if( isBusy )
		{
			slotDiv.innerHTML='<img alt="" border="0" src="'+ cdnUrl +'images/widgets/ajax-loader.gif" style="position:absolute; left:135px; top:100px" />';
			slotDiv.style.background = 'url('+cdnUrl+'images/widgets/blank_widget.jpg)';
			slotDiv.style.backgroundRepeat = 'no-repeat';
		}
		else
		{
			slotDiv.style.background = '';
			slotDiv.innerHTML = returnEmptyWidget(index);
		}

	}
}

// Add the empty widget slots.
function addEmptyWidgetSlots()
{
	for(var r=0;r<rows;r++)
		for (var c=0;c<cols ;c++ )
		{
			var index = r*parseInt(cols);
			index += c;
			var slotDiv = document.getElementById(slots[index].id);
			YAHOO.log("addEmptyWidgetSlots:slot player:"+slots[r*cols+c].player, "info", "CLWRWidget");
			if(!slots[r*cols+c].player)
			{
				//alert("Adding empty slot:"+r+","+c);
				slotDiv.innerHTML = returnEmptyWidget(r*cols+c);
				YAHOO.log("  addEmptyWidgetSlots:" + r+","+c+":empty", "info", "CLWRWidget");
			}
			else
			{
				slotDiv.innerHTML = "";
				YAHOO.log("  addEmptyWidgetSlots:" + r+","+c+":full", "info", "CLWRWidget");
			}
		}

}

function setPlayersToSlots(widgetIndex, instanceID)
{
	var r = widgetList[widgetIndex].row;
	var c = widgetList[widgetIndex].col;

	widgetList[widgetIndex].player = 	new YAHOO.CLWRWidget.DDPlayer("p"+instanceID);

	// Align the widget position to its slot's position. 
	YAHOO.util.Dom.setXY("p"+instanceID, YAHOO.util.Dom.getXY(slots[r*cols+c].id) );

	var slotIndex = r*cols + c;

	widgetList[widgetIndex].player.slot = slots[slotIndex];
	slots[slotIndex].player = widgetList[widgetIndex].player;
	//players[i].slot.player = players[i];
	widgetList[widgetIndex].player.setHandleElId("h"+widgetIndex);
}

// Clear out the HTML for a player. 
function clearPlayerDivHTML(widgetHolderId)
{
	var widgetHolderDiv = document.getElementById(widgetHolderId);
	
	widgetHolderDiv.style.display = "none";
	widgetHolderDiv.innerHTML = "";
}

// Remove a widget from the canvas. 
// The boolean bSendUpdate determines whether the widget is removed from the backend as well. 
// bSendUpdate will be false when whole rows are deleted. When widgets are removed individually, bSendUpdate will be true.
function removeWidget(widgetInstanceId, bSendUpdate){
	
	if ( widgetsValidateLogIn() == false ) 
		return;

	var confirmed; 
	if( bSendUpdate )
		confirmed = confirm("Are you sure you wish to delete this widget?");
	else
		confirmed = true;
	if (confirmed){
		var index = parseInt(findWidgetIndex(widgetInstanceId));
		var row, col;
		
		row = parseInt(widgetList[index].row);
		col = parseInt(widgetList[index].col);

		var iframe = document.getElementById("iframe"+widgetInstanceId);
		if( iframe != null )
			iframe.parentNode.removeChild(iframe);

		clearPlayerDivHTML(widgetHolders[index]);

		widgetList = remove(widgetList,index);
		
		widgetHolders = remove(widgetHolders,index); // TODO: Why is this necessary?

		slots[row*cols+col].player = null;

		widgetCount --; 

		addEmptyWidgetSlots();

		updateWidgetMatrix();

		removedInstanceIDs[removedInstanceIDs.length] = widgetInstanceId;
		
		// Save the canvas to User Profile
		if(bSendUpdate)
			saveCanvas(); 
	}
}


function addToFavorites()
{	
	// TODO. 
	alert("Not yet implemented. No mantis ticket please.");
	return false;
}

function generateSaveWidgetsXMLRequest(deletedRow)
{
	var positionArray = [];

	// Initiate the position array. Add an extra row when saving to the user profile. 
	positionArray.length = (rows+1)*cols;

	// Update the position array with the widgets. 
	for(var i=0;i<widgetCount; i++)
	{
		var position = (parseInt(widgetList[i].row)*cols)+ parseInt(widgetList[i].col);
		positionArray[position] = widgetList[i];
	}

	// Initiate the XML
	var xml = '<?xml version="1.0" encoding="utf-8" ?>\n';

	xml += '<WidgetCanvas>';
	xml += '<Section>' + sectionID + '</Section>';	
	xml += '<WidgetList>';
	
	if( deletedRow != undefined ) {
		xml += '<DeletedRowList>';
		xml += '<DeletedRow>'+ deletedRow + '</DeletedRow>';
		xml += '</DeletedRowList>';
	}

	for( var i=0; i< removedInstanceIDs.length; i++){

		xml += '<Widget>';
		xml += '<WidgetID>X</WidgetID>';
		xml += '<InstanceID>' + removedInstanceIDs[i] + '</InstanceID>';
		xml += '<Position>X</Position>';
		xml += '</Widget>';
	}

	for( var i=0; i< widgetCount; i++) {
		var position = (parseInt(widgetList[i].row)*cols)+ parseInt(widgetList[i].col);

		xml += '<Widget>';
		xml += '<WidgetID>' + widgetList[i].widget_id + '</WidgetID>';
		xml += '<InstanceID>' + widgetList[i].widget_instance_id + '</InstanceID>';
		xml += '<Position>' + position + '</Position>';
		xml += '</Widget>';
	}
	xml += '</WidgetList></WidgetCanvas>';

	return xml;

}

// Save current canvas	
function saveCanvas(deletedRow)
{
	// Indicate that the widget canvas is out of sync with the backend. 
	syncState = false;

	YAHOO.example.Local_XML = new function() {
		var xml = generateSaveWidgetsXMLRequest(deletedRow);
        this.connectionCallback = {
		            success: function(o) {
				xmlDoc = o.responseXML.documentElement; 
				// Remove the successfully deleted instance IDs
				instanceIDs = xmlDoc.getElementsByTagName("InstanceID");
				len = instanceIDs.length;
				for(j=0; j< len; j++)
				{
					removedInstanceIDs = removeByVal(removedInstanceIDs, instanceIDs[j].childNodes[0].nodeValue);
				}
            },
            failure: function(o) {
				// Dont do anything for now. Sync state is false, we'll try again when the DOM unloads. 
            }
        };

        this.getXML = YAHOO.util.Connect.asyncRequest("POST",
                "SaveCanvas",
                this.connectionCallback,
				xml);
    };
}

// Update the widget list based on players and slots.
function updateWidgetMatrix()
{
	// Get current widget placement matrix.
	for( var i=0;i<widgetCount;i++)
	{
		if(widgetList[i].player.slot)
		{
			widgetList[i].row = widgetList[i].player.slot.row;
			widgetList[i].col = widgetList[i].player.slot.col;
		}
	}
}

function resetWidgetXY()
{
	for (var i=0;i<widgetCount;i++)
	{
		// Align the widget position to its slot's position. 
		if( YAHOO.util.Dom.getXY(widgetList[i].player.slot.id) != YAHOO.util.Dom.getXY(widgetList[i].player.id))
			YAHOO.util.Dom.setXY(widgetList[i].player.id, YAHOO.util.Dom.getXY(widgetList[i].player.slot.id) );

		if( YAHOO.util.Dom.getStyle("wcHolder_"+rowIDs[widgetList[i].row], "display") != YAHOO.util.Dom.getStyle(widgetList[i].player.id, "display") )
		{
			YAHOO.util.Dom.setStyle(widgetList[i].player.id, "display", YAHOO.util.Dom.getStyle("wcHolder_"+rowIDs[widgetList[i].row], "display"));
		}
	}
}

function createNewRow()
{
	if ( widgetsValidateLogIn() == false ) 
		return;

	createNewRowHTML(ROW_STATE_EXPANDED);
	
	var r = rows - 1;
	for (var c=0;c<cols;c++)
	{
		widgetSlotId='slot_'+(lastRowID*cols+c);
		slots[r*cols+c] = new YAHOO.util.DDTarget(widgetSlotId);
		slots[r*cols+c].row = r;
		slots[r*cols+c].col = c;
		slots[r*cols+c].id = widgetSlotId;

	}
	addEmptyWidgetSlots();
	
	if( rows >= MAX_WIDGET_ROWS) {
		document.getElementById("widgetsAddMoreAnchor").style.display = "none";
	}
}

function unloadWidgetsFromRow(row) {
	for(var i=widgetCount-1; i>=0; i--) {
		if( widgetList[i].row == row ) {
			var iframe = document.getElementById("iframe"+widgetList[i].widget_instance_id);
									
			iframe.parentNode.removeChild(iframe);
			
			document.getElementById(widgetHolders[i]).style.display = "none";
		}
	}
}

// Collapse a row if number of expanded rows are more than the max. 
function collapseExtraRow(rowToExpand) {
	var expandedRowCount = 0; 
	
	// The farthest row will be collapsed. 
	var farthestRowID = -1; 
	var farthestRow = -1; 
	var longestRowDistance = -1; 

	for(var i=0; i<rows; i++) {
		if( getRowState(i) == ROW_STATE_EXPANDED ) {
			expandedRowCount++;
			if( Math.abs(rowToExpand-i) > longestRowDistance ) {
				longestRowDistance = Math.abs(rowToExpand-i);
				farthestRowID = rowIDs[i]; 
				farthestRow = i;
			}
		}
	}

	if(expandedRowCount >= MAX_EXPANDED_WIDGET_ROWS) {
		unloadWidgetsFromRow(farthestRow); 
		document.getElementById("wcHolder_"+farthestRowID).style.display = "none";
		toggleRowText(document.getElementById("wcHolder_"+farthestRowID+"_a"));
		resetWidgetXY();
	}
}

function collapseExpandRow(rowID, elementID, bSave)
{
	var rowState;
	if(moving[elementID])
		return;
	
	var row = arrayIndexOf(rowIDs, rowID); 
	if( document.getElementById(elementID).style.display != "none" ) {
		//Unload widgets from DOM as they collapse
		unloadWidgetsFromRow(row);
		rowState = ROW_STATE_COLLAPSED;
	} else {
		// Collapse other rows if number of expanded rows are more than the max. 
		collapseExtraRow(row);

		// Reload widgets into DOM
		for(var i=widgetCount-1; i>=0; i--) {
			if( widgetList[i].row == row ) {

				document.getElementById(widgetHolders[i]).style.display = "block";

				var p = document.getElementById("p"+widgetList[i].widget_instance_id);
				
				if( p.childNodes.length < 2) {
					var iframeHTML = getPlayerIFrame(widgetList[i]);
					p.innerHTML += iframeHTML;
				}
			}
		}
		rowState = ROW_STATE_EXPANDED;
	}
	
	if( bSave )
		saveRow(rowID,rowState);
	toggleSlide(elementID);
	toggleRowText(document.getElementById(elementID+"_a"));
}

function asyncLoadRows()
{
	YAHOO.example.Local_XML = new function() {
        this.connectionCallback = {
			success: function(o) {
				var xmlDoc = o.responseXML.documentElement;
				var rows=xmlDoc.getElementsByTagName("Row");	
				for(var i=0;i<rows.length;i++){
					var rowNumber = parseInt(rows[i].getElementsByTagName("RowNumber")[0].childNodes[0].nodeValue);
					var rowName = "";
					var rowState = 1;
					if( rows[i].getElementsByTagName("Name")[0] )
						rowName = rows[i].getElementsByTagName("Name")[0].childNodes[0].nodeValue;

					if( rows[i].getElementsByTagName("RowState")[0] )
						rowState = rows[i].getElementsByTagName("RowState")[0].childNodes[0].nodeValue;
					
					var el = document.getElementById("nameLink_"+(rowNumber));
					if( el && rowName != "" ) {
						el.innerHTML = unescapeHTML(rowName);
					}
					YAHOO.log("Row State:"+ rowState);
					

					// Collapse/Expand a row. 
					rowStates[i] = rowState;
					if( (getRowState(rowNumber)!= -1) && (rowState != getRowState(rowNumber))  ) {
						YAHOO.log("Collapsing/Expanding Row:"+rowState+","+getRowState(rowNumber));
						collapseExpandRow(rowIDs[rowNumber], 'wcHolder_'+rowIDs[rowNumber], false);
					}

				}
            },
            failure: function(o) {
	        }
        };

        this.getXML = YAHOO.util.Connect.asyncRequest("POST",
                "GetRows",
                this.connectionCallback,
				"Section="+sectionID);
    };
}

function toggleWidgetHelp(){
	if( document.getElementById("widgetHelpDropdown").style.display == "none" ){
		YAHOO.CLWRWidget.Favorites.showElement('widgetHelpDropdown');
		YAHOO.CLWRWidget.Favorites.hideElement('widgetHelpLink');
	} else {
		YAHOO.CLWRWidget.Favorites.hideElement('widgetHelpDropdown');
		YAHOO.CLWRWidget.Favorites.showElement('widgetHelpLink');
	}
}



function getRowState(row) {
	if( document.getElementById('wcHolder_'+rowIDs[row]) == null) 
		return -1;
	else if( document.getElementById('wcHolder_'+rowIDs[row]).style.display == "none") 
		return ROW_STATE_COLLAPSED;
	else
		return ROW_STATE_EXPANDED;
}