/***********************************************************************/
/* LEMOOPOPUP.JS : LE MOO POPUP!                                       */
/* COPYRIGHT 2010 SPINNAKER 360 PTE LTD ALL RIGHTS RESERVED            */
/* THIS SCRIPT MAY NOT BE REPRODUCED OR DISTRIBUTED WITHOUT PERMISSION */
/***********************************************************************/
//**** [DEPENDENCY] ****//
// MOOTOOLS CORE 1.2

//**** [COMPATIBILITY] ****//
// IE - 6+
// FF - 3.X+
// OPERA - 10 ??
// CHROME - 4.X+ ??
// SAFARI - 3+

//**** [OPTIONS] ****//
// defaultWidth, defaultHeight (int) : default dimensions when popup is still show loader
// width, height (int) : fixed dimensions for popup (@!@#!@ FOR IE6, IE7)
// smokeScreenOpacity (float) : smoke screen opacity when activated
// transitDuration (int) : transit duration for animations
// transitAnimate (object) : Mootools animation to use
// mode ("text" or "ajax") : where to draw data from
// data : if mode is text - text to be displayed. if ajax - page to draw data from
// param : ajax mode only - data parameters
// autoHeader : auto attach header to popup?
// header : header html
// loadMessage : message to show while popup is loading

/**** [DIRECT DOM MANIPULATION?] ****
|-this.smokeScreen
|-this.wrapper
	|-this.contentsWrapper
		|-this.wrapperTop
		|-this.contents
		|-this.wrapperBottom
|-this.tempHolder
*************************************/

// (I) AUTO CREATE LeMoo OBJECT ON DOMREADY
// CALL POPUP FOR POPUPS
var popup = null;
window.addEvent("domready", function(){
	popup = new LeMooPopup();
});

