/**
* @author	André Dietisheim (dietisheim@sphere.ch)
* @version 2.5.2, 2004-02-10 (created on 2002-04-22)
* Copyright (c) 2001-2005 André Dietisheim
*/

function Xmenu( sNavigationName, sNavigation, globals, styles, contents )
{
	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.contents = contents;

	this.iContent = 0;
	this.tree = null;
	this.overNode = null;
	this.outNode = null;
	this.lastNode = null;
	this.absY = 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.tree = this.buildTree( 0, 0, false, null, "tree" );

	this.nodeFound = null;
	this.navigationNode = null;
	if ( this.findNode( this.sNavigation, this.tree ) )
	{ // 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( iAbsX, iAbsY, bSibling, sParent, sPath )
{	
		var node = this.buildNode( iAbsX, iAbsY, bSibling, sParent, sPath );
		this.iContent++;
		if ( this.iContent < this.contents.length && node.iLevel < this.contents[ this.iContent ][ 2 ] )
		{ // child
			node.child = this.buildTree(  node.absX, node.absY, false, "this." + node.sPath, node.sPath + ".child" );
		}
		if ( this.iContent < this.contents.length && node.iLevel == this.contents[ this.iContent ][ 2 ] )
		{ // sibling
			node.sibling = this.buildTree( node.absX, node.absY, true, node.sParent, node.sPath + ".sibling" );
		}
		node.xlayer = this.addXlayer( this.xlayerParent, node, this.styles )
		return node;
}

Xmenu.prototype.buildNode = function( iAbsX, iAbsY, bSibling, sParent, sPath )
{
	var node = new Object();
	node.child = null;
	node.sibling = null;
	node.sParent = sParent;
	node.sPath = sPath;

	node.sText = this.contents[ this.iContent ][ 0 ];
	node.target = this.contents[ this.iContent ][ 1 ];
	node.iLevel = this.contents[ this.iContent ][ 2 ];

	if ( this.iType == this.VERTICAL )
	{
		if ( !bSibling )
		{ // child
			if ( node.iLevel > 1 || ( node.iLevel == 1 && !this.bMenuBelow ) ) // menu below: level 2,3,... || menu right: 1, 2, ...
				node.absX = iAbsX + this.styles[ node.iLevel ][ 2 ] + this.styles[ node.iLevel + 1 ][ 0 ];
			else // menu below: level 0, 1 || menu right: level 0
				node.absX = iAbsX + this.styles[ node.iLevel + 1 ][ 0 ];

			if ( node.iLevel != 1 || ( node.iLevel == 1 && !this.bMenuBelow ) ) // level 0, 2, 3, ... : add yOffset
				node.absY = iAbsY + this.styles[ node.iLevel + 1 ][ 1 ];
			else // level 1: add height of last node + yOffset
				node.absY = iAbsY + this.styles[ node.iLevel + 1 ][ 1 ] + this.styles[ node.iLevel ][ 3 ];
		}
		else
		{ // sibling
			node.absX = iAbsX;
			node.absY = iAbsY + this.styles[ node.iLevel + 1 ][ 3 ];
		}
	}
	else if ( this.iType == this.HORIZONTAL )
	{
		if ( !bSibling )
		{ // child
			if ( node.iLevel > 1 || ( node.iLevel == 1 && !this.bMenuBelow ) ) {// menu below: level 2,3,... || menu right: 1, 2, ...
				node.absX = iAbsX + this.styles[ node.iLevel ][ 2 ] + this.styles[ node.iLevel + 1 ][ 0 ];
			} else {
				node.absX = iAbsX + this.styles[ node.iLevel + 1 ][ 0 ];
			}
			
			if ( node.iLevel != 1 || ( node.iLevel == 1 && !this.bMenuBelow ) ) {// level 0, 2, 3, ... : add yOffset
				node.absY = iAbsY + this.styles[ node.iLevel + 1 ][ 1 ];
			} else { // newzealandartpaintings + 1 added to get over border
				node.absY = iAbsY + this.styles[ node.iLevel ][ 3 ] +1;
			}
		}
		else
		{ // sibling
			if ( node.iLevel != 0 ) {
				node.absY = iAbsY + this.styles[ node.iLevel + 1 ][ 3 ];
				node.absX = iAbsX;

			}
			else {
				node.absY = iAbsY;
				node.absX = iAbsX + this.styles[ node.iLevel + 1 ][ 2 ];
			}
		}
	}
	else if ( this.iType == this.COLLAPSING )
	{
		if ( !bSibling )
		{ // child
			node.absX = iAbsX + this.styles[ node.iLevel + 1 ][ 0 ];
			node.absY = iAbsY + this.styles[ node.iLevel + 1 ][ 1 ];
		}
		else
		{ // sibling
			node.absX = iAbsX;
			node.absY = iAbsY + this.styles[ node.iLevel + 1 ][ 3 ];
		}
	}
	return node;
}

Xmenu.prototype.cumulateOffsets = function( iStyleIndex, iMaxLevel )
{
	var iOffset = 0;
	for ( i = 0; i < iMaxLevel; i++ )
	{
		iOffset += this.styles[ i + 1 ][ iStyleIndex ];
	}
	return iOffset;
}

Xmenu.prototype.addXlayer = function( xparentLayer, node, styles )
{
	var parent =	null;
	var x =	"left";
	var y =	"top";
	var offsetX = node.absX;
	var offsetY = node.absY;
	var w =	styles[ node.iLevel + 1 ][ 2 ];
	var h = styles[ node.iLevel + 1 ][ 3 ];
	var clipTop = 0;
	var clipRight = w;
	var clipBottom = h;
	var clipLeft = 0;
	var zIndex =	node.iLevel;
	var visibility = false;
	var fading =	styles[ node.iLevel + 1 ][ 4 ];
	var events =	
	[ 
		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 + ")"
	];						
	var sText =  node.sText;
//	alert("X:"+offsetX+", Y:"+offsetY+", Text:"+sText);
	var bgcolor = styles[ node.iLevel + 1 ][ 5 ][ 0 ];
	var fgcolor =  styles[ node.iLevel + 1 ][ 5 ][ 1 ];
	var align =  styles[ node.iLevel + 1 ][ 5 ][ 2 ];
	var iTopTextBorder = styles[ node.iLevel + 1 ][ 5 ][ 3 ]
	var iRightTextBorder = styles[ node.iLevel + 1 ][ 5 ][ 4 ]
	var iBottomTextBorder = styles[ node.iLevel + 1 ][ 5 ][ 5 ]
	var iLeftTextBorder = styles[ node.iLevel + 1 ][ 5 ][ 6 ]
	var href = null;
	var bold =  styles[ node.iLevel + 1 ][ 5 ][ 7 ];
	var fontface =  styles[ node.iLevel + 1 ][ 5 ][ 8 ];
	var fontsize =  styles[ node.iLevel + 1 ][ 5 ][ 9 ];
	if ( styles[ node.iLevel + 1 ][ 5 ][ 11 ] )
	{	// icon defined
		var icon = ( node.child || styles[ node.iLevel + 1 ][ 5 ][ 10 ] )? styles[ node.iLevel + 1 ][ 5 ][ 11 ] : this.sSpacerUrl;
		var icon_w = styles[ node.iLevel + 1 ][ 5 ][ 12 ];
		var icon_h = styles[ node.iLevel + 1 ][ 5 ][ 13 ];
		var iconBorder = styles[ node.iLevel + 1 ][ 5 ][ 14 ];
	}
	else
	{	// icon not defined
		var icon = null;
		var icon_w = 0;
		var icon_h = 0;
		var iconBorder = 0;
	}
	var src = null; // iframe: src

	return new Xlayer( parent, xparentLayer, x, y, offsetX, offsetY, w, h, clipTop, clipRight, clipBottom, clipLeft, zIndex, visibility, bgcolor, fading, events, sText, bold, align, iTopTextBorder, iRightTextBorder, iBottomTextBorder, iLeftTextBorder, fgcolor, href, icon, icon_w, icon_h, iconBorder, fontface, fontsize, src, this.sSpacerUrl );
}

Xmenu.prototype.create = function()
{
	this.createXlayers( null );
	this.setVisibSiblings( this.tree, true );
}

Xmenu.prototype.createXlayers = function( tree )
{
	if ( !tree ) 
	{ // call without param -> take root node
		tree = this.tree;
	}
	if ( tree.child )
	{
		this.createXlayers( tree.child );
	}
	if ( tree.sibling )
	{
		 this.createXlayers( tree.sibling );
	}

	tree.xlayer.create();
}

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.tree, true );
	}
	this.bOpened = true;
	this.openListener.onMenuOpen( this );
}

