/* =====================================================================================

Canvas-based Modal class by Philip Hutchison, March 2009 (http://pipwerks.com).

Copyright (c) 2009 Philip Hutchison
MIT-style license. Full license text can be found at 
http://www.opensource.org/licenses/mit-license.php

Requires MooTools 1.2
Internet Explorer requires excanvas.js since it doesn't natively handle <canvas>

======================================================================================== */


var Modal = new Class({

	Implements: [Options],

	//These are defaults that can be overridden later.
	options: {
		title: "",
		html: "",
		padding: 12,
		font: {
			title: {
				size: "small",
				face: "Verdana, Geneva",
				weight: "bold",
				color: "#333"
			},
			content: {
				size: "small",
				face: "inherit",
				weight: "inherit",
				color: "#333"
			}
		},
		width: 350,
		height: 200,
		shadowSize: 6,
		titlebarHeight: 28,
		edgeMargin: 1,
		opacity: 0.66,
		colors: {
			modalBackground: "#000",
			windowBackground: "#AAA",
			windowTitleBar: { top: "#F5F5F5", bottom: "#AAA" },
			contentBackground: "#F8F8F8",
			closeButton: {
				fill: { top: "#F69", bottom: "#F33" },				
				centerline: { top: "#C00", bottom: "#C33" },
				outline: { top: "#666", bottom: "#DDD" }
			}
		},
		windowRadius: { topLeft: 9, topRight: 9, bottomLeft: 3, bottomRight: 3 },
		closeButton: true,
		backgroundClickDismissesModal: true,
		animate: true,
		showTitleBar: true
	},
	
	elements: { wrapper: null, container: null,	canvas: null, modalBackground: null, textWrapper: null, title: null, maincontent: null },
	
	originalCSS: {
		html: { height: null, overflow: null },
		docBody: { height: null, overflow: null }
	},
	
	initialize: function(options){
		window.scrollTo(0,0);
		
		if($type(options.windowRadius) === "number" || $type(options.windowRadius) === "string"){
			var num = options.windowRadius;
			options.windowRadius = { topLeft: num, topRight: num, bottomLeft: num, bottomRight: num }
		}
		
		this.setOptions(options);
		
		var that = this, //for private members
			opt = that.options,
			adjustedWidth = opt.width + (opt.shadowSize * 2),
			adjustedHeight = opt.height + (opt.shadowSize * 2),
			content_h = opt.height - (opt.edgeMargin * 2),
			content_y = opt.shadowSize + opt.edgeMargin,
			content_text_h = opt.height - (opt.edgeMargin * 2) - (opt.padding * 2);
		
		if(opt.showTitleBar){
			content_h = opt.height - opt.edgeMargin - opt.titlebarHeight;
			content_y = opt.shadowSize + opt.titlebarHeight;
			content_text_h = opt.height - opt.edgeMargin - (opt.padding * 2) - opt.titlebarHeight - 1; //the -1 is for top border
		}

		//If another modal window is created before this one is removed, queuing it
		if($("modalWindowWrapper")){
			window.modalQueue = window.modalQueue || [];
			window.modalQueue[window.modalQueue.length] = options;
			return;
		}
		
		var modalBackgroundClickHandler = function (e){
			e.stop();
			if(opt.backgroundClickDismissesModal){
				that.close();
			}
		};

		var closeButtonClickHandler = function (e){
			e.stop();
			that.close();
		};
		
		var closeWindow = function (){
			
			//Destroy modal window
			$("modalWindowContainer").destroy();
			
			//var restore = restorePage;
			
			//If there's a queue, launch next window
			if(window.modalQueue && window.modalQueue.length > 0){
				
				$("modalWindowWrapper").destroy();
				new Modal(window.modalQueue[0]);
				window.modalQueue.splice(0,1); //reorder queue
			
			} else {
				
				if(opt.animate){
					//Fade out background then destroy
					var myEffect = new Fx.Morph('modalWindowWrapper', { duration: 250, onComplete: restorePage }).start({'opacity': 0});
				} else {
					//Destroy with no fade
					restorePage();
				}
				
			}	
		}.bind(this);
		
		var prepBodyStyles = function (){
			
			var html = $$("html")[0];
			var docBody = $(document.body);
			
			that.originalCSS.html.height = html.style.height;
			that.originalCSS.html.overflow = html.style.overflow;
			that.originalCSS.docBody.height = docBody.style.height;
			that.originalCSS.docBody.overflow = docBody.style.overflow;
			
			html.setStyles({ height: "100%", overflow: "hidden" });
			docBody.setStyles({ height: "100%", overflow: "hidden" });
			
		};

		var restorePage = function (){
			
			$(document.body).setStyles({
				height: that.originalCSS.docBody.height,
				overflow: that.originalCSS.docBody.overflow
			});
			
			$$("html")[0].setStyles({
				height: that.originalCSS.html.height,
				overflow: that.originalCSS.html.overflow
			});
			
			$("modalWindowWrapper").destroy();
			
		};

		var generate_wrapper = function (){
			return new Element("div", {
				id: "modalWindowWrapper",
				styles: {
					width: "100%",
					height: "100%",
					position: "absolute",
					"z-index": 9000,
					top: 0,
					left: 0
				}
			}).inject(document.body);
		};
		
		var generate_modalBackground = function (){
			return new Element("div", {
				id: "modalWindowBackground",
				styles: {
					width: "100%",
					height: "100%",
					background: opt.colors.modalBackground,
					opacity: opt.opacity
				},
				events: {
					click: modalBackgroundClickHandler.bind(that)
				}
			}).inject(that.elements.wrapper);			
		};
	
		var generate_container = function (){
			var w = adjustedWidth,
				h = adjustedHeight;
			return new Element("div", {
				id: "modalWindowContainer",
				styles: {
					width: w,
					height: h,
					position: "absolute",
					"z-index": 9001,
					left: "50%",
					top: "50%",
					"margin-left": "-" +w/2 +"px",
					"margin-top": "-" +h/2 +"px"
				}
			}).inject(document.body);
		};
	
		var generate_canvas = function (){	
			var canvas = $("modalWindowCanvas");
			if(!canvas){
				var w = adjustedWidth,
					h = adjustedHeight;
				var usesVML = (typeof window.G_vmlCanvasManager !== "undefined");
				canvas = new Element("canvas", {
					id: "modalWindowCanvas",
					width: w,
					height: h,
					styles: {
						position: "absolute",
						"z-index": 9002,
						left: "50%",
						top: "50%",
						"margin-left": "-" +w/2 +"px",
						"margin-top": "-" +h/2 +"px"
					}
				}).inject(that.elements.container);
				
				//IE uses VML not Canvas
				if(usesVML) { canvas = window.G_vmlCanvasManager.initElement(canvas); }
		
				// Make sure we don't execute when canvas isn't supported
				if(!canvas || !canvas.getContext){ 
					alert("Canvas not supported.\ncanvas.getContext: " +canvas.getContext);
					return false;
				}
			}
			return canvas;
		};
	
		//Creates the drop-shadow that appears under the modal window
		var generate_dropShadow = function (){
			var width = adjustedWidth,
				height = adjustedHeight,
				radius = opt.windowRadius;
			var opacity_steps = 1 / opt.shadowSize;
			//Blur is not yet available in canvas. 
			//Workaround is to create drop-shadow 'onion-style'
			for (var x = 0; x < opt.shadowSize; x++){
				var opacity = Math.round((opacity_steps * (x/6)) * 100) /100;
				new Rectangle({
					canvas: that.elements.canvas,
					width: width - (x * 2),
					height: height - (x * 2),
					x: x,
					y: x,
					radius: {
						topLeft: radius.topLeft + x,
						topRight: radius.topRight + x,
						bottomLeft: radius.bottomLeft + x,
						bottomRight: radius.bottomRight + x
					},
					fill: "rgba(50, 50, 50, " +opacity +")"			
				});
			}			
		};
	
		var generate_windowElements = function (){
		
			if(!that.elements.canvas){ return false; }
			
			//Shadow
			generate_dropShadow();
			
			//Window background
			new Rectangle({
				canvas: that.elements.canvas,
				width: opt.width,
				height: opt.height,
				x: opt.shadowSize,
				y: opt.shadowSize,
				radius: opt.windowRadius,
				fill: opt.colors.windowBackground
			});
						
			if(opt.showTitleBar){
								
				//Window title area
				new Rectangle({
					canvas: that.elements.canvas,
					width: opt.width,
					height: opt.titlebarHeight,
					x: opt.shadowSize,
					y: opt.shadowSize,
					radius: {
						topLeft: opt.windowRadius.topLeft,
						topRight: opt.windowRadius.topRight
					},
					fill: {
						start_x: 0,	start_y: 0,	end_x: 0, end_y: opt.titlebarHeight,
						stops: [
							{ position: 0, color: opt.colors.windowTitleBar.top },
							{ position: 1, color: opt.colors.windowTitleBar.bottom }
						]
					}
				});
								
			}
	
			//Content background
			new Rectangle({
				canvas: that.elements.canvas,
				width: opt.width - (opt.edgeMargin * 2),
				height: content_h,
				x: opt.shadowSize + opt.edgeMargin,
				y: content_y,
				radius: {
					topLeft: (opt.showTitleBar) ? 0 : opt.windowRadius.topLeft,
					topRight: (opt.showTitleBar) ? 0 : opt.windowRadius.topRight,
					bottomLeft: opt.windowRadius.bottomLeft,
					bottomRight: opt.windowRadius.bottomRight
				},
				fill: opt.colors.contentBackground
			});
			
			if(opt.showTitleBar && opt.closeButton){
				
				var btnSize = opt.titlebarHeight - 10;
				var btnMargin = (opt.titlebarHeight - btnSize) /2;
												
				//Button outline
				new Rectangle({
					canvas: that.elements.canvas,
					width: btnSize,
					height: btnSize,
					x: opt.width + opt.shadowSize - btnSize - btnMargin,
					y: opt.shadowSize + btnMargin,
					radius: btnSize/2 + 2,
					fill: {
						start_x: 0,
						start_y: opt.shadowSize + btnMargin,	
						end_x: 0, 
						end_y: opt.shadowSize + btnMargin + btnSize,
						stops: [
							{ position: 0, color: opt.colors.closeButton.outline.top },
							{ position: 1, color: opt.colors.closeButton.outline.bottom }
						]
					}
				});

				//Button center line
				new Rectangle({
					canvas: that.elements.canvas,
					width: btnSize -2,
					height: btnSize -2,
					x: opt.width + opt.shadowSize - btnSize - btnMargin + 1,
					y: opt.shadowSize + btnMargin + 1,
					radius: btnSize/2 + 1,
					fill: {
						start_x: 0,
						start_y: opt.shadowSize + btnMargin + 1 - 2,
						end_x: 0, 
						end_y: opt.shadowSize + btnMargin + 1 + btnSize - 2,
						stops: [
							{ position: 0, color: opt.colors.closeButton.centerline.top },
							{ position: 1, color: opt.colors.closeButton.centerline.bottom }
						]
					}
				});
				
				//Button main
				new Rectangle({
					canvas: that.elements.canvas,
					width: btnSize -4,
					height: btnSize -4,
					x: opt.width + opt.shadowSize - btnSize - btnMargin +2,
					y: opt.shadowSize + btnMargin +2,
					radius: btnSize/2,
					fill: {
						start_x: 0, 
						start_y: opt.shadowSize + btnMargin +2, 
						end_x: 0,
						end_y: opt.shadowSize + btnMargin + 2 + btnSize - 4,
						stops: [
							{ position: 0, color: opt.colors.closeButton.fill.top },
							{ position: 1, color: opt.colors.closeButton.fill.bottom }
						]
					}
				});
				
			}
		};
	
		var generate_textWrapper = function (){		
			var w = opt.width,
				h = opt.height;
			return new Element("div", {
				id: "modalWindowTextWrapper",
				styles: {
					position: "absolute",
					"z-index": 9003,
					left: "50%",
					top: "50%",
					width: w,
					height: h,
					"margin-left": "-" +w/2 +"px",
					"margin-top": "-" +h/2 +"px"
				}
			}).inject(that.elements.container);
		};
				
		var generate_title = function (){
			var width = opt.width - 6;
			if(opt.closeButton){
				width = opt.width - opt.titlebarHeight - 10;
			}
			return new Element("h1", {
				id: "modalWindowTitle",
				html: opt.title,
				styles: {
					width: width,
					height: opt.titlebarHeight,
					"line-height": opt.titlebarHeight,
					display: "block",
					margin: "0 0 0 6px",
					padding: 0,
					border: "none",
					"font-size": opt.font.title.size,
					"font-family": opt.font.title.face,
					//"font-weight": opt.font.title.weight,
					color: opt.font.title.color,
					overflow: "hidden"
				}
			}).inject(that.elements.textWrapper);		
		};
		
		var generate_closeButton_a = function (){
			var btnSize = opt.titlebarHeight - 10;
			var btnMargin = (opt.titlebarHeight - btnSize) /2;
			return new Element("a", {
				id: "modalWindowCloseBtn",
				href: "#",
				styles: {
					width: btnSize,
					height: btnSize,
					display: "block",
					position: "absolute",
					"z-index": 9005,
					right: btnMargin,
					top: btnMargin,
					border: "none",
					outline: "none",
					margin: 0,
					padding: 0
				},
				events: { click: closeButtonClickHandler.bind(that) }
			}).inject(that.elements.textWrapper);		
		};
				
		var generate_maincontent_div = function (){
			return new Element("div", {
				id: "modalWindowContent",
				html: opt.html,
				styles: {
					width: opt.width - (opt.edgeMargin * 2) - (opt.padding * 2),
					height: content_text_h, 
					display: "block",
					"margin-left": opt.edgeMargin,
					"margin-top": (opt.showTitleBar) ? 0 : opt.edgeMargin +"px",
					padding: opt.padding + "px",
					"font-size": opt.font.content.size,
					"font-family": opt.font.content.face,
					//"font-weight": opt.font.content.weight,
					color: opt.font.content.color,
					overflow: "auto",
					"border-top": (opt.showTitleBar) ? "1px solid #777" : "none"
				}
			}).inject(that.elements.textWrapper);
		};

		this.close = closeWindow;

		//Set wrapper and modal background
		this.elements.wrapper = generate_wrapper();

		this.elements.modalBackground = generate_modalBackground();
		prepBodyStyles();
		
		//Create container to hold canvas and text elements
		this.elements.container = generate_container();
		
		// ----- Create canvas -----		
		this.elements.canvas = generate_canvas();
		if(!this.elements.canvas){ return false; }	
		
		// ----- Create window elements in canvas -----
		generate_windowElements();
		
		// ----- Create text overlays -----
		this.elements.textWrapper = generate_textWrapper();
		
		if(opt.showTitleBar){
			generate_title();
		}
		
		if(opt.showTitleBar && opt.closeButton){
			generate_closeButton_a();
		}
		generate_maincontent_div();

	}

});