/**
	Price Matrix Hover behaviour: 

	When the user hovers over cells in the matrix table, the selectedFlight style moves with the selection.
	Also the departure and return date of the corresponding hovered cells are highlighted.

	If the user doesn't move the mouse for one second or moves the cursor outside the table, the selection returns to the originally selected cell.

*/

/* Matrix table parameters */

//matrix table style
var tableStyle;

//cell that has the selected flight css style
var selectedFlightStyle;

/*********************** HEADERS ********************/
//return date cell - unselected cell style
var returnCellStyle; 
//return date cell - selected cell style
var returnCellSelStyle;
//departure date cell - unselected cell style
var departCellStyle;
//departure date cell - selected cell style
var departCellSelStyle;


/***********MATRIX CELLS ***********/
var priceStyle;
var priceLowStyle;
var priceNAStyle;

//headers for departure and return dates
var rowHeaders;
var colHeaders;

//local variables 
var matrixTable;
var nbRows;
var nbCells;

var selectedCell;						// currently selected cell
var coordsSelectedCell = new Array();	// coordinates of the currently selected cell
var hoveredCell;						// currently hovered cell

var highSelectedFlight = 1;				//flag that indicates whether the selected flight is highlighted

var timerMove = 0;						//timer used for highlighting the selected flight when there is no mouse move for a period of time
var period = 1000;						//period of milliseconds for the timer




/**
	Find the coordinates of a cell in the matrixTable table as an array of two elements [row, col] 
*/
function getCoords(crtCell){
  if (crtCell){
	  for (i=0; i<nbRows; i++){
	   for (n=0; n<nbCells; n++){
		 if (matrixTable.rows[i].cells[n] == crtCell){
			 return [i, n];
		 }
	   }
	  }
  }
}

/** 
	Check if any of the nodes in the subtree of the given element has the specified CSS class.
*/
function childWithStyle(element, style){  
   if (element && element.hasChildNodes && (element.childNodes.length > 0)) {
   	var i=0;
        for (i = 0; i < element.childNodes.length; i++) {
            if (hasClass(element.childNodes[i], style)){
                return element.childNodes[i];
            }
            else {
                childStyle = childWithStyle(element.childNodes[i], style);
                if (childStyle && childStyle != 0) {
                    return childStyle;
                }
            }
        }
    }
    else {
        return 0;
    }
}  

/**
	Highlight/remove highlight from return date cell. 	
 */
function replaceReturnDateStyle(row, col, currentStyle, newStyle){	
	// get the return date cell and change its style
	retDate = matrixTable.rows[rowHeaders].cells[col];		
	replaceClass(retDate, currentStyle, newStyle);
}


/**
	Highlight/remove highlight from departure date cell.
*/
function replaceDepartDateStyle(row, col, currentStyle, newStyle){		
	// get the departure date cell and change its style 
	depDate = matrixTable.rows[row].cells[colHeaders];
	replaceClass(depDate, currentStyle, newStyle);     
}


/**
	Highlight the cell, in case it supports highlighting.
*/
function cellHighlight(cell){	
	if (cell){
		if (hasClass(cell, priceStyle) ||
		    hasClass(cell, priceLowStyle) || 
			hasClass(cell, priceNAStyle)){
				addClass(cell, selectedFlightStyle);
		}
		hoveredCell = cell;		
	}
}

/** 
	Remove highlight from the previously selected cell.
*/
function cellNoHighlight(cell){
	if (cell){
		if (hasClass(cell, selectedFlightStyle)){
			removeClass(cell, selectedFlightStyle);
		}	
	   	hoveredCell = 0;
   }
}

/** 
	Remove previous selection (if any).
*/
function removeSel(){
	// if there's already a selected cell, remove selection
	if (selectedCell){
		removeClass(selectedCell, selectedFlightStyle);
		hoveredCell = 0;		
		highSelectedFlight = 0;
	}
	// remove previously selected return date
	if (coordsSelectedCell[1] || (coordsSelectedCell[1]==0)){
		replaceReturnDateStyle(coordsSelectedCell[0], coordsSelectedCell[1], returnCellSelStyle, returnCellStyle);
	}	
	
	// remove previously selected departure date 
	if (coordsSelectedCell[0] || (coordsSelectedCell[0]==0)){
		replaceDepartDateStyle(coordsSelectedCell[0], coordsSelectedCell[1], departCellSelStyle, departCellStyle);
	}		
}

