function Menu( trigger, cfg ){
	
	//ref the trigger
	this.trigger = trigger;
	this.$trigger = $j(this.trigger);

	//setup the options
	cfg = cfg || {};
	this.config = {
		orient: 'right',
		offset: { left: 0, top: 0 },
		vAlign: 'top'
	};
	
	$j.extend( this.config, cfg);
	
	//create the menu
	this.create();
	
	//tie this DOM trigger to this menu
	this.trigger.menu = this;
	
	this._open = false;
	
	this.bodyClickCloseHandler = function(e){
		var menu = e.data.menu;			
		var $target = $j(e.target);
		if( 
			e.target != menu.trigger &&
			menu.$trigger.find('*').index( e.target ) < 0			
			){
			
			menu.close();	
		}			
	}
	
	this.windowResizeHandler = function(e){
		var menu = e.data.menu;			
		menu.orient();		
	}
	
	//point the current menu to this
	Menu.current = this;
		
}

Menu.prototype.create = function(){
	
	//ref the body
	this.$body = $j('body').eq(0);
	
	//setup the menu
	this.$menu = $j('<div class="menu"></div>').css({position:'absolute',display:'none'});
	
	//if there was a class name set, add it
	if( this.config.className ){
		this.$menu.addClass( this.config.className)
	}
	
	//ref options
	this.$options = $j('<ul class="menu_options" />');
	
	//add the options list to the menu
	this.$menu.append( this.$options );
	
	//now wrap this object with a wrapper
	/*this.$wrap = this.$trigger.parents('.menu_wrap');
	if( this.$wrap.length < 1 ){
		this.$wrap = $j('<span class="menu_wrap" />');
		this.$trigger.wrap( this.$wrap );
	}*/
	
	this.$menu.get(0).trigger = this.trigger;
	
	//add the options to the wrap
	this.$body.prepend( this.$menu );

}

Menu.prototype.addOptions = function(){
	
	var opts = arguments, $li, $a;
	
	for( var i=0,opt; opt = opts[i]; ++i ){
		
		$li 	= $j('<li />');
		
		if( opt.constructor == String || opt.jquery ){
		
			$li.append( opt );
		
		}else if( opt.label ){
			$a = $j('<a />')
					.text( opt.label )
					.attr('href', opt.action)
					.addClass( opt.className )
					.appendTo( $li );
						
			if( opt.click  && typeof opt.click == 'function'){
				$a.click( opt.click );
			}	
		}
					
		this.$options.append( $li );	
		
	}
	
}

Menu.prototype.close = function(){	

	this._open = false;
	
	this.$menu.css({display:'none'});
	
	$j(document).unbind('click.menu_close',this.bodyClickCloseHandler);
	$j(window).unbind('resize.menu_orient', this.windowResizeHandler );
	
	SDNA.Event.publish('menu.close',{});
}

//flip-flop the menu if it will get cutoff by the right side 
//of the browser	
Menu.prototype.orient = function(){
	
	//position the menu
	var triggerOffset = this.$trigger.offset(),
		 mWidth = this.$menu.get(0).offsetWidth || this.$menu.width(),
		 tWidth = this.trigger.offsetWidth || this.$trigger.width(),
		 tHeight = this.$trigger.height(),
		 wWidth = $j(window).width();
	
	//orientation may change from the default
	var orient = this.config.orient;
	if( triggerOffset.left + tWidth + mWidth > wWidth ){	
		orient = 'left';		
	}else if( triggerOffset.left - mWidth){
		orient = 'right';
	}
	this.$menu.removeClass('menu_left menu_right').addClass( 'menu_' + orient );

	
	//adjust the offset
	var menuPosition = { 
		top: triggerOffset.top + this.config.offset.top + (this.config.vAlign=='middle'?tHeight/2:0), 
		left: triggerOffset.left + (orient == 'right'? tWidth + this.config.offset.left : -mWidth-this.config.offset.left )
	};
	
	//now position it off of the offset
	this.$menu.css( menuPosition );		
}

Menu.prototype.open = function(){	
	
	this._open = true;
	
	//put the menu above everything
	// note: this was changed to accomodate pop_viewport which now has a zIndex of 99999
	this.$menu.css({zIndex: 100000, display:'block' });
	
	this.orient();
				
	//close menu on doc click
	$j(document).bind(
		'click.menu_close', 
		{menu: this},
		this.bodyClickCloseHandler
	);	
	
	$j(window).bind(
		'resize.menu_orient', 
		{menu: this},
		this.windowResizeHandler
	);	
		
	SDNA.Event.publish('menu.open',{});

}

Menu.prototype.toggle = function(){	
	if( this.isOpen() ){
		this.close();
	}else{
		this.open();	
	}
}

Menu.prototype.isOpen = function(){
	
	return this._open;
	
}

Menu.prototype.destroy = function(){
	delete this.trigger.menu;
	this.$menu.remove();
}

//Menu content getter/setter
Menu.prototype.content = function( content ){
	
	if( content ){
		this.$options.empty().append( content );
	}else{
		return this.$menu.get(0);
	}
}

//Singleton extensions
Menu.getMenuFor = function( trigger ){
	
	return trigger.menu || false;
	
}

//Singleton extensions
Menu.getTriggerFor = function( menu ){
	
	return menu.trigger || false;
	
}

Menu.open = function( ){
	
	if( Menu.current ){
		Menu.current.open();
		return true;		
	}else{
		return false;
	}
}

Menu.close = function( ){
	
	if( Menu.current ){
		Menu.current.close();
		return true;
	}else{
		return false;
	}
}
