//-( Litebox Module )-----------------------------------------------------------

/**
 *	Litebox creates modal dialogs.
 *
 *	@copyright	Portland Webworks 2006
 */

// Handle for the visible litebox; liteboxes are modal, so this is unique.
var __litebox_handle = null;

(new Image( )).src = auri( 'resource/image/litebox/black_matte.png' );
(new Image( )).src = auri( 'resource/image/litebox/stipple_matte.gif' );
(new Image( )).src = auri( 'resource/image/litebox/indicator_bar.gif' );


//-( Litebox )------------------------------------------------------------------

/**
 *	Create a modal dialog using an arbitrary node for content.
 *
 *	@class		Litebox
 */
 
/* class */ function Litebox( ) {
	this.setFrame( document.body.appendChild(
		 document.createElement( 'div' )
		) );
		
	this.getFrame( ).className	= 'liteboxFrame';
	
	this.setScrollLock( true );
	this.setDismissOnClick( true );

	/**
	 *	@browser Internet Explorer
	 *	IE doesn't "do" the alpha channel on PNGs, so we use a stippled GIF
	 *	instead -- it's less pretty but approximates the desired effect. We
	 *	probably don't need to do this for IE 7?
	 */
	if( isIE( ) && isAtMostVersion( 6 ) ) {
	    this._frame.style.background = 'none';
		this._frame.style.backgroundImage
			= "url( '"
			+ auri( 'resource/image/litebox/stipple_matte.gif' )
			+ "' )";
		}
	}

