//   Copyright (C) 2006 Cognos Incorporated. All rights reserved.
//   Cognos (R) is a trademark of Cognos Incorporated.

function CSelectionRegionManager()
{
	this.m_selectionRegions = new Array();
}

CSelectionRegionManager.prototype.clearSelections = function()
{
	for(var i = this.m_selectionRegions.length-1; i >= 0; i--)
	{
		var selectionRegion = this.m_selectionRegions[i];
		if (selectionRegion instanceof CSelectionRegion && !selectionRegion.isCut())
		{
			selectionRegion.clearSelection();
		}
	}
}

CSelectionRegionManager.prototype.clearCutSelections = function()
{
	for(var i = this.m_selectionRegions.length-1; i >= 0; i--)
	{
		var selectionRegion = this.m_selectionRegions[i];
		if (selectionRegion instanceof CSelectionRegion && selectionRegion.isCut()) 
		{	
			selectionRegion.clearCutSelection();
		}
	}
}

CSelectionRegionManager.prototype.getSelectionRegion = function(selectionRegionKey)
{
	for(var i = this.m_selectionRegions.length-1; i >= 0; i--)
	{
		var selectionRegion = this.m_selectionRegions[i];
		if ((selectionRegion instanceof CSelectionRegion) && (selectionRegion.getKey() == selectionRegionKey))
		{
			return selectionRegion;
		}
		
	}
	
	return null;
}

CSelectionRegionManager.prototype.createSelectionRegion = function(selectionRegionKey, cellList)
{
	var selectionRegion = new CSelectionRegion(selectionRegionKey,cellList);
	this.m_selectionRegions.push(selectionRegion);
	
	return selectionRegion;
}

function CSelectionRegion(selectionRegionKey,cellList)
{
	this.m_key = selectionRegionKey;
	this.m_bVisible = false;
	this.m_secondarySelections = new Array();
	this.m_primarySelections = new Array();
	this.m_reportTable = document.getElementById("rt")	
	
	this.createRegions(cellList);	
}

CSelectionRegion.prototype.getKey = function()
{
	return this.m_key;
}

CSelectionRegion.prototype.findOrCreateSelectionDiv = function(left, top, right, bottom)
{	
	var selectionDiv;
	for(var i = this.m_secondarySelections.length-1; i >= 0; --i)
	{
		selectionDiv = this.m_secondarySelections[i];
		if(this.isAdjacentToDiv(selectionDiv, left, top, right, bottom)) 
			return selectionDiv;
	}

	selectionDiv = new CSelectionRegionDiv(this);
	
	this.m_secondarySelections.push(selectionDiv);
	
	return selectionDiv;

}

CSelectionRegion.prototype.isAdjacentToDiv = function(selectionDiv, left, top, right, bottom)
{
	if(typeof selectionDiv == "undefined" || selectionDiv == null)
		return false;
			
	// check to see if the coordinates are adjacent to the div
	var divLeft = selectionDiv.getLeft();
	var divRight = selectionDiv.getRight();
	var divTop = selectionDiv.getTop();
	var divBottom = selectionDiv.getBottom();				
	
	/* To determine is a cell is adjacent to or within a div region, we need to consider the following:
	
		The cell is adjacent to the div region
			1.	The cell's right/left coord is adjacent to or equal to the div regions left/right coord, 
				and the cells bottom/top is adjacent to the div regions top/bottom  (COVERED BY LINE 1 OF THE RETURN STATEMENT)
			2.	The cell's right/left coord is adjacent to the div regions left/right coord, 
				and the cell top/bottom coord is equal to the div regions top/bottom coord (COVERED BY LINE 2 OF THE RETURN STATEMENT)
	
		The cell is within the div region when
			1.	The cells left coord is greater or equal to the div region's left coord and
				the cell's right coord is less than or equal to the div region's right coord and
				the cell's top coord is greater than or equal to the div region's top coord and
				the cell's bottom coord is less than or equal to the div regions bottom coord (COVERED BY LINE 3 OF THE RETURN STATEMENT)
				
		TODO: Make this return statement more legible. 
	*/
	
	return ( ( ( (right+1)==divLeft || (left-1)==divRight || right == divLeft || left == divRight || right == divRight || left == divLeft ) && ( ((bottom+1)==divTop) || ((top-1)==divBottom) ) ) ||
			 ( (((right+1) == divLeft) || ((left-1) == divRight)) && ( top == divTop || bottom == divBottom) ) ||
			 ( left >= divLeft && right <= divRight && top >= divTop && bottom <= divBottom )			  
			);
}