Xmenu.prototype.openLastClicked = function()
{
	node = this.navigationNode;
	this.lastNode = node;

	if ( node.child != null )
		this.setVisibSiblings( node.child, true );

	while ( node != null )
	{
		this.highlightClickedNode( node );
		if ( node.sParent != null )
		{
			this.setVisibSiblings( eval( node.sParent ).child, true );
			node = eval( node.sParent );
		}
		else
		{
			this.setVisibSiblings( this.tree, true );
			node = null;
		}
	}
}

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;

	if ( this.nodeFound ) 
		return true;
	else 
		return false;
}

Xmenu.prototype.close = function()
{
	if ( this.bOpened && !this.bKeepExpansionState )
	{
		this.setVisibChildren( this.tree, false );
		this.setVisibSiblings( this.tree, true );
		if ( this.iType == this.COLLAPSING )
			this.setCollapsePos( this.tree );
//		if ( this.bClick && this.lastNode )
//		{
			this.clearHighlightChildren( this.tree );
			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 );
		}
		if ( this.outNode )
			var outNode = this.outNode;
		else
			var outNode = this.tree;
		if ( outNode.iLevel > node.iLevel )
		{
			this.showBranch( node, this.outNode );
//			this.setVisibSiblings( eval( outNode.sParent + ".child" ), false );
//			this.setVisibSiblings( outNode.child, false );
		}
		else if ( outNode.iLevel == node.iLevel )
		{
			this.setVisibSiblings( outNode.child, false );
		}
		this.setVisibSiblings( node.child, true );
	}
	if ( this.checkClickPath( node ) )
	{ // current node is not the node that was clicked (or its parents)
		this.highlight( node, true );
	}
	return false;
}