extend( Litebox.prototype, {

	_canvas							: null
,	_frame							: null
,   _scrollLock         			: false
,   _ignoreCanvasClick 				: false

,	_delayUncloaking				:	false
,	getDelayUncloaking				:	function( ) {
		return this._delayUncloaking;
		}
,	setDelayUncloaking				:	function( v ) {
		this._delayUncloaking = v;
		return this;
		}

,	setDismissOnClick	: function( flag ) {

		if( flag ) {
//		console.log('here');
			this._frame.onclick	= bind( this, function( e ) {
				e = getEvent( e );
				if( this.getIgnoreCanvasClick( ) ) {
					if( getEventTarget( e ) !== this.getFrame( ) ) {
						return true;
						}
					}
//console.log('dispose');
				this.dispose( );
				} );
			}
		else {
			this._frame.onclick	= null;
			}

		return this;
		}

,   setIgnoreCanvasClick    : function( flag ) {
		if( flag ) {
			this._ignoreCanvasClick = true;
			}
		else {
			this._ignoreCanvasClick = false;
			}
		return this;
		}

,   getIgnoreCanvasClick    : function( ) {
        return this._ignoreCanvasClick;
        }

,   setScrollLock       : function( flag ) {
        if( flag ) {
            this._scrollLock = true;
            }
        else {
            this._scrollLock = false;
            }
        return this;
        }

,   getScrollLock       : function( ) {
        return this._scrollLock;
        }

,	setFrame			: function( f ) {
		this._frame = f;
		return this;
		}
        
,   getFrame            : function( ) {
        return this._frame;
        }

,	getCanvas			: function( ) {
		return this._canvas;
		}
		
,	setCanvas			: function( c, hide ) {

		this.clearCanvas( );

		this._canvas					= c;
		this._canvas.style.position	    = 'relative';
		this._canvas.style.zIndex	    = 24001;
		
		if( hide !== false ) {
    		this.cloakCanvas( );
	        }
        
		this.getFrame( ).appendChild( this._canvas );
		
		return this;
		}

,	clearCanvas			: function( ) {
		// FIXME: Remove canvas node, etc.
		if( this._canvas ) {
			removeNode( this._canvas );
			}
		this._canvas	= null;
		}
	
,	getCanvasWidth		: function( ) {
		return getObjWidth( this.getCanvas( ) );
		}

,	getCanvasHeight		: function( ) {
		return getObjHeight( this.getCanvas( ) );
		}
		
,	setCanvasPosition	: function( x, y ) {
		this.getCanvas().style.left	= x + 'px';
		this.getCanvas().style.top	= y + 'px';
		return this;
		}
		
,	updateFrame			: function( ) {
		this.getFrame( ).style.height
			= Math.max( getWindowHeight( ), getDocumentHeight( ) ) + 'px';
		this.getFrame( ).style.width
			= Math.max( getWindowWidth( ), getDocumentWidth( ) ) + 'px';
		}

,	updateCanvas		: function( ) {
		this.getCanvas( ).style.width	= this.getCanvasWidth( );
		this.getCanvas( ).style.height	= this.getCanvasHeight( );
	}
	
,	updateCanvasPosition: function( ) {
		this.updateFrame( );

		var hW = getWindowHeight( );
		var hO = this.getCanvasHeight( );
		var hS = getScrollOffsetY( );
		
		var wW = getWindowWidth( );
		var wO = this.getCanvasWidth( );
		var wS = getScrollOffsetX( );
		
		var pW = Math.max( parseInt( (wW - wO)/2 + wS ), 0 );
		var pH = Math.max( parseInt( (hW - hO)/2 + hS ), 0 );

		this.setCanvasPosition( pW, pH );
		}

,	hide				: function( ) {
		this.makeHidden( );
		LiteboxController.pop( this );
		}

,   isHidden            : function( ) {
		// FIXME: This won't work in general. It's only used by
		// the interactive map.
        return ( __litebox_handle == null );
        }

,	show				: function( ) {
		
		if( !this.getCanvas( ) ) {
			alert( 'setCanvas( ) before you show() a litebox!' );
			}

		LiteboxController.push( this );

		this.cloakCanvas( );
		this.makeVisible( );
		
		this.updateCanvasPosition( );
		
		this.uncloakCanvas( );
		
		return this;
		}

,	makeVisible			: function( ) {
		this.showFrame( );
		this.showCanvas( );
        
		
		if( !this.getDelayUncloaking( ) ) {
			this.uncloakCanvas( );
			}
		}

,	makeHidden			: function( ) {
		this.hideCanvas( );
		this.hideFrame( );
		}

		
,	hideCanvas			: function( ) {
		this.getCanvas( ).style.display = 'none';
		}
		
,	showCanvas			: function( ) {
		this.getCanvas( ).style.display = 'block';
		}

,	hideFrame			: function( ) {
		this.getFrame( ).style.display	= 'none';
		}
	
,	showFrame			: function( ) {
		this.getFrame( ).style.display = 'block';
		}


// Allows litebox to get dimensions of box for the update( ) call, without the user seeing the litebox jump all around.
,   cloakCanvas         : function( ) {
        this.getCanvas( ).style.visibility = 'hidden';
        return this;
        }
,   uncloakCanvas       : function( ) {
        this.getCanvas( ).style.visibility = 'visible';
        return this;
        }

,	dispose				: function( ) {
		this.hide( );
		}

	} );


//-( LiteboxImage )-------------------------------------------------------------

/**
 *	Litebox an image by URI. Blanks screen and displays loading bar; dismisses
 *	image on click.
 *
 *	@class		LiteboxImage
 *	@extends	Litebox
 */
 
/* class */ function LiteboxImage( imgURI ) /* extends Litebox */ {
	Litebox.apply( this, [] );

	this._imgURI		= imgURI;
	this._image	 		= new Image( );
	
	this.setCanvas( document.createElement( 'div' ) );
	this.getCanvas( ).className = 'liteboxCore loading';
	this.show( );

	/**
	 *	@browser Safari
	 *	The onload() handler may be called *immediately* once the source is set
	 *	(e.g, if the image data has already been loaded), so set it the handler 
	 *	before allowing the image to load.
	 */
	this._image.onload	= bind( this, 'reveal' );
	this._image.onerror = bind( this, 'imgError' );
	this._image.src 	= this._imgURI;
	}

