/**
* @author	André Dietisheim (dietisheim@sphere.ch)
* @version 3, 2005-05-23 (created on 2002-04-22)
* Copyright (c) 2001-2005 André Dietisheim
*/

function Xmenu( sNavigationName, sNavigation, globals, styles, nodesList )
{
	if( !Xmenu.prototype.instances ) Xmenu.prototype.instances = new Array();
	Xmenu.prototype.instances[ Xmenu.prototype.instances.length ] = this; // store this instance in static Array

	this.index = Xmenu.prototype.instances.length - 1;

	this.sNavigationName = sNavigationName;
	this.sNavigation = sNavigation;
	this.iType = globals[ 0 ];
	this.iCloseDelay = globals[ 1 ] * 1000;
	this.bClick = globals[ 2 ];
	this.bMenuBelow = globals[ 3 ];
	this.bLeftAlign = globals[ 4 ];
	this.bKeepExpansionState = globals[ 5 ];
	this.bHighlightClickedNodes = globals[ 6 ];
	this.sSpacerUrl = globals[ 8 ];
	this.styles = styles;
	this.nodesList = nodesList;

	this.iNodesIndex = 0;
	this.nodesTree = null;
	this.overNode = null;
	this.outNode = null;
	this.lastNode = null;
	this.iAbsY = 0;
	this.timeout = null;
	this.bOpened = false;
	iParentLayerWidth = ( is.iemac5up )? 0 : globals[ 7 ][ 0 ]; // XparentLayer disturbs Xlayer-events on iemac5
	iParentLayerHeight = ( is.iemac5up )? 0 : globals[ 7 ][ 1 ];
	this.xlayerParent = new XlayerParent( "XlayerParent" + this.index, this.sSpacerUrl, null, iParentLayerWidth, iParentLayerHeight, null );

	this.nodesTree = this.buildTree( false, "nodesTree", 0, null, null );

	this.nodeFound = null;
	this.navigationNode = null;
	if ( this.findNode( this.sNavigation, this.nodesTree ) )
	{ // node indicated in request found
		this.navigationNode = eval( "this." + this.nodeFound );
	}
}

Xmenu.prototype.VERTICAL = 0;
Xmenu.prototype.HORIZONTAL = 1;
Xmenu.prototype.COLLAPSING = 2;

Xmenu.prototype.buildTree = function( bSibling, sPath, parentNode, predecessor )
{	
		var node = this.nodesList[ this.iNodesIndex++ ];
		node.sPath = sPath;
		node.parentNode = parentNode;
//		node.setStyle( this.styles[ node.iLevel ] );	//-
		node.setStyle( this.styles[ node.iStyle ] );	//+
		this.setNodePos( node, bSibling, predecessor );

		if ( this.iNodesIndex < this.nodesList.length && node.iLevel < this.nodesList[ this.iNodesIndex ].iLevel )
		{ // child
			node.child = this.buildTree( false, node.sPath + ".child", node, node );
		}
		if ( this.iNodesIndex < this.nodesList.length && node.iLevel == this.nodesList[ this.iNodesIndex ].iLevel )
		{ // sibling
			node.sibling = this.buildTree( true, node.sPath + ".sibling", parentNode, node );
		}

		node.instantiateXlayer( 
			this.xlayerParent, 
			[ 	Xlayer.prototype.MOUSEOVER, "Xmenu.prototype.instances[" + this.index + "].onmouseover( Xmenu.prototype.instances[" + this.index + "]." + node.sPath + ")",
				Xlayer.prototype.MOUSEOUT, "Xmenu.prototype.instances[" + this.index + "].onmouseout( Xmenu.prototype.instances[" + this.index + "]." + node.sPath + ")",
				Xlayer.prototype.CLICK, "Xmenu.prototype.instances[" + this.index + "].onclick( Xmenu.prototype.instances[" + this.index + "]." + node.sPath + ")" 
			],
			this.sSpacerUrl 
		);

		return node;
}