CSelectionRegion.prototype.createRegions = function(cellList)
{	
	var selectionDiv = null;
			
	for(var i = cellList.length-1; i >= 0; --i)
	{	
		// determine the parent offsets
		var offsetLeft = 0;
		var offsetTop = 0;
			
		var currentParent = cellList[i].offsetParent;
		while(currentParent && currentParent != this.m_reportTable) 
		{
			offsetLeft += currentParent.offsetLeft;
			offsetTop += currentParent.offsetTop;
			currentParent = currentParent.offsetParent;
		}
			
		var left = offsetLeft + cellList[i].offsetLeft;
		var top = offsetTop + cellList[i].offsetTop;
		var right = left + cellList[i].clientWidth;
		var bottom = top + cellList[i].clientHeight;	
				
		var divLeft, divRight, divTop, divBottom;
			
		if(!this.isAdjacentToDiv(selectionDiv, left, top, right, bottom))
			selectionDiv = this.findOrCreateSelectionDiv(left, top, right, bottom);
				
		divLeft = selectionDiv.getLeft();
		divRight = selectionDiv.getRight();
		divTop = selectionDiv.getTop();
		divBottom = selectionDiv.getBottom();			
		
		// update the the div coords
		if(left < divLeft || divLeft == 0)
			selectionDiv.setLeft(left);
			
		if(top < divTop || divTop == 0)
			selectionDiv.setTop(top);
			
		if(right > divRight)
			divRight = right;
			
		selectionDiv.setWidth(divRight - selectionDiv.getLeft());
			
		if(bottom > divBottom)
			divBottom = bottom;	
			
		selectionDiv.setHeight(divBottom - selectionDiv.getTop());					
		
	}
}

CSelectionRegion.prototype.isVisible = function()
{
	return this.m_bVisible;
}

CSelectionRegion.prototype.clearSelection = function()
{
	this.clearPrimarySelections();
	this.hide();
}

CSelectionRegion.prototype.hide = function()
{
	this.m_bVisible = false;
	
	for(var i = this.m_secondarySelections.length-1; i >= 0; i--)
	{
		this.m_secondarySelections[i].hide();
	}
}

CSelectionRegion.prototype.show = function()
{	
	this.m_bVisible = true;
		
	for(var i = this.m_secondarySelections.length-1; i >= 0; i--)
	{
		this.m_secondarySelections[i].show();
	}
	
	// Draw primary selection for all selections in this list (we do this afterwards to override the secondary list)
	for (var i = this.m_primarySelections.length-1; i >= 0; i--)
	{
		var theTd = this.m_primarySelections[i];
		if (typeof theTd == "object" && theTd != null)
		{
			if (theTd.getAttribute("oldClassName") != null)
				theTd.className = theTd.getAttribute("oldClassName");
			else
				theTd.setAttribute("oldClassName", theTd.className);

			theTd.className += " primarySelection";
		}
	}			
	
}

CSelectionRegion.prototype.clearPrimarySelections = function()
{
	while(this.m_primarySelections.length)
	{
		var theTd = this.m_primarySelections.pop();
		if(typeof theTd != "undefined" && theTd != null && theTd.getAttribute("oldClassName") != null)
		{
			theTd.className = theTd.getAttribute("oldClassName");
			theTd.removeAttribute("oldClassName");
		}	
	}
}

CSelectionRegion.prototype.addPrimarySelection = function(cell)
{
	this.m_primarySelections.push(cell.getCellRef());
}

CSelectionRegion.prototype.setToCutSelection = function()
{
	this.m_bIsCut = true;
	this.clearPrimarySelections();
	
	for(var i = this.m_secondarySelections.length-1; i >= 0; i--)
	{
		this.m_secondarySelections[i].setToCutSelection();
	}
}