extend( LiteboxImage.prototype, Litebox.prototype );
extend( LiteboxImage.prototype, {
 	constructor			: 	LiteboxImage
,	_imgURI				:	null
,	_progressBar		:	null
,	_image				:	null
,	_imageNode			:	null
,	reveal				:	function( ) {
		this.getCanvas( ).appendChild( 
			this._imageNode = document.createElement( 'img' )
			);
        
        this._imageNode.style.visibility    = 'hidden';
        this._imageNode.src                 = this._image.src;
        
		this.getCanvas( ).className		    = 'liteboxCore';
		this.getCanvas( ).style.width	    = this._image.width  + 'px';
		this.getCanvas( ).style.height	    = this._image.height + 'px';
		
        this.getCanvas( ).style.visibility  = 'hidden';
        
        this.updateCanvasPosition( );
//		LiteboxController.update( );
		
		this._imageNode.style.visibility    = 'visible';
        this.getCanvas( ).style.visibility  = 'visible';
		}
,	imgError			: function( ) {
		this.error( 'Image not found!<hr>'+this._imgURI );
		}
,	error				: function( msg ) {
		this.setCanvas( document.createElement( 'div' ) );
		this.getCanvas( ).className = 'liteboxMessage';
		this.getCanvas( ).innerHTML = msg;
		
		this.updateCanvasPosition( );
		this.uncloakCanvas( );
		}
	} );


//-( LiteboxController )--------------------------------------------------------

/**
 *	LiteboxController is responsible for keeping Liteboxes properly positioned
 *	when responding to scroll and resize events.
 *	
 *	@class	LiteboxController
 */

/* class */ function LiteboxControllerClass( ) {

	this._stack		= [];
	this._textareas	= [];
	this._flash		= [];

	}

extend( LiteboxControllerClass.prototype, {

	_stack				: null
,	_textareas			: null
,	_flash				: null

,	update				: function( ) {
		var box = this.getFrontLitebox( );
		if( box ) {
			if( !box.getScrollLock( ) ) {
				box.updateCanvasPosition( );
				}
			}
		}

,	getFrontLitebox	: function( ) {
		if( this._stack.length ) {
			return this._stack[ this._stack.length - 1 ];
			}
		return null;
		}

,	push				: function( box ) {
		if( this.getFrontLitebox( ) ) {
			this.getFrontLitebox( ).makeHidden( );
			}
		else {
			
			/**
			 *	@browser Firefox
			 *	Firefox shows textarea scrollbars through the litebox. This
			 *	isn't so awesome. We also can't "visibility: hidden" them, 
			 *	because Firefox hides the textareas while still showing the
			 *	scollbars. Instead, we swap out the value.
			 *
			 *	Note that this probably won't work if there are textareas
			 *	in the Litebox, or if the document textareas have onchange
			 *	handlers, etc.; a pure-CSS solution would probably be better.
			 */
			var textareas = document.getElementsByTagName( 'textarea' );
			for( var ii = 0; ii < textareas.length; ii++ ) {
				var t = textareas[ ii ];
//				t._oldValue = t.value
//				t.value = '';
				t.style.overflow = 'hidden';
				this._textareas.push( t );
				}
			
			if( isset( 'flashUpshift' ) ) {
				var hp;
				for( var k in flashUpshift ) {
					hp = getObj( flashUpshift[ k ][ 0 ] )
					if( hp ) {
						hp.style.visibility = 'hidden';
						this._flash.push( hp );
						}
					}
				}
			}
		this._stack.push( box );
		}

,	pop					: function( box ) {
		if( this._stack.length ) {
			box = this._stack.pop( );
			if( this.getFrontLitebox( ) ) {
				this.getFrontLitebox( ).makeVisible( );
				}
			else {
				/**
				 *	@browser Firefox
				 *	See push().
				 */
				for( var ii = 0; ii < this._textareas.length; ii++ ) {
//					this._textareas[ ii ].value
//						= this._textareas[ ii ]._oldValue;
					this._textareas[ ii ].style.overflow = 'auto';
					}
				this._textareas = [];
				
				for( var ii = 0; ii < this._flash.length; ii++ ) {
					this._flash[ ii ].style.visibility = 'visible';
					}
				this._flash = [];
				}
			return box;
			}
		}

,	clear				: function( ) {
		if( this._stack.length ) {
			while( box = this.getFrontLitebox( ) ) {
				box.dispose( );
				}
			}
		}
	
	} );
	
LiteboxController = new LiteboxControllerClass( );

window.onscroll = chainHandlers(
	 window.onscroll
	,bind( LiteboxController, 'update' )
	);

window.onresize = chainHandlers(
	 window.onresize
	,bind( LiteboxController, 'update' )
	);