/** 
	The selection (highlighting) returns to the cell that was initially selected.
*/
function returnSel(){
	var coordsHovered;
    //remove selection from hovered cell, if any 
	if (hoveredCell && hoveredCell != 0){
		coordsHovered = getCoords(hoveredCell);
		cellNoHighlight(hoveredCell);
		if (coordsHovered){
			replaceReturnDateStyle(coordsHovered[0], coordsHovered[1], returnCellSelStyle, returnCellStyle);
			replaceDepartDateStyle(coordsHovered[0], coordsHovered[1], departCellSelStyle, departCellStyle);
		}
	}
	//if there originally was a selected cell, highlight it
	if (selectedCell){
		addClass(selectedCell, selectedFlightStyle);
		hoveredCell = selectedCell;
		highSelectedFlight = 1;
	}
	// highlight return dates if they were initially highlighted
	if (coordsSelectedCell[1] || (coordsSelectedCell[1]==0)){
		replaceReturnDateStyle(null, coordsSelectedCell[1], returnCellStyle, returnCellSelStyle);
	}
	// highlight departure dates if they were initially highlighted
	if (coordsSelectedCell[0] || (coordsSelectedCell[0]==0)){
		replaceDepartDateStyle(coordsSelectedCell[0], null, departCellStyle, departCellSelStyle);
	}
}

/**
	Highlight hovered cell, along with its corresponding header cells (departure and return dates).
*/
function mouseOver(cell){
	if (cell){
		a = getCoords(cell);		
		//if selected flight is highlighted, remove it
		if (highSelectedFlight!=0){	
			removeSel();
		}
		cellHighlight(cell);
		
		//don't highlight return dates if only one column
		if (!colHeaders || nbCells > (colHeaders + 2)){			
			replaceReturnDateStyle(a[0], a[1], returnCellStyle, returnCellSelStyle);
		}
		//don't highlight departure dates if only one row
		if (!rowHeaders || nbRows > (rowHeaders + 2)){
			replaceDepartDateStyle( a[0], a[1], departCellStyle, departCellSelStyle);
		}
	}
}

/**
	Remove highlight from the lastly hovered cell, as well as from its corresponding headers.
*/
function mouseOut(cell){
	if (cell){
		a = getCoords(cell);
        cellNoHighlight(cell);
        replaceReturnDateStyle(a[0], a[1], returnCellSelStyle, returnCellStyle);
        replaceDepartDateStyle(a[0], a[1], departCellSelStyle, departCellStyle);
    }
}

/**
	Map event handlers to matrix table cells.
*/ 
function mapTable(){  
	matrixTable.onmouseout = function() {
		returnSel();
	}
	matrixTable.onmousemove = function() {
	   clearTimeout(timerMove);
	   timerMove = setTimeout("returnSel()", period);
	}

	//cell events
	for (i=0; i<nbRows; i++){
		for (n=0; n<nbCells; n++){
			cell = matrixTable.rows[i].cells[n];
			if (!cell){ continue;}
		   
			//headers don't exist if they are different from 0 and !header is true 
			rowHeadExists = !(!rowHeaders && (rowHeaders!=0));
			colHeadExists = !(!colHeaders && (colHeaders!=0));
			
			// assign mouseover and mouseout events to common cells, while excluding assignment to headers
			if (((!rowHeadExists) || (rowHeadExists && (i>rowHeaders))) && ((!colHeadExists) || (colHeadExists && (n > colHeaders)))){
				cell.onmouseover = function(){                           
									mouseOver(this);
							    }
				cell.onmouseout = function(){
									mouseOut(this);
								}
			}
		}
	}
}


/** 
	Initialization method
*/
function loadHover(styles){
	tableStyle = styles.tableStyle;
	selectedFlightStyle = styles.selectedFlightStyle;
	returnCellStyle = styles.returnCellStyle;
	returnCellSelStyle = styles.returnCellSelStyle;
	departCellStyle = styles.departCellStyle;
	departCellSelStyle = styles.departCellSelStyle;
	priceStyle = styles.priceStyle;
	priceLowStyle = styles.priceLowStyle;
	priceNAStyle = styles.priceNAStyle;			
	
	// initialize variables
	matrixTable = document.getElementById(tableStyle);
	nbRows = matrixTable.rows.length;
	nbCells = matrixTable.rows[1].cells.length;	

	// get selected flight and its coordinates
	selectedCell = childWithStyle(matrixTable, selectedFlightStyle);

	if(selectedCell){
		coordsSelectedCell = getCoords(selectedCell);
	} 
	else {	// no cell is selected, but there are headers selected (ex. price matrix + 3 + 3)
		var headerSel;
		if (headerSel = childWithStyle(matrixTable, returnCellSelStyle)){
			coordsSelectedCell[1] = getCoords(headerSel)[1];
		}
		if (headerSel = childWithStyle(matrixTable, departCellSelStyle)){
			coordsSelectedCell[0] = getCoords(headerSel)[0];
		}
	}

	// find header of the return date
	var returnCell = childWithStyle(matrixTable, returnCellStyle);
	if (returnCell){
		rowHeaders = getCoords(returnCell)[0];
	}	

	// find column of the departure date
	var departCell = childWithStyle(matrixTable, departCellStyle);
	if (departCell){
		colHeaders = getCoords(departCell)[1];
	}

	// map events to the table
	mapTable();
}






