function ListPreviewer(container, mouseLogger)
{
    this._Items = new Array();
    this._intervalId = null;
    this._current = null;
    this._container = container;
    this._mouseLogger = mouseLogger;
    this._IsStopped = false;
}

ListPreviewer.prototype = 
{
    AddItem:function(item)
    {
        if(this._Items.length >0)
        {
            this._Items[this._Items.length-1].Next = item;
            item.Next = this._Items[0];
        }
        else
            item.Next = item;
            
        this._Items.push(item);
    },
    
    ShowItem:function(id)
    {
        if(this._current)
            this._current.Hide();
        
        for(var i=0;i<this._Items.length;i++)
        {
            if(this._Items[i].ID == id)
            {
                this._current = this._Items[i];
                this._current.Display();
            }
            else
            {
                this._Items[i].Hide();
            }
        }
    },
    
    BeginCycling:function(delay)
    {
        if(this._intervalId != null)
            clearInterval(this._intervalId);
        var self = this; 
        this._intervalId = setInterval(function(){self._Cycle()}, delay);
    },
    
    _Cycle:function()
    {        
        if(this._Items.length==0 || this._CheckMouseOver())
            return; 
        
        //skip the iteration directly after it restarting
        if(this._IsStopped)
        {
            this._IsStopped = false;
            return;
        }
        
        if(this._current == null)
            this._current = this._Items[0];
        else
        {
            this._current.Hide();
            this._current = this._current.Next;
        } 
            
        this._current.Display();   
    },
    
    _CheckMouseOver:function()
    {
        try
        {
            if(this._mouseLogger.IsMouseInside(this._container))
            {
                this._IsStopped = true;
                return true;
            }
            else
            {
                return false;
            }
        }
        catch(e)
        {
            return true;
        }
    },
    
    LogMouseMove:function(e)
    {
        this._mouseLogger.LogMouseMove(e);
    }
}

function ListPreviewerItem(displayElement, id)
{
    this.Next = null;
    this._displayElement = displayElement;
    this.ID = id;
}

ListPreviewerItem.prototype = 
{
    
    Display:function()
    {
        this._displayElement.className = this._displayElement.className.replace(/infohidden/, 'infovisible');
    },
    
    Hide:function()
    {
        this._displayElement.className = this._displayElement.className.replace(/infovisible/, 'infohidden');
    }
}

function MouseLogger()
{
    this._lastMouseMoveX = null;
    this._lastMouseMoveY = null;
}
MouseLogger.prototype = 
{

    LogMouseMove:function(e)
    {
        this._lastMouseMoveX = this._GetX(e);
        this._lastMouseMoveY = this._GetY(e);
    },
    
    IsMouseInside:function(object)
    {
        // and check if inside div coordinates
	    var div_coords = getObjPosRelPage(object);
	    return ((this._lastMouseMoveX > div_coords[0]) && (this._lastMouseMoveY > div_coords[1]) && (this._lastMouseMoveX - div_coords[0] < object.offsetWidth) && (this._lastMouseMoveY - div_coords[1] < object.offsetHeight));
   
    },
    
    _GetX:function(evt)
    {
        if(evt.pageX)
            return evt.pageX;
        else if(evt.clientX)
            return evt.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
        else 
            return -1;
    },

    _GetY:function(evt)
    {
        if(evt.pageY)
            return evt.pageY;
        else if(evt.clientY)
            return evt.clientY + document.body.scrollTop + document.documentElement.scrollTop;
        else 
            return -1;
    }
}
 



/* function to obtain object's position relative to the page, in a browser independent way */
function getObjPosRelPage(passedObj) {

	var obj_x = 0;
	var	obj_y = 0;
	if (passedObj.offsetParent) {
		do {
			obj_x += passedObj.offsetLeft;
			obj_y += passedObj.offsetTop;
		} while (passedObj = passedObj.offsetParent);
	}
	
	// Only IE seems to get this right if the body is centered... FF and Safari need the extra margin body added...
	if (typeof window.innerWidth != 'undefined')
	{
		obj_x +=  (window.innerWidth - document.body.offsetWidth) / 2;	// to cope for body being centered via margin auto...
	}
 
	return [obj_x,obj_y];
}

// adds array of listPreviewers to the document object
function initListPrevierwersMouseListeners() {

	var divObjects = document.getElementsByTagName('DIV');

    var mouseLogger = new MouseLogger();
    var previewers = [];
	for (i = 0; i < divObjects.length; i++) {
		if (divObjects.item(i).className.indexOf('listPreviewerCont') >= 0) 
		{
		    var previewer = new ListPreviewer(divObjects.item(i), mouseLogger);
		    previewers[i] = previewer;			
			// and cycle throught the child listPreviewerItems setting the mouseover listeners
			var listPreviewerItemsSelectors = divObjects.item(i).getElementsByTagName('A');
			var max_previewer_height = 0;
			
			for (j = 0; j < listPreviewerItemsSelectors.length; j++) 
			{
				if (listPreviewerItemsSelectors.item(j).className.indexOf('listSelector') >= 0) 
				{
				    listPreviewerItemsSelectors.item(j).tag = "distinctElem" + j;
				    listPreviewerItemsSelectors.item(j).previewerIndex = "" + i;
				    previewer.AddItem(new ListPreviewerItem(listPreviewerItemsSelectors.item(j).parentNode,listPreviewerItemsSelectors.item(j).tag));
				        
				    AttachEvt(  listPreviewerItemsSelectors.item(j), 
				                "onmouseover",  
					            function(e)
					            {   
					                
					                var elem = e.srcElement;
					                if(!elem)
					                    elem = e.target;
					                    
					                for(var k=0;k<6 && (elem.className.indexOf('listSelector') <0);k++)
					                {
					                    elem = elem.parentNode;
					                }
					                previewers[elem.previewerIndex*1].ShowItem(elem.tag);
					            }
					);
					var siblingDivs = listPreviewerItemsSelectors.item(j).parentNode.getElementsByTagName('DIV');
					for (k = 0; k < siblingDivs.length; k++) {
						siblingDivObj = siblingDivs.item(k);
						if (siblingDivObj.className && (siblingDivObj.className.indexOf('itemInfo') >= 0)) {			
							// set visibility hidden and display block to get height, then return to original settings;
							if (siblingDivObj.parentNode.className.indexOf('infohidden') >= 0) {
								siblingDivObj.style.visibility = 'hidden';
								siblingDivObj.style.display = 'block';
								var item_height = siblingDivObj.offsetHeight;
								siblingDivObj.style.display = '';
								siblingDivObj.style.visibility = '';
							} else {
								var item_height = siblingDivObj.offsetHeight;
							}
							if (item_height > max_previewer_height) {
								max_previewer_height = item_height;
							}
						}
					}
				}
			}	
			
			divObjects.item(i).style.height = max_previewer_height + 'px';
			
			AttachEvt(document,"onmousemove", function(e){previewer.LogMouseMove(e);});
			previewer.BeginCycling(2000);	
		}
	}
}

function AttachEvt(object,evt, funct)
{
    var func = function(e)
    {
        if( typeof( e ) == "undefined" && typeof( window.event ) != "undefined" )
        e = window.event;
        funct(e);
    }
    if (typeof( window.addEventListener ) != "undefined" ) 
    {
        // Firefox way
        object.addEventListener(evt.replace("on",""), func, false);
    } 
    else 
    {
       // IE way
        object.attachEvent(evt, func);
    } 
}