// (II) THE CLASS ITSELF
var LeMooPopup = new Class({
	Implements:[Options, Chain],
	options:{
		defaultWidth:200, defaultHeight:50,
		width:Number.NaN, height:Number.NaN, smokeScreenOpacity:0.6,
		transitDuration:200, transitAnimate:Fx.Transitions.Sine.easeOut,
		mode:"text", data:null, param:null,
		autoHeader:false, header:null,
		loadMessage:"<img src='images/spinnerSmall.gif' /> Loading..."
	},

	initialize:function(options){
	// initialize() : setup the popup
		// (0) TARGET ON ESCAPE KEY
		this.onEscapeTarget = Browser.isIE ? document.body : document;

		// (1) SETUP SMOKE SCREEN
		this.smokeScreen = new Element("div", { id:"LMP_smokescreen" });
		// IE6 fix - CC is more reliable
		/*@cc_on
			@if(@_jscript_version<=5.6)
			this.smokeScreen.addClass("ie6");
			@end
		@*/

		this.smokeScreen.fade("hide");
		this.smokeScreen.injectBottom(document.body);

		// (2) SETUP CONTENTS WRAPPER
		this.wrapper = new Element("div", { id:"LMP_wrapper" });
			this.contentsWrapper = new Element("div", { id:"LMP_contentsWrapper" });
			this.contentsWrapper.injectBottom(this.wrapper);
				this.wrapperTop = new Element("div", { id:"LMP_wrapperTop" });
				this.contents = new Element("div", { id:"LMP_contents" });
				this.wrapperBottom = new Element("div", { id:"LMP_wrapperBottom" });

				this.wrapperTop.set("html", "<table class='fullflat'><tr><td id='LMP_wrapperTopLeft'></td><td id='LMP_wrapperTopCenter'>&nbsp;</td><td id='LMP_wrapperTopRight'></td></tr></table>");
				this.wrapperBottom.set("html", "<table class='fullflat'><tr><td id='LMP_wrapperBottomLeft'></td><td id='LMP_wrapperBottomCenter'>&nbsp;</td><td id='LMP_wrapperBottomRight'></td></tr></table>");

				this.wrapperTop.injectBottom(this.contentsWrapper);
				this.contents.injectBottom(this.contentsWrapper);
				this.wrapperBottom.injectBottom(this.contentsWrapper);
		this.wrapper.fade("hide");
		this.wrapper.injectBottom(document.body);

		// (3) SETUP TEMP CONTENTS HOLDER
		this.tempHolder = new Element("div", { id:"LMP_temp" });
		this.tempHolder.injectBottom(document.body);

		// (4) SET FLAG
		this.open = false;
	},

	show:function(width, height){
	// show() : show the popup
	// PARAM width, height : specific popup width / height

		// (1) RESET POPUP
		if(this.open){ this.animateReset(); }
		else{ this.reset(); }

		// (2) SHOW "LOADING" POPUP
		// Smoke screen is in need of constant repairs for IE6
		/*@cc_on
			@if(@_jscript_version<=5.6)
			this.fixSmokeScreen();
			@end
		@*/
		this.smokeScreen.fade(this.options.smokeScreenOpacity);
		this.wrapper.fade(1);

		// (A2) IE6!
		/*@cc_on
			@if(@_jscript_version<=5.6)
			this.killSelect();
			@end
		@*/

		// (3) FETCH THE CONTENT - DUMP IN TEMP CONTENT
		this.setTempContents();

		// (4) SET FINAL DIMENSIONS - IF DEFINED
		if(isFinite(width) && isFinite(height)){
			this.options.width = width;
			this.options.height = height;
		} else {
			this.options.width = Number.NaN;
			this.options.height = Number.NaN;
		}

		// (5) ANIMATE!
		// SLIGHT DELAY TO MAKE SURE INITIAL FADE TRANSITION HAS FINISHED
		this.showTransit.delay(500, this);

		// (6) BIND ESC KEY TO CLOSE
		this.boundOnEscape = this.onEscape.bind(this);
		$(this.onEscapeTarget).addEvent('keydown', this.boundOnEscape);

		// (7) SET FLAG
		this.open = true;
	},

	hide:function(){
	// hide() : hide the popup

		// (1) DEFINE HIDE TRANSITIONS
		ssTransit = new Fx.Morph(this.smokeScreen, {
			duration: this.options.transitDuration
		});
		wrapperTransit = new Fx.Morph(this.wrapper, {
			duration: this.options.transitDuration
		});

		// (2) CHAIN OF HIDE
		ssTransit.start({ opacity: [this.options.smokeScreenOpacity, 0] });
		wrapperTransit.start({ opacity: [1, 0] }).chain(
			function(){
				// (2.1) FULLY HIDE WHEN HIDE TRANSIT IS OVER
				this.contents.set("html", "");
				this.wrapper.setStyle("display", "none");

				// (A2.1) IE6!
				/*@cc_on
					@if(@_jscript_version<=5.6)
					this.resurrectSelect();
					@end
				@*/
				// (2.2) UNBIND ESC KET
				$(this.onEscapeTarget).removeEvent('keydown', this.boundOnEscape);
				delete this.boundOnEscape;

				// (2.3) SET FLAG
				this.open = false;

				// (2.4) FIRE ONHIDE EVENT
				if (typeof this.onHide == "function") {
					this.onHide.bind(this); this.onHide(); this.onHide = null;
				}
			}.bind(this)
		);
	},

	setMode:function(mode, data, param){
	// setMode() : set popup mode

		switch(mode){
			default: case "text":
				this.options.mode = "text";
				this.options.data = data;
				break;

			case "ajax":
				this.options.mode = "ajax";
				this.options.data = data;
				this.options.param = param;
				break;
		}
	},

	reset:function(){
	// reset() : [helper fn] reset the popup to init position / status
	// Since popup is centered horizontally on screen with css - only need to determine vertical center

		// (1) SET LOADING MESSAGE
		this.contents.set("html", this.options.loadMessage);

		// (2) SET STYLES
		this.wrapper.setStyle("display", "block");
		this.contents.setStyles({
			"width":"auto", "height":"auto"
		});
		this.contentsWrapper.setStyles({
			"width":this.options.defaultWidth,
			"height":this.options.defaultHeight
		});

		// (3) CALCULATE PHYSICS
		var pgWrapDimension = $('pageWrapper').getSize();		// Page wrapper dimensions
		var vpDimension = $(window).getSize();					// Viewport dimensions
		var popupDimension = this.contentsWrapper.getSize();	// Popup dimensions

		// New y position, SubsToGo version - assumed to center popup within #pageWrapper
		// BUT - if viewport is smaller, use viewport dimensions
		var htAnchor = pgWrapDimension.y <= vpDimension.y ? pgWrapDimension : vpDimension;
		var newHtPos = parseInt((htAnchor.y - popupDimension.y) / 2);
		// This ensures that popup will not cover fulfillment expiry timer
		newHtPos = newHtPos<50 ? 50 : newHtPos ;

		// (4) SET COORDINATES
		this.contentsWrapper.setStyle("top", newHtPos);
	},

	animateReset:function(){
	// animateReset() : animated reset popup; for already opened popups

		// (1) SET LOADING MESSAGE
		this.contents.set("html", this.options.loadMessage);

		// (2) TRANSITIONS
		var widthTransit = new Fx.Morph(this.contentsWrapper, {
			duration: this.options.transitDuration,
			transition: this.options.transitAnimate
		});
		var heightTransit = new Fx.Morph(this.contents, {
			duration: this.options.transitDuration,
			transition: this.options.transitAnimate
		});

		widthTransit.start({ 'width':this.options.defaultWidth }).chain(
			function(){
				heightTransit.start({ 'height':this.options.defaultHeight });
			}.bind(this)
		);
	},

	setTempContents:function(){
	// setTempContents() : [helper fn] set the contents of the temp contents div

		var tempContent = this.options.autoHeader ? this.options.header : "" ;
		switch(this.options.mode){
			default: case "text":
				if(this.options.data===null){ this.options.data = ""; }
				tempContent += this.options.data;
				this.tempHolder.set("html", tempContent);
				break;

			case "ajax":
				this.options.param = this.options.param===null ? "" : this.options.param ;
				new Request({
					url: this.options.data, async: false,
					onSuccess: function(responseText){
						tempContent += responseText;
						this.tempHolder.set("html", tempContent);
					}.bind(this),
					onFailure: function(){
						tempContent += "An error occured while retrieving content...";
						this.tempHolder.set("html", tempContent);
					}.bind(this)
				}).post(this.options.param);
				break;
		}
		
	},

	showTransit:function(){
	// showTransit() : [helper fn] show popup animation

		// (1) RECALCULATE PHYSICS
		var pgWrapDimension = $('pageWrapper').getSize();				// Page Wrapper dimensions
		var vpDimension = $(window).getSize();							// Viewport dimensions
		var contentDimension = this.contents.getSize();					// Current contents dimensions

		// (1.1) USE FIXED DIMENSIONS IF DEFINED
		var newWidth = 0, newHeight = 0;
		if(isFinite(this.options.width) && isFinite(this.options.height)){
			newWidth = this.options.width;
			newHeight = this.options.height;
		} else {
			var tempDimension = this.tempHolder.getSize();
			newWidth = parseInt(tempDimension.x);
			newHeight = parseInt(tempDimension.y);
		}

		// (1.2) OFFSET DIMENSIONS FOR PADDINGS, MARGINS, BROWSER ENGINE OFFSET...
		// MOD HERE : IMPLEMENT AUTO CALCULATION WHERE POSSIBLE
		newWidth += 30; newHeight += 10;

		// (1.3) CALCULATE NEW Y LOCATION
		// New y position, SubsToGo version - assumed to center popup within #pageWrapper
		// BUT - same as rePosition(), if viewport is smaller, use viewport dimensions
		var htAnchor = pgWrapDimension.y <= vpDimension.y ? pgWrapDimension.y : vpDimension.y;
		var newHtPos = parseInt((htAnchor - newHeight) / 2);
		// This ensures that popup will not cover fulfillment expiry timer
		newHtPos = newHtPos<50 ? 50 : newHtPos ;

		// (2) TRANSITIONS
		var transitPositionEffect = new Fx.Morph(this.contentsWrapper, {
			duration: this.options.transitDuration,
			transition: this.options.transitAnimate
		});
		var widthTransit = new Fx.Morph(this.contentsWrapper, {
			duration: this.options.transitDuration,
			transition: this.options.transitAnimate
		});
		var heightTransit = new Fx.Morph(this.contents, {
			duration: this.options.transitDuration,
			transition: this.options.transitAnimate
		});

		// (2.1) POSITION SHIFT
		transitPositionEffect.start({ "top":newHtPos }).chain(
			function(){
				// (2.2) WIDTH
				widthTransit.start({ 'width':[contentDimension.x,newWidth] }).chain(
					function(){
						// (2.3) HEIGHT
						heightTransit.start({ 'height':[contentDimension.y,newHeight] }).chain(
							function(){
								// (2.4) SET CONTENTS
								this.contents.set("html",this.tempHolder.get("html"));

								// (2.5) CLEAR TEMP HOLDER
								this.tempHolder.set("html", "");
								/*@cc_on
								@if(@_jscript_version<=5.6)
								this.fixSmokeScreen();
								@end
							@*/

								// (2.6) FIRE ONSHOW EVENT
								if(typeof this.onShow == "function"){
									this.onShow.bind(this); this.onShow(); this.onShow = null;
								}
							}.bind(this)
						);
					}.bind(this)
				);
			}.bind(this)
		);
	},

	fixSmokeScreen:function(){
	// fixSmokeScreen() : IE6 ONLY - THE BEST OF THE BEST! fix the smoke screen after showing popup
	// IE6 part of smoke screen gets "chopped off" after setting contents

		// (1) CALCULATE PHYSICS
		var pgWrapDimension = $('pageWrapper').getSize();				// Page Wrapper dimensions
		var vpDimension = $(window).getSize();							// Viewport dimensions
		// Use page wrapper or viewport height, whichever is more
		var newHeight = pgWrapDimension.y >= vpDimension.y ? pgWrapDimension.y : vpDimension.y ;

		// (2) RENEW SMOKE
		this.smokeScreen.setStyle("height",newHeight);
	},

	onEscape: function(ev){
	// onEscape() : ON ESCAPE KEY PRESS
		if(ev.key == 'esc'){ this.hide(); }
	},

	killSelect: function(){
	// killSelect() : IE6 ONLY - THE BESTEST! Hide all <select> on show - prevent messed up z-indexing

		var allSelect = $$('select');
		if(allSelect!==undefined && allSelect!==null && allSelect!=""){
			allSelect.each(function(el){
				el.setStyle("display", "none");
			});
		}
	},

	resurrectSelect: function(){
	// resurrectSelect() : IE6 ONLY - Unhide all <select> tags on hide

		var allSelect = $$('select');
		if(allSelect!==undefined && allSelect!==null && allSelect!=""){
			allSelect.each(function(el){
				el.setStyle("display", "block");
			});
		}
	}
});