Xmenu.prototype.setNodePos = function( node, bSibling, predecessor )
{
	var iLevel = node.iLevel;
	var style = node.style;	
	if ( predecessor )
	{
		iX = predecessor.iX;
		iY = predecessor.iY;
		iH = predecessor.iH;
		iW = predecessor.iW;
		iOffsetX = predecessor.iOffsetX || 0;
		iOffsetY = predecessor.iOffsetY || 0;
	}
	else 
	{
		iX = 0;
		iY = 0;
		iH = 0;
		iW = 0;
		iOffsetX = 0;
		iOffsetY = 0;
	}
	
		if ( this.iType == this.VERTICAL )
		{
			if ( !bSibling )
			{ // child or node 1 of menu below
				if ( this.bMenuBelow && node.iLevel == 1 )
				{
					node.iX = iX + node.iOffsetX;
					node.iY = iY + iH + node.iOffsetY;
				}
				else
				{
					node.iX = iX + iW + node.iOffsetX;
					node.iY = iY + node.iOffsetY;
				}
			}
			else
			{ // sibling
				node.iX = iX;
				node.iY = iY + iH;
			}
		}
		else if ( this.iType == this.HORIZONTAL )
		{
			if ( !bSibling )
			{ // child or node 1 of menu below
				if ( this.bMenuBelow && node.iLevel == 1 )
				{
					node.iX = iX + node.iOffsetX;
					node.iY = iY + iH + node.iOffsetY;
				}
				else
				{
					node.iX = iX + node.iOffsetX;
					node.iY = iY + iH + node.iOffsetY;
				}
			}
			else
			{ // sibling
				node.iX = iX + iW;
				node.iY = iY;
			}
		}
		else if ( this.iType == this.COLLAPSING )
		{
			if ( !bSibling )
			{ // child
				node.iX = iX + node.iOffsetX;
				node.iY = iY + iH + node.iOffsetY;
			}
			else
			{ // sibling
				node.iX = iX;
			}
		}
}

Xmenu.prototype.create = function()
{
	this.createXlayers( null );
	this.setVisibSiblings( this.nodesTree, true );
	if ( this.iType == this.COLLAPSING )
		this.setCollapseYPos( this.nodesTree );
}

Xmenu.prototype.createXlayers = function( tree )
{
	if ( !tree ) 
	{ // call without param -> take root node
		tree = this.nodesTree;
	}
	if ( tree.child )
		this.createXlayers( tree.child );
	if ( tree.sibling )
		 this.createXlayers( tree.sibling );

	tree.createXlayer();
}

Xmenu.prototype.setOpenListener = function( openListener )
{
	this.openListener = openListener;
}

Xmenu.prototype.setCloseListener = function( closeListener )
{
	this.closeListener = closeListener;
}

Xmenu.prototype.setLinkClickListener = function( linkClickListener )
{
	this.linkClickListener = linkClickListener;
}

Xmenu.prototype.open = function()
{	
	if ( this.navigationNode != null )
		this.openLastClicked();
	else
		this.setVisibSiblings( this.nodesTree, true );
	this.bOpened = true;
	this.openListener.onMenuOpen( this );
}

Xmenu.prototype.openLastClicked = function()
{
	node = this.navigationNode;
	this.lastNode = node;
	this.outNode = node;

	if ( node.child )
		this.setVisibSiblings( node.child, true );

	while ( node )
	{
		this.highlightClicked( node );
		if ( node.parentNode )
		{
			this.setVisibSiblings( node.parentNode.child, true );
			node = node.parentNode;
		}
		else
		{
			this.setVisibSiblings( this.nodesTree, true );
			node = null;
		}
	}
	if ( this.iType == this.COLLAPSING )
		this.setCollapseYPos( this.nodesTree );
}

Xmenu.prototype.findNode = function( sText, node )
{
	if ( this.nodeFound )
		return true;

	if ( node.child )
		this.findNode( sText, node.child );

	if ( node.sibling )
		this.findNode( sText, node.sibling );

	if ( sText == node.sText )
		this.nodeFound = node.sPath;

	return this.nodeFound;
}

Xmenu.prototype.close = function()
{
	if ( this.bOpened && !this.bKeepExpansionState )
	{
		this.setVisibChildren( this.nodesTree, false );
		this.setVisibSiblings( this.nodesTree, true );
		if ( this.iType == this.COLLAPSING )
			this.setCollapseYPos( this.nodesTree );
		this.clearHighlightChildren( this.nodesTree );
		this.lastNode = null;

		this.bOpened = false;
		this.closeListener.onMenuClose( this );
	}
}

Xmenu.prototype.onmouseover = function( node )
{
	this.overNode = node;
	if ( ( this.iType == this.VERTICAL || this.iType == this.HORIZONTAL ) && !this.bClick )
	{
		if ( !this.bOpened )
		{ // this menu will open
			this.bOpened = true;
			this.openListener.onMenuOpen( this );
		}

		var outNode = ( this.outNode )? this.outNode : this.nodesTree;
		if ( outNode.iLevel > node.iLevel )
		{
			this.showBranch( node, this.outNode );
		}
		else if ( outNode.iLevel == node.iLevel )
		{
			this.setVisibSiblings( outNode.child, false );
		}
		this.setVisibSiblings( node.child, true );
		this.fadeSiblings( node.child );
	}
	if ( !node.isHighlightClicked() )
	{ // current node is not the node that was clicked (or its parents)
		node.highlight( true );
	}
	return false;
}