CSelectionRegion.prototype.isCut = function()
{
	return this.m_bIsCut;
}

CSelectionRegion.prototype.clearCutSelection = function()
{
	this.m_bIsCut = false;
	this.clearPrimarySelections();
	
	for(var i = this.m_secondarySelections.length-1; i >= 0; i--)
	{
		this.m_secondarySelections[i].clearCutSelection();
		this.m_secondarySelections[i].hide();
	}	
}

CSelectionRegion.prototype.getPrimarySelectedItem = function(e, eventHandler)
{
	var cellList = document.getElementsByName(this.getKey());
					
	// iterate through the cell list until we find a cell which matches the coords of the generated event
	for(var i = cellList.length-1; i >=0; i--)
	{
		var currentParent = cellList[i].offsetParent;

		var scrollLeft = 0;
		var scrollTop = 0;
			
		// determine the parent offsets
		var offsetLeft = 0;
		var offsetTop = 0;	
		
		while(currentParent) 
		{	
			scrollLeft += currentParent.scrollLeft;
			scrollTop += currentParent.scrollTop;
			
			offsetLeft += currentParent.offsetLeft;
			offsetTop += currentParent.offsetTop;
			
			currentParent = currentParent.offsetParent;
		}
		
		var xCoord = e.clientX + scrollLeft + document.body.offsetLeft;
		var yCoord = e.clientY + scrollTop + document.body.offsetTop;		
	
	
		var left = (offsetLeft + cellList[i].offsetLeft);
		var top = (offsetTop + cellList[i].offsetTop);
		var right = left + cellList[i].clientWidth;
		var bottom = top + cellList[i].clientHeight;
			
		if( (left <= xCoord && xCoord <= right) && (top <= yCoord && yCoord <= bottom) )
		{
			// if the cell has child span nodes, see if the event occurs within one of the span elements
			// if so, return the span element
			if(typeof eventHandler != "undefined")
			{		
				var spanElements = cellList[i].getElementsByTagName("span");
				for(var j = spanElements.length-1; j >= 0; j--)
				{
					if(!spanElements[j].getAttribute(eventHandler))
						continue;
						
					var spanLeft = left + spanElements[j].offsetLeft;
					var spanTop = top + spanElements[j].offsetTop;
					var spanRight = spanLeft + spanElements[j].offsetWidth;
					var spanBottom = spanTop + spanElements[j].offsetHeight;
					
					if( (spanLeft <= xCoord && xCoord <= spanRight) && (spanTop <= yCoord && yCoord <= spanBottom) )
						return spanElements[j];
				}
			}
			return cellList[i];
		}
	}
	
	return null;
}

CSelectionRegion.prototype.onClickEvent = function(e)
{
	//get the event in a cross-browser fashion
	e = (e) ? e : ((event) ? event : null);

	if(typeof this.selectionRegion != "undefined")
	{
		var node = this.selectionRegion.getPrimarySelectedItem(e, "onclick");
		
		if(node != null && typeof node.onclick != "undefined" && node.onclick != null)
		{
			var htmlDivRegion;
			if (document.all)
				htmlDivRegion = e.srcElement;
			else
				htmlDivRegion = e.originalTarget;
				
			htmlDivRegion.selectedCell = node;
				
			var onClickHandler = node.onclick;
			return onClickHandler(e);
		}	
	}
		
	return false;
}

CSelectionRegion.prototype.onDoubleClickEvent = function(e)
{
	//get the event in a cross-browser fashion
	e = (e) ? e : ((event) ? event : null);

	if(typeof this.selectionRegion != "undefined")
	{
		var node = this.selectionRegion.getPrimarySelectedItem(e, "ondblclick");
		
		if(node != null)
		{
			var htmlDivRegion;
			if (document.all)
				htmlDivRegion = e.srcElement;
			else
				htmlDivRegion = e.originalTarget;
				
			htmlDivRegion.selectedCell = node;
				
			return true;
		}	
	}
		
	return false;
}

