function Window( options ){
	
	//setup jquery
	this.$ = jQuery;		
	
	//setup a ref to self
	var self = this;
	
	//initialize this
	this.init();
	
	//setup default options
	
	/*
	@param 	block		true | false 			means to block the UI with a semi-transparent overlay
	@param	style		'pop' | 'slide'			popup window or a slide over
	@param	direction	'bottom' | 'top'		slide from the bottom or from the top
	@param	modal		true | false			modal: true means to make this dialog a modal dialog (user MUST act on popup)
	@param	close		'.close_pop'			class name of a close button in the markup
	*/
	this.defaults = { 
		style: 'pop', 
		direction: 'bottom', 
		modal: false, 
		block: true, 
		close: function(){}, 
		open: function(){}, 
		duration:100,
		addClose: true,
		error: false,
		alert: false,
		focus: true 
	};	
	
	//flag to indicate blockd
	this.blocked = false;
	
	//extend options
	this.options = this.$.extend( {}, this.defaults, options );
			
	//setup DOM stuff on ready		
	this.$().ready( function(){ self.init( true ); } );
	
	//set this as the current window object
	Window.current = this;
	
}


//setup some default globals
Window.defaults = {
	
	open: function(){},
	close: function(){}

};


Window.prototype.init = function( dom ){

	//Window init routines
		
	//DOM ready routines	
	if( dom == true ){
		
		//setup DOM refs
		this.$body = this.$('body');
		
		//setup the UI blocker
		this.$block = this.$('<div><div></div></div>').addClass('block').css({position:'fixed', left:0, top: 0, height:'100%', width:'100%', background: '#000', opacity:0.6, display:'none' }).appendTo( this.$body );
		
		//setup popups
		this.$pop = this.$('<div class="pop"><div class="pop_content"></div></div>')
			.css(
				{
					display:'none'
				}
			)
			.prependTo( this.$body)
			.wrap( '<div class="pop_viewport"></div>' );
		
		this.$popContent = this.$pop.find('>.pop_content');		
					
	} else {
		
	}	

}

/*

@var	content		string|url|jquery DOM|DOM  

*/
Window.prototype.pop = function( content, options ){
	
	
	var self = this;
	this.options = this.$.extend( {}, this.defaults, options );
	
	var reUrl 	= /[A-Za-z0-9\.-]{3,}\.[A-Za-z]{3}/;
	
	function showDOM(){
		self.$pop.find('.pop_content').empty();
		
		if( self.options.error == true ){
			self.$pop.find('.pop_content').append(
				$j('<div class="error message"><h2>Error</h2></div>')
					.append( $j('<p></p>').append(content) )
			);
		}else{
			self.$pop.find('.pop_content').append( content );
		}
		
		self.initPop( options );
		self.show();													
		self.options.open.call( self );			
	}
		
	if( typeof content == 'string' && reUrl.test( content ) ){
		if( this.options.block ){ this.block(); }
		this.$body.addClass('window_loading');
		
		this.$popContent.load(
			content,
			function(){
				
				self.$body.removeClass('window_loading');
				self.initPop();
				self.show();													
				Window.defaults.open.call( self, this );
				self.options.open.call( self, this  );
			}
			
		);
		
	//its just a string or DOM					
	} else if(typeof content == 'string' || typeof content == 'object') {
		
		if( !content.jquery && content.constructor == Object){			
			content = SDNA.utils.json2String( content, '<br />' ,'<br />' );	
		}
				
		if( this.options.block ){ 
			this.block( {callback:showDOM} ); 
		}else{
			showDOM();				
		}			
	}

}