Xmenu.prototype.onmouseout = function( node )
{
	this.overNode = null;
	if ( !node.isHighlightClicked() )
			node.highlight( false );

	var timeout = this.timeout;
	if ( ( this.iType == this.VERTICAL || this.iType == this.HORIZONTAL ) && !this.bClick ) // close menu if no onmouseover until timeout
		this.timeout = setTimeout( "Xmenu.prototype.instances[" + this.index + "].checkOnmouseout()", this.iCloseDelay );

	this.outNode = node;
	clearTimeout( timeout );
	return false;
}

Xmenu.prototype.checkOnmouseout = function()
{
	if ( this.overNode == null && !( this.bKeepExpansionState && this.bClick ) )
	{ // onmouseover executed since delay?
		this.close();
	}
}

Xmenu.prototype.onclick = function( node )
{	
	if ( node.target )
	{ // follow href
		node.target.open( node.sText, this.sNavigationName, this.sNavigation );
		this.sNavigation = node.sText;
		this.navigationNode = node; // store navigation node
		this.clearHighlightChildren( this.nodesTree );
		//this.linkClickListener.onLinkClick( this ); // inform controller
	}
	else if (
		( ( this.iType == this.VERTICAL || this.iType == this.HORIZONTAL ) && this.bClick ) || 
		this.iType == this.COLLAPSING )
	{
		node.highlight( true );
		if ( !this.bOpened )
		{ // this menu will open
			this.bOpened = true;
			this.openListener.onMenuOpen( this );
		}
			
		if ( this.iType == this.COLLAPSING )
		{
			this.collapse( node );
			this.fadeSiblings( node.child );
		}
		else if ( ( this.iType == this.VERTICAL || this.iType == this.HORIZONTAL ) && this.bClick )
		{
			this.showBranch( node, this.lastNode );
			this.fadeSiblings( node.child );
		}

		this.lastNode = node;
	}
	return false;
}

Xmenu.prototype.showBranch = function( node, hideNode )
{
	if ( this.bClick && node.child && node.child.xlayer.isVisible() )
	{ // reclose branch
		this.setVisibChildren( node.child, false );
		this.clearHighlightChildren( node, false );
	}
	else
	{
		if ( hideNode )
		{ // hide old nodes
			this.setVisibChildren( this.nodesTree, false );
			//this.clearHighlightChildren( this.nodesTree, false );
		}
		if ( node.child ) this.setVisibSiblings( node.child, true );
		while ( node )
		{ // show new nodes
			if ( this.bClick )
				this.highlightClicked( node, true );

			if ( node.parentNode )
			{
				this.setVisibSiblings( node.parentNode.child, true );
			}
			else
				this.setVisibSiblings( this.nodesTree, true );
			node = node.parentNode;
		}
	}
}

Xmenu.prototype.clearHighlightChildren = function( node )
{
	if ( node )
	{
		if	( node.child )
			 this.clearHighlightChildren( node.child );
		if ( node.sibling )
			 this.clearHighlightChildren( node.sibling );
		node.highlightClicked( false );
	}
}

Xmenu.prototype.collapse = function( node )
{
	this.showBranch( node, this.lastNode );
	this.setCollapseYPos( this.nodesTree );
}

Xmenu.prototype.setCollapseYPos = function( node )
{
	this.iAbsY = this.nodesTree.getY();
	this.setCollapsingNodesY( node );
}

Xmenu.prototype.setCollapsingNodesY = function( node )
{
	if ( node.isVisible() )
	{
		node.setPos( node.getX(), this.iAbsY );
		this.iAbsY += node.iH;
	}

	if ( node.child ) 
	{
		this.iAbsY += node.child.iOffsetY;
		this.setCollapsingNodesY( node.child );
		this.iAbsY -= node.child.iOffsetY;
	}
	if ( node.sibling ) 
		this.setCollapsingNodesY( node.sibling );
}

Xmenu.prototype.highlightClicked = function( node )
{
	if ( node && this.bHighlightClickedNodes )
	{
		node.highlightClicked( true );
	}
}

Xmenu.prototype.fadeSiblings = function( node )
{
	if ( node )
	{
		if ( node.sibling )
			this.fadeSiblings( node.sibling );
		node.xlayer.fade();
	}
}

Xmenu.prototype.setVisibSiblings = function( node, bVisibility )
{
	if ( node )
	{
		if ( node.sibling )
			 this.setVisibSiblings( node.sibling, bVisibility );
		node.setVisibility( bVisibility );
	}
}

Xmenu.prototype.setVisibChildren = function( node, bVisibility )
{
	if ( node )
	{
		if	( node.child )
			 this.setVisibChildren( node.child, bVisibility );
		if	( node.sibling )
			 this.setVisibChildren( node.sibling, bVisibility );
		node.setVisibility( bVisibility );
	}
}

Xmenu.prototype.isNavigationNodeFound = function()
{
	return this.navigationNode != null;
}
