//
//  Configuration
//
modalWindowOptions = Object.extend({
    //fileLoadingImage: '../images/image-loader.gif',
    fileLoadingImage: 'circle-loader-white.gif',
    fileCloseX: 	  'closex.png',

    overlayOpacity: 0.6,   // controls transparency of shadow overlay
    resizeSpeed: 7         // controls the speed of the image resizing animations (1=slowest and 10=fastest)
}, window.modalWindowOptions || {});
/*
var modalWindowGlobals = {

	imgCloseX: $(document.createElement('img'));
	imgLoadingImage: $(document.createElement('img'));

}
*/

// -----------------------------------------------------------------------------------

// Helper function
var	windowSize = function() {
	
     var xScroll, yScroll;
	
	if (window.innerHeight && window.scrollMaxY) {	
		xScroll = window.innerWidth + window.scrollMaxX;
		yScroll = window.innerHeight + window.scrollMaxY;
	} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}
	
	var windowWidth, windowHeight;
	
	if (self.innerHeight) {	// all except Explorer
		if(document.documentElement.clientWidth){
			windowWidth = document.documentElement.clientWidth; 
		} else {
			windowWidth = self.innerWidth;
		}
		windowHeight = self.innerHeight;
	} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
		windowWidth = document.documentElement.clientWidth;
		windowHeight = document.documentElement.clientHeight;
	} else if (document.body) { // other Explorers
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}	
	
	// for small pages with total height less then height of the viewport
	pageHeight = Math.max( yScroll, windowHeight );

	// for small pages with total width less then width of the viewport
	pageWidth = Math.max( xScroll, windowWidth );

	 	// returns correct dimensions for window, had issues with prototype's sometimes. this was ganked from apple.
	var viewWidth  = window.innerWidth  || (window.document.documentElement.clientWidth  || window.document.body.clientWidth);
	var viewHeight = window.innerHeight || (window.document.documentElement.clientHeight || window.document.body.clientHeight);
	var x          = window.pageXOffset || (window.document.documentElement.scrollLeft   || window.document.body.scrollLeft);
	var y          = window.pageYOffset || (window.document.documentElement.scrollTop    || window.document.body.scrollTop);
	
	return {
			 'viewWidth':  viewWidth,
			 'viewHeight': viewHeight,
			 'pageWidth':  pageWidth,
			 'pageHeight': pageHeight,
			 'x':      x,
			 'y':      y
		   }
	
}

// -----------------------------------------------------------------------------------