Window.prototype.initPop = function(){
	
	//setup ref to self for functions
	var self = this;
	
	//add a class if there is one
	this.$pop.attr('class','pop');
	if( this.options.className ){
		this.$pop.addClass( this.options.className );
	}
	
	//if this is an error popup
	if( this.options.error == true ){
		this.$pop.addClass('pop_error');
	}
	
	//if this is an alert popup
	if( this.options.alert == true ){
		this.$pop.addClass('pop_alert');
	}
	
	//change width if set
	if( this.options.width ){
		this.$pop.css( {width:this.options.width} );
	}else{
		this.$pop.css( {width:null} );
	}
	
	//add a close button if close is set to true
	if( this.options.addClose == true){
		this.$popContent.append('<a class="pop_close">Close</a>');
	}
	
	//auto focus the first field
	if( this.options.focus == true ){
		this.$popContent.find(':text,textarea').eq(0).focus();
	}
	
	//bind the close button, if there is one
	this.$pop
		.find( '.pop_close' )
		.unbind('click.pop_close')
		.bind('click.pop_close',function(){self.closePop();});
		
	//put the zindex above everything
	this.$pop.css({zIndex: SDNA.utils.getTopZindex()});
		
	//bind a click to the block if not modal
	if( this.options.modal == false ){
		this.$block.unbind('click.modal').bind('click.modal',function(){self.closePop();});
	}
	
	//center the popup
	this.centerPop();
	if( this.options.centerOnResize ){
		//on resize, move this pop
		this.$(window)
			.unbind('resize.pop_center')
			.bind('resize.pop_center', 
				function(){ 
					self.centerPop();
				} 
			);
	}
		
}

Window.prototype.centerPop = function(){
	if( this.$pop ){
		//we only need to vertically center, css takes care of horz	
		this.$pop.css({top: this.$().scrollTop() });
	}
}

Window.prototype.closePop = function(){	
	this.unblock();
	this.hide();
	Window.defaults.close.call( this );
	this.options.close.call( this  );
	this.$(window).unbind('resize.pop_center');
	SDNA.Event.publish('window.closed', {});
}

Window.prototype.hide = function(){
	
	this.$pop.hide();
}

Window.prototype.show = function(){	
	this.$pop.show();
	SDNA.Event.publish('window.shown',{});
}

Window.prototype.block = function( options ){
	
	var size = Window.size();
	var options = options || {};
	options.callback = options.callback || function(){};
	
	this.$block.css(
		{
			zIndex:SDNA.utils.getTopZindex()
		}
	);
		
	this.$block.stop().fadeIn( this.options.duration, options.callback );
	
	if( options && options.loading ){
		this.$body.addClass('window_loading');
	}
	
	this.blocked = true;
	
}

Window.prototype.unblock = function( callback ){
	
	this.$block.fadeOut(this.options.duration, callback );
	this.$body.removeClass('window_loading');
	this.blocked = false;	
}

Window.prototype.isBlocked = function(){
	return this.blocked;
}

Window.prototype.isPopped = function(){
	return this.$pop.css('display') != 'none';
}

Window.prototype.getContent = function(){
	return this.$pop.get(0);
}

Window.size = function(){
	var d = document, de = d.documentElement, win = window; 
	var h = (win.innerHeight? win.innerHeight : de.clientHeight?de.clientHeight:d.body.clientHeight );
	var w = (win.innerWidth? win.innerWidth : de.clientWidth?de.clientWidth:d.body.clientWidth );
	return {width:w,height:h};
}

//Singleton extensions
Window.pop = function( content, options ){
	
	if( !Window.current ){
		Window.current = new Window();		
	}else{
		
		if( Window.isPopped() ){
			//close any previous popups
			Window.current.closePop();
		}
	}
	
	//now popup this one
	Window.current.pop( content, options);
	
}

Window.block = function( options){
	
	if( !Window.current ){
		Window.current = new Window();
		
	}
	Window.current.block( options );	
	
}
Window.unblock = function( callback ){
	
	if( !Window.current ){
		Window.current = new Window();
		
	}
	Window.current.unblock( callback );	
	
}
Window.isBlocked = function(){
	
	if( Window.current ){
		return Window.current.isBlocked();
	}else{
		return false;
	}
	
}
Window.isPopped = function(){
	
	if( Window.current ){
		return Window.current.isPopped();
	}else{
		return false;
	}
	
}
Window.show = function( ){
		
	if( Window.current ){
		Window.current.show();
		return true;		
	}else{
		return false;
	}
}
Window.hide = function( ){
	
	if( Window.current ){
		Window.current.hide();
		return true;
	}else{
		return false;
	}
}
Window.close = function( ){
	
	if( Window.current ){
		Window.current.closePop();
		return true;
	}else{
		return false;
	}
}