Xmenu.prototype.onmouseout = function( node )
{
	if ( this.checkClickPath( node ) )
		this.highlight( node, 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.checkClickPath = function( node )
{
	if ( this.bHighlightClickedNodes )
	{
		lastNode = this.lastNode;
		while ( lastNode != null )
		{
			if ( lastNode == node ) // node clicked found
				return false;
			else // continue looking for it
				lastNode = eval( lastNode.sParent );
		}
		return true;
	}
	else
	{
		return true;
	}
}

Xmenu.prototype.checkOnmouseout = function()
{
	if ( this.overNode == this.outNode && !( 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.tree );
		this.linkClickListener.onLinkClick( this ); // inform controller
	}
	else if (
		( ( this.iType == this.VERTICAL || this.iType == this.HORIZONTAL ) && this.bClick ) || 
		this.iType == this.COLLAPSING )
	{
		this.highlight( node, true );
		if ( !this.bOpened )
		{ // this menu will open
			this.bOpened = true;
			this.openListener.onMenuOpen( this );
		}
			
		if ( this.iType == this.COLLAPSING )
			this.collapse( node );
		else if ( ( this.iType == this.VERTICAL || this.iType == this.HORIZONTAL ) && this.bClick )
			this.showBranch( node, this.lastNode );
		this.lastNode = node;
	}
	return false;
}

Xmenu.prototype.showBranch = function( node, hideNode )
{
//	if ( this.bClick && hideNode == node && node.child && node.child.xlayer.isVisible() )
	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.tree, false );
			this.clearHighlightChildren( this.tree, false );
		}
		if ( node.child ) this.setVisibSiblings( node.child, true );
		while ( node )
		{ // show new nodes
			if ( this.bClick )
				this.highlightClickedNode( node, true );
			if ( node.sParent ) 
				this.setVisibSiblings( eval( node.sParent ).child, true );
			else
				this.setVisibSiblings( this.tree, true );
			node = eval( node.sParent );
		}
	}
}

Xmenu.prototype.clearHighlightChildren = function( node )
{
	if ( node )
	{
		if	( node.child )
			 this.clearHighlightChildren( node.child );
		if ( node.sibling )
			 this.clearHighlightChildren( node.sibling );
		this.highlight( node, false );
	}
}

Xmenu.prototype.collapse = function( node )
{
	this.showBranch( node, this.lastNode );
	this.setCollapsePos( this.tree );
}

Xmenu.prototype.setCollapsePos = function( node )
{
	if ( node == this.tree ) // start looping
		this.absY = this.tree.xlayer.y;
			
	if ( node.xlayer.isVisible() )
	{
		node.xlayer.setPos( node.xlayer.x, this.absY );
		this.absY += node.xlayer.h;
	}

	if ( node.child ) 
		this.setCollapsePos( node.child );
	if ( node.sibling ) 
		this.setCollapsePos( node.sibling );
}

Xmenu.prototype.highlight = function( node, bHighlight )
{
	var index = ( bHighlight )? 6 : 5;	// style for mouseover or mouseout ?
	node.xlayer.setBgColor( this.styles[ node.iLevel + 1 ][ index ][ 0 ] );
	// nn4 crashes, iemac stops rendering
	if ( !is.nn4up && !is.iemac5up ) node.xlayer.setFgColor( this.styles[ node.iLevel + 1 ][ index ][ 1 ] );
}

Xmenu.prototype.highlightClickedNode = function( node )
{
	if ( node && this.bHighlightClickedNodes )
	{
		node.xlayer.setBgColor( this.styles[ 0 ][ 0 ] );
		if ( !is.nn4up && !is.iemac5up ) 
			node.xlayer.setFgColor( this.styles[ 0 ][ 1 ] );
	}
}

Xmenu.prototype.setVisibSiblings = function( node, bVisibility )
{
	if ( node )
	{
		if ( node.sibling )
			 this.setVisibSiblings( node.sibling, bVisibility );
		node.xlayer.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.xlayer.setVisibility( bVisibility );
	}
}

Xmenu.prototype.isNavigationNodeFound = function()
{
	return this.navigationNode != null;
}