var modalWindow = Class.create({

	onPrerender:  null,
	onShow:       null,
	imgLoading:   null,
	imgCloseX:    null,
	overlay:      null,
	isActive:     false,
	isOpen:       false,
	divContainer: null,
	divContent:   null,
	width: 0,
	height: 0,
	isReadyToRender: false,
    
    // Constructor
    initialize: function( handle, options ) {
    	var that = this;
    
    	// Preload loading image and close X
    	this.imgLoading = Mekin.Resource.createImageRel(
    		modalWindowOptions.fileLoadingImage,
    		{position: 'absolute'},
    		{hide: true, preload: false}
    	);
    	this.imgCloseX  = Mekin.Resource.createImageRel(
    		modalWindowOptions.fileCloseX,
    		{
    			position: 'absolute',
				right: '-16px',
				top:   '-16px',
				cursor: 'pointer',
				zIndex: 1001
    		}, {hide: true, preload: false});
		
		Event.observe( this.imgCloseX, 'click', function(e){
			that.hide();
		});
    	    
    	options = Object.extend({
    	
    		width:   640,
    		height:  480,
    		onPrerender: null
    	
    	}, options || {} );
        
    	this.width  = options.width;
    	this.height = options.height;
    	this.onPrerender = options.onPrerender;
    	this.onShow = options.onShow;

		this.divContent = $(document.createElement('div'));
		this.divContent.setStyle({
			position: 'absolute',
			left:     0,
			top:      0,
			width:    '100%',
			height:   '100%',
			/*overflow: 'hidden',*/
			opacity: 0
		});

		//this.divContent.hide();
    	
    	// Fire initialization callback (preload images, etc)
    	if (options.onInitialize)
    	{
    		options.onInitialize.call(this);
    	}
        
		//
		// Set up transparent overlay
		//
		this.overlay = $(document.createElement('div'));
		this.overlay.setStyle({
			background: 'black',
			position:   'absolute',
			left:       '0px',
			top:        '0px',
			zIndex:     999
		});
		this.overlay.hide();
		
		// Hide when we click off the main div
		this.overlay.observe( 'click', function(e) {
			that.hide();
		});
		// ESC key closes too
		Event.observe( window, 'keyup', function(e)
		{
			if ( that.isOpen && !that.isActive && e.which == 27 )
			{
				that.hide();
			}
		});
		
		//
		// Create the container
		//
		this.divContainer = $(document.createElement('div'));
		this.divContainer.hide();
		this.divContainer.setStyle({
			background: 'white',
			position:   'absolute',
			border:     '1px solid black',
			zIndex:     1000
		});
		this.divContainer.appendChild( this.divContent );
		this.divContainer.appendChild( this.imgLoading );
		this.divContainer.appendChild( this.imgCloseX  );
		
		// Add to the body
		//DoOrWaitForLoad( function(){
			var body = window.document.body;
			body.appendChild( that.overlay );
			body.appendChild( that.divContainer );
    	//});
    	
    	// Make dom handle clickable
    	if (handle)
    	{
	    	Event.observe( handle, (options.dblClick?'dbl':'') + 'click', function(e)
	    	{
	    		that.show( this );
	    	});
	    	
	    	// Give the handle a pointer
	    	$(handle).setStyle({cursor:'pointer'});
	    }
	    
    },
    
	getDivPlacement: function( startX, startY, width, height ) {
	
		// where to place the div?
		
		// Get some info first
		var dims               = windowSize();
		var yOffset            = document.viewport.getScrollOffsets()[1];
		var xOffset            = document.viewport.getScrollOffsets()[0];
		
		// ensure that newTop is at least 0 so it doesn't hide close button
		this.top             = Math.max( (dims.viewHeight - height) * 0.5 + yOffset, 0 );
		this.left            = Math.max( (dims.viewWidth  - width ) * 0.5 + xOffset, 0 );
		
		return {
				 'x': -(startX - this.left),
				 'y': -(startY - this.top)
			   }
	
	},

	// Open a box, fire callbacks, get ready to show content
    show: function( )
    {
    	if (this.onShow) {
    		this.onShow.call(this);
    	}
    	
    	this.isReadyToRender = false;
    
    	var that = this;
    	
    	this.isActive = true;
    	this.isOpen   = false;
    	
		var dims = windowSize();
		this.overlay.setStyle( {width: '100%', height: dims.pageHeight + 'px' } );
		
		// Start state
		var startWidth  = this.width  * 0.1;
		var startHeight = this.height * 0.1;
		var startLeft   = (dims.viewWidth  - startWidth  ) * 0.5;
		var startTop    = (dims.viewHeight - startHeight ) * 0.5;
		
		this.divContainer.setStyle({
			left:   startLeft   + 'px',
			top:    startTop    + 'px',
			width:  startWidth  + 'px',
			height: startHeight + 'px'
		});
		
		var placement = this.getDivPlacement( startLeft, startTop, this.width, this.height );

    	// Display box
		new Effect.Parallel([
		
			// Fade out the background
			new Effect.Appear( that.overlay, { to: modalWindowOptions.overlayOpacity, sync: true } ),
			
			// Fade in the containing div
			new Effect.Appear( that.divContainer, { sync: true } ),
			
			// 'Unroll' the box
			new Effect.Move( that.divContainer, { x: placement.x, y: placement.y, sync: true } ),
			
			// Stretch to proper dimensions
			new Effect.Morph( that.divContainer, {
				style: { width: that.width + 'px', height: that.height + 'px' },
				sync: true,
				afterFinish: function(effect) {
					Mekin.Effects.appear( that.imgCloseX, { duration: 0.2 } );
					that.isReadyToRender = true;
					if (that.onPrerender)
					{
						if (that.onPrerender.call(that) == true)
						{
							that.render();
						}
						else
						// Not yet ready
						{
							// Show loading thingy
							that.imgLoading.setStyle({
								left: (that.width  - that.imgLoading.width ) * 0.5 + 'px',
								top:  (that.height - that.imgLoading.height) * 0.5 + 'px'
							});
							Mekin.Effects.appear( that.imgLoading, {to:.7} );
						}
					}
					else
					{
						that.render();
					}
				}
			})
		], { duration: 0.5 } );

    },
    
    resize: function( width, height, options ) {
    
    	var that = this;
    
		var dims = windowSize();
    
		// Start state
		var startWidth  = this.width;
		var startHeight = this.height;
		var startLeft   = this.divContainer.offsetLeft;
		var startTop    = this.divContainer.offsetTop;
		
		// set new width/height
		this.width  = width;
		this.height = height;
		
		// Get new placement based on this data
		var placement = this.getDivPlacement( startLeft, startTop, this.width, this.height );
    
    	// Perform resize
		new Effect.Parallel([
    
			// 'Unroll' the box
			new Effect.Move( that.divContainer, { x: placement.x, y: placement.y, sync: true } ),
			
			// Stretch to proper dimensions
			new Effect.Morph( that.divContainer, {
				style: { width: that.width + 'px', height: that.height + 'px' },
				sync: true,
				afterFinish: function(effect) {
					if (options && options.afterFinish) {
						options.afterFinish();
					}
				}
			})
		], {duration: .3} );
    },
    
    // Show content
    render: function()
    {
    	// Possible to call render anytime; be sure we're ready to render
    	if (this.isReadyToRender != true) {
    		return;
    	}
    	var that = this;
    	
    	// Hide the loader
    	this.imgLoading.hide();
    	
    	// Show the content somehow
    	new Effect.Appear( this.divContent, {
	    	duration: .3,
	    	afterFinish: function() {
	    		that.isOpen = true;
	    		that.isActive = false;
	    	}
	    });
    },
    
    // Restore main page
    hide: function()
    {
    	this.isReadyToRender = false;
    	
    	var that = this;
    	this.isActive = true;
    	
    	new Effect.Parallel([
    		
    		new Effect.Fade( this.divContainer, {sync: true} ),
    		
    		new Effect.Fade( this.overlay, {sync: true} ),
    		
    		new Effect.Fade( this.imgCloseX, {sync: true} )
    	
    	], {
    		duration: .3,
    		afterFinish: function() {
    			that.imgCloseX.hide();
    			that.divContent.hide();
    			that.isOpen = false;
    			that.isActive = false;
    		}
    	});
    }
});