CSelectionRegion.prototype.onContextMenuEvent = function(e)
{
	//get the event in a cross-browser fashion
	e = (e) ? e : ((event) ? event : null);

	if(typeof this.selectionRegion != "undefined")
	{
		var node = this.selectionRegion.getPrimarySelectedItem(e, "oncontextmenu");
		
		if(node != null && typeof node.oncontextmenu != "undefined" && node.oncontextmenu != null)
		{
			var htmlDivRegion;
			if (document.all)
				htmlDivRegion = e.srcElement;
			else
				htmlDivRegion = e.originalTarget;
				
			htmlDivRegion.selectedCell = node;
				
			var contextMenuHandler = node.oncontextmenu;
			return contextMenuHandler(e);
		}	
	}
		
	return false;
}

function CSelectionRegionDiv(selectionRegion)
{
	this.m_parentRegion = selectionRegion;
	this.m_left = 0;
	this.m_top = 0;
	this.m_width = 0;
	this.m_height = 0;
	this.m_bIsCut = false;
	
	this.m_htmlDiv = null;
}

CSelectionRegionDiv.prototype.getLeft = function()
{
	return this.m_left;
}

CSelectionRegionDiv.prototype.getRight = function()
{
	return (this.m_left + this.m_width);
}

CSelectionRegionDiv.prototype.getWidth = function()
{
	return this.m_width;
}

CSelectionRegionDiv.prototype.getTop = function()
{
	return this.m_top;
}

CSelectionRegionDiv.prototype.getBottom = function()
{
	return (this.m_top + this.m_height);
}

CSelectionRegionDiv.prototype.getHeight = function()
{
	return this.m_height;
}

CSelectionRegionDiv.prototype.setLeft = function(left)
{
	this.m_left = left;
}

CSelectionRegionDiv.prototype.setWidth = function(width)
{
	this.m_width = width;
}

CSelectionRegionDiv.prototype.setTop = function(top)
{
	this.m_top = top;
}

CSelectionRegionDiv.prototype.setHeight = function(height)
{
	this.m_height = height;
}

CSelectionRegionDiv.prototype.hide = function()
{
	if(this.m_htmlDiv != null)
	{
		this.m_htmlDiv.style.display = "none";
	}

}

CSelectionRegionDiv.prototype.show = function()
{
	if(this.m_htmlDiv != null)
	{
		this.m_htmlDiv.style.display = "block";
		// make sure the div class name is properly set
		this.m_htmlDiv.className = "secondarySelectionRegion";
	}
	else
	{
		var reportTable = document.getElementById("rt");
		if(reportTable == null)
			return;
			
		this.m_htmlDiv = document.createElement("div");
		this.m_htmlDiv.className = "secondarySelectionRegion";
		
		this.m_htmlDiv.selectionRegion = eval(this.m_parentRegion);
		this.m_htmlDiv.oncontextmenu = this.m_parentRegion.onContextMenuEvent;
		this.m_htmlDiv.onclick = this.m_parentRegion.onClickEvent;
		this.m_htmlDiv.ondblclick = this.m_parentRegion.onDoubleClickEvent;
				
		this.m_htmlDiv.style.left = this.getLeft();
		this.m_htmlDiv.style.width = this.getWidth()+1; // add 1 pixel to the width so the div region covers the right cell border
		this.m_htmlDiv.style.top = this.getTop();
		this.m_htmlDiv.style.height = this.getHeight()+1; // add 1 pixel to the height the div region covers the bottom cell border

		this.m_htmlDiv.innerHTML = '<img src="../common/images/spacer.gif"/>';
			
		reportTable.appendChild(this.m_htmlDiv);		
	}
}

CSelectionRegionDiv.prototype.setToCutSelection = function()
{
	if(this.m_htmlDiv == null)
		return;
		
	this.m_htmlDiv.className = "cutSelectionRegion";
}

CSelectionRegionDiv.prototype.clearCutSelection = function()
{
	if(this.m_htmlDiv == null)
		return;
	
	this.m_htmlDiv.className = "secondarySelectionRegion";
}
