/******************************************\
  GSSI DMenu builder
  Requires: Base, DOM, Environment, Events
\******************************************/

if (! GSSI) { alert("gssi.dmenu.js: gssi.base.js not loaded") };
if (! GSSI.DOM ) { alert("gssi.dmenu.js: gssi.dom.js not loaded") };
if (! GSSI.Environment ) { alert("gssi.dmenu.js: gssi.environment.js not loaded") };
if (! GSSI.Events ) { alert("gssi.dmenu.js: gssi.events.js not loaded") };

GSSI.DMenu = GSSI.Class({
	initialize: function( source, options ) {
		this.options = GSSI.Base.Extend( {
				mainposition:'below left',
				subposition:'top after',
				disappeardelay:100,
				appeardelay:0,
				cssclass:"dmenu",
				cascadecssclass: null,
				opaque: true,
				shadow: false,
				shadowLeft:0,
				shadowTop:0,
				shadowWidthDiff: 0,
				shadowHeightDiff: 0,
				mainoffsetx: 0,
				mainoffsety: 0,
				suboffsetx: 0,
				suboffsety: 0,
				style: null,
				height:null,
				width:null,
				onmouseover: null,
				onmousemove: null,
				onmouseout: null,
				onmenushow: null,
				onmenuhide: null,
				onmenuchange: null,
				insertatend: false
			}, options );
		
		this.submenus = {};
		this.allblocks = {};
		if (GSSI.Environment.Browser.KHTML) {
			this.source = GSSI.Base.Extend( { '\uE48B':{ xxx:'xxx' } }, source );  // Safari misrenders the first one - insert dummy
		} else {
			this.source = source;
		}
		this.timer = null;
		this.index = GSSI.DMenu.add(this);
		this.displayroot = null;
		
		var menu = this;
		GSSI.Environment.onDOMReady( function() { menu.build(); } );
	},

	build: function() {
		if ( this.built ) { return; }
		for(var m in this.source) {
			this.submenus[m] = this._buildrecursive( this.source[m], null );
		}
		this.built = true;
	},
	
	_buildrecursive: function( source, parent ) {
		var options;

		options = GSSI.Base.Clone(this.options);
		if (parent == null) {
			options.position = this.options.mainposition;
			options.offsetx = this.options.mainoffsetx;
			options.offsety = this.options.mainoffsety;
		} else {
			options.position = this.options.subposition;
			options.offsetx = this.options.suboffsetx;
			options.offsety = this.options.suboffsety;
		}
		options = GSSI.Base.Extend(options, source["_options"]);
		var styleobj = GSSI.Base.Extend( { position:'absolute', left:0, top:0, visibility:'hidden', zIndex:5000, display:'none' }, options.style );
		var localclass = this.options.cssclass;
		
		if ( (options.cssclass) && (options.cssclass != this.options.cssclass) ) {
			localclass += " " + options.cssclass;
		}
		
		var block = GSSI.DOM.createElement( "div",
												{ 'class': localclass, id:GSSI.DOM.UID() },
												styleobj
										   );
		this.allblocks[ block.id ] = block;
		
		block.options = options;
			
		block.menuparent = parent;
		block.submenus = {};
		source["_options"] = null;
		if( block.options.shadow ) {
			block.shadow = GSSI.DOM.createElement( "div", { 'class':'shadow' }, {position:'absolute',left:0,top:0, display:'none'} );
			block.appendChild(block.shadow);
		}
		if( block.options.opaque ) {
			block.iframe = GSSI.DOM.createElement( "iframe", { 'class':'backing' }, {position:'absolute',left:0,top:0,zIndex:-20,border:'none', display:'none'} );
			block.iframe.src = "javascript:' ';";
			block.appendChild(block.iframe);
		}
		block.list = GSSI.DOM.createElement( "ul", {}, {margin:0, position:'absolute', top:0, left:0, listStyle:'none', width:'auto', display:'none'} );
		block.appendChild(block.list);
		
		if (block.options.height !== null) { block.list.style.height = block.options.height + 'px'; }
		if (block.options.width !== null) { block.list.style.width = block.options.width + 'px'; }
		
		var menu = this;
		var linedata, linetype;
		var listitem;
		var a, target, c, classname, s;
		var count = 0;
		var className = '';
		for (var m in source) {
			count++;
		}
		var itemCount = count;
		count = 0;
		for( var m in source ) {
			linedata = source[m];
			className = '';
			if (! linedata) { continue; };
			linetype = typeof(linedata);
			if (linetype == 'function') { continue; };
			
			count++;
			
			if (count == 1) { className = 'first-child'; }
			if (count == itemCount-1) { className = className + ' last-child'; }
			
			listitem = GSSI.DOM.createElement( "li", {'class': className}, { display:'block', zoom:'1', verticalAlign:'bottom'} );
			if (typeof(linedata) == 'string') {
				target = null;
				classname = null;
				 while (true) {

					if ((! target) && (linedata.substring(0,7) == "target:")) {
						c = linedata.indexOf(":", 7 );
						target = linedata.substring( 7, c );
						linedata = linedata.substring(c+1);
						continue;
					} 

					if ((! classname) && (linedata.substring(0,6) == "class:")) {
						c = linedata.indexOf(":", 6 );
						classname = linedata.substring( 6, c );
						linedata = linedata.substring(c+1);
						continue;
					} 
					
					break;
				};
				
				a =	GSSI.DOM.createElement( "a",
					{ href: linedata, target: target, 'class': classname },
					{ display:'block', zoom:'1' },
					null
				);
				s =	GSSI.DOM.createElement( "span", null, null, m );
				a.appendChild(s);
				a.addEvent( 'mouseover', function() { menu.keepOnly(block); } );
				a.addEvent( 'mouseout', function() { menu.hide(); } );
				listitem.appendChild( a );
			} else {
				var b = this._buildrecursive( linedata, block );
				block.submenus[m] = b;
				a = GSSI.DOM.createElement( "a",
					{ href:(block.submenus[m].options.link || 'javascript:void(0);'), 'class':block.submenus[m].options.cssclass },
					{ display:'block', zoom:'1' },
					null
				);
				s =	GSSI.DOM.createElement( "span", null, null, m );
				a.appendChild(s);
				a.addEvent( 'mouseover', this._makemenushow(a, b) );
				a.addEvent( 'mouseout', function() { menu.hide(); } );
				listitem.appendChild(a);
			}
			block.list.appendChild(listitem);
		}

		if( this.options.onmouseover && block ) { GSSI.Events.Add( block, 'mouseover', menu.options.onmouseover ) };
		if( this.options.onmousemove && block ) { GSSI.Events.Add( block, 'mousemove', menu.options.onmousemove ) };
		if( this.options.onmouseout && block ) { GSSI.Events.Add( block, 'mouseout', menu.options.onmouseout ) };	

		if (menu.options.insertatend) {
			GSSI.DOM.GetBody().appendChild(block);
		} else {
			GSSI.DOM.GetBody().prependChild(block);
		}
		return block;
	},
	
	_makemenushow: function( anchor, block ) {
		var menu = this;
		return function() {
			 menu.showBlock(block, anchor);
		};
	},
	
	show: function( name, callingelement ) {
		this.showBlock( this.submenus[name], callingelement );
	},

	showID: function( id, callingelement ) {
		this.showBlock( this.allblocks[id], callingelement );
	},
	
	showBlock: function( element, callingelement ) {
		var menu = this;
		this._settimer( function(){ 
			menu._showNowWithAncestors(element, callingelement);
			if ( menu.options.onmenushow ) { menu.options.onmenushow(this); };
		}, this.options.appeardelay );
	},
	
	hide: function() {
		var menu = this;
		this._settimer( function(){
			menu._hideNow();
			if ( menu.options.onmenuhide ) { menu.options.onmenuhide(this); };
		}, this.options.disappeardelay );
	},
	
	keep: function() {
		this._cleartimer();
	},
	
	keepOnly: function( element ) {
		this._cleartimer();
		this._showNowWithAncestors( element, null );
	},

	keepOnlyID: function( id ) {
		this.keepOnly( this.allblocks[id] );
	},
	
	_menusize: function( element ) {
		if (! element._dmenusized ) {
			var i;
			element.sizeTo( element.list );			
			
			element._dmenusized = true;
		}
	},
	
	_showNow: function( element ) {
		this._menusize(element);
		element.style.visibility = 'visible';
		if (element.callingelement && this.options.cascadecssclass) {
			element.callingelement.addClass(this.options.cascadecssclass);
		}
	},

	_showNowWithAncestors: function( element, callingelement ) {
		
		element.style.visibility = 'hidden';
		element.style.display = 'block';
		element.list.style.display = 'block';
		if( callingelement && element ) {

			this._menusize(element);
			element.moveTo( callingelement, element.options.position, { offsetTop:element.options.offsety, offsetLeft:element.options.offsetx } );
			
			if( element.iframe ) {
				element.iframe.sizeTo( element.list );
			}
			
			if( element.shadow ) {
				element.shadow.sizeTo( element.list, element.options.shadowWidthDiff, element.options.shadowHeightDiff );
				element.shadow.style.top = element.options.shadowTop + "px";
				element.shadow.style.left = element.options.shadowLeft + "px";
			}
						
			element.callingelement = GSSI.$(callingelement);
		}
		
		this._hideNow();
		var root = null;
		if (element) {
			var e = element;
			do {
				this._showNow(e);
				root = e;
				e = e.menuparent;
			} while (e);
		}
		if (this.displayroot != root) {
			if ( this.options.onmenuchange ) { this.options.onmenuchange(this); };
		}
		this.displayroot = root;
	},
	
	_hideNow: function() {
		var b;
		for( var id in this.allblocks ) {
				b = this.allblocks[id];
				b.style.visibility = 'hidden';
				if (b.callingelement && this.options.cascadecssclass) {
					b.callingelement.removeClass(this.options.cascadecssclass);
				}
		}
	},
	
	_cleartimer: function() {
		if( this.timer ) {
			clearTimeout(this.timer);
			this.timer = null;
		};
	},
	
	_settimer: function( func, delay ) {
		this._cleartimer();
		var menu = this;
		this.timer = setTimeout( function(){ menu._cleartimer(); func(); }, delay );		
	}
});

GSSI.DMenu.Static({

		all: [],
		
		add: function( menuobject ) {
			var i = GSSI.DMenu.all.length;
			GSSI.DMenu.all[i] = menuobject;
			return i;
		}

});




