(function($) {

 	//these globals are required by the simplemodal code
	var ie6 = $.browser.msie && parseInt($.browser.version) === 6 && typeof window['XMLHttpRequest'] !== 'object',
	ie7 = $.browser.msie && parseInt($.browser.version) === 7,
	ieQuirks = null,
	w = [],
	htmlScroll = null;
	
	//selectively override the default simplemodal methods to achieve our own functionality
	
    var haModal = {
		
		/*
		 * Extended SimpleModal options
		 *
		 * pie:				(Boolean:true) Apply CSS3 PIE (PIE_uncompressed.js is required) to specified DOM elements (see pieElems)
		 * pieElems:		(String:'#modal-content,#modal-title') The DOM element(s) selectors for which to apply PIE to
		 */
		 
		defaults: {
			pie:true,
			focus: false,
			modal:false,
			buttonClass:'gtb green'
		},

        impl: {
        
        	/*
			 * Initialize the modal dialog
			 */
        	init: function (data, options) {
        		
        		htmlScroll = $('html').css('overflow-y');
        		if(htmlScroll == 'scroll') {
        			$('html').css('overflow-y','hidden')
        		}
        			
				var s = this;

				// don't allow multiple calls
				if (s.d.data) {
					return false;
				}
	
				// $.boxModel is undefined if checked earlier
				ieQuirks = $.browser.msie && !$.boxModel;
	
				// merge defaults and user options
				s.o = $.extend({}, $.modal.defaults, options);
	
				// keep track of z-index
				s.zIndex = s.o.zIndex;
	
				// set the onClose callback flag
				s.occb = false;
	
				// determine how to handle the data based on its type
				if (typeof data === 'object') {
					// convert DOM object to a jQuery object
					data = data instanceof jQuery ? data : $(data);
					s.d.placeholder = false;
	
					// if the object came from the DOM, keep track of its parent
					if (data.parent().parent().size() > 0) {
						data.before($('<span></span>')
							.attr('id', 'simplemodal-placeholder')
							.css({display: 'none'}));
	
						s.d.placeholder = true;
						s.display = data.css('display');
	
						// persist changes? if not, make a clone of the element
						if (!s.o.persist) {
							s.d.orig = data.clone(true);
						}
					}
				}
				else if (typeof data === 'string' || typeof data === 'number') {
					// just insert the data as innerHTML
					data = $('<div></div>').html(data);
				}
				else {
					// unsupported data type!
					alert('SimpleModal Error: Unsupported data type: ' + typeof data);
					return s;
				}
	
				// create the modal overlay, container and, if necessary, iframe
				s.create(data);
				data = null;
	
				// display the modal dialog
				s.open();
	
				// useful for adding events/manipulating data in the modal dialog
				if ($.isFunction(s.o.onShow)) {
					s.o.onShow.apply(s, [s.d]);
				}
				
				//apply PIE to the data if specified
				if (s.o.pie == true && typeof(PIE) != 'undefined' && uitools.isIE() == true) {

					if (s.o.pieElems != null) {
						$.each($(s.o.pieElems, s.d.data), function(){
							PIE.attach($(this).get(0));
						})						
					} else {
						PIE.attach(s.d.data.get(0));
					}

				}
	
				// don't break the chain =)
				return s;
			},
		
        	/*
			 * Create and add the modal overlay and container to the page
			 */
        	create: function (data) {
        	
				var s = this;
				
				//fix for Android position
				if(navigator.userAgent.match(/Android/i) != null) {
					var posx = ($(document).width() - 500) / 2
    					s.o.position = [$(window).scrollTop() + 100, posx];
    				}
	
				// get the window properties
				w = s.getDimensions();
				
				$(s.o.appendTo).css({overflow:'hidden'});
				
				// create the container
				s.d.container = $('<div></div>')
					.attr('id', s.o.containerId)
					.addClass('modal-container')
					.css($.extend(s.o.containerCss, {
						display: 'none',
						position: 'fixed',
						height:'100%',
						width:'100%',
						top:0,
						left:0
					}))
					.appendTo(s.o.appendTo);
					
					
				s.d.overlay = $('<div></div>')
					.attr('id', s.o.overlayId)
					.addClass('modal-overlay')
					.css($.extend(s.o.overlayCss, {
						display: 'none',
						opacity: s.o.opacity / 100,
						height: '100%', //s.o.modal ? w[0] : 0,
						width: '100%',//s.o.modal ? w[1] : 0,
						position:'absolute',
						/* position:'relative' */
						left: 0,
						top: 0,
						zIndex: s.o.zIndex + 1
					}))
					.appendTo(s.d.container);
	
				//create the wrap
				s.d.wrap = $('<div></div>')
					.attr('tabIndex', -1)
					.addClass('modal-wrap')
					.css({
						/* height: '100%',  */
						height: '100%', 
						outline: 0,
						width: '100%',
						overflow:'auto',
						position:'absolute',
						zIndex: s.o.zIndex + 2
					})
					.appendTo(s.d.container);
	
				// add styling and attributes to the data
				// append to body to get correct dimensions, then move to wrap
				s.d.data = data
					.attr('id', data.attr('id') || s.o.dataId)
					.addClass(s.o.dataId)
					.css($.extend(s.o.dataCss, {
							display: 'none',
							position:'absolute'
					}))
					.appendTo('body');
				
				//add buttons if any
				if (typeof(s.o.buttons) != 'undefined') {
					$.each(s.o.buttons, function(i,button){
						
						if (typeof(button.href) == 'undefined')
							button.href = '';
						
						if (typeof(button.cssClass) == 'undefined')
							button.cssClass = s.o.buttonClass;
						
						var $button = $('<a href="'+button.href+'" class="'+button.cssClass+'"><span>'+button.label+'</span></a>');
						if (typeof(button.handler) != 'undefined') {
							$button.click(button.handler)
						}
						
						s.d.data.append($button);
					})
					
				}
					
				data = null;

				s.setContainerDimensions();

				s.d.data.appendTo(s.d.wrap);
				
				s.d.data.append(s.o.close && s.o.closeHTML ? $(s.o.closeHTML).addClass(s.o.closeClass) : '')
	
				// fix issues with IE
				if (ie6 || ieQuirks) {
					s.fixIE();
				}
				
				//fix issues with ipad/android viewport not scrolling modal into view
				if(navigator.userAgent.match(/iPad/i) != null) {
    					window.scroll(0,0);
    				}

			},
			
			bindEvents: function () {
			
				var s = this;
	
				// bind the close event to any element with the closeClass class
				$('.' + s.o.closeClass).bind('click.simplemodal', function (e) {
					e.preventDefault();
					s.close();
				});
	
				// bind the overlay click to the close function, if enabled
				if (s.o.modal && s.o.close && s.o.overlayClose) {
					
					s.d.wrap.bind('click.simplemodal', function (e) {
						e.preventDefault();
						s.close();
					});
					
					s.d.data.bind('click.simplemodal', function (e) {
						e.cancelBubble = true;
						if (e.stopPropagation)
							e.stopPropagation();
					});
					
				}
	
				// bind keydown events
				$(document).bind('keydown.simplemodal', function (e) {
				
					if (s.o.modal && e.keyCode === 9) { // TAB
						s.watchTab(e);
					}
					else if ((s.o.close && s.o.escClose) && e.keyCode === 27) { // ESC
						e.preventDefault();
						s.close();
					}
				});
	
				// update window size
				$(window).bind('resize.simplemodal', function () {
					// redetermine the window width/height
					w = s.getDimensions();

					// reposition the dialog
					s.o.autoResize ? s.setContainerDimensions() : s.o.autoPosition && s.setPosition();

					if (ie6 || ieQuirks) {
						s.fixIE();
					} else if (s.o.modal) {
						// update the iframe & overlay
						s.d.iframe && s.d.iframe.css({height: w[0], width: w[1]});
						/* s.d.overlay.css({height: w[0], width: w[1]}); */
					}
				});
			},
			
			/*
			 * Update the container. Set new dimensions, if provided.
			 * Focus, if enabled. Re-bind events.
			 */
			update: function (height, width) {
				
				var s = this;
	
				// prevent update if dialog does not exist
				if (!s.d.data) {
					return false;
				}
	
				// reset orig values
				s.d.origHeight = s.getVal(height, 'h');
				s.d.origWidth = s.getVal(width, 'w');
	
				// hide data to prevent screen flicker
				s.d.data.hide();
				/*height && s.d.container.css('height', height);
				width && s.d.container.css('width', width);*/
				s.setContainerDimensions();
				s.d.data.show();
				s.o.focus && s.focus();
	
				// rebind events
				s.unbindEvents();
				s.bindEvents();
			},
			
			setContainerDimensions: function () {

				var s = this,
					badIE = ie6 || ie7;
	
				// get the dimensions for the container and data
				var ch = s.d.origHeight ? s.d.origHeight : $.browser.opera ? s.d.container.height() : s.getVal(badIE ? s.d.container[0].currentStyle['height'] : s.d.container.css('height'), 'h'),
					cw = s.d.origWidth ? s.d.origWidth : $.browser.opera ? s.d.container.width() : s.getVal(badIE ? s.d.container[0].currentStyle['width'] : s.d.container.css('width'), 'w'),
					dh = s.d.data.outerHeight(true), dw = s.d.data.outerWidth(true);
	
				s.d.origHeight = s.d.origHeight || ch;
				s.d.origWidth = s.d.origWidth || cw;
	
				// mxoh = max option height, mxow = max option width
				var mxoh = s.o.maxHeight ? s.getVal(s.o.maxHeight, 'h') : null,
					mxow = s.o.maxWidth ? s.getVal(s.o.maxWidth, 'w') : null,
					mh = mxoh && mxoh < w[0] ? mxoh : w[0],
					mw = mxow && mxow < w[1] ? mxow : w[1];
	
				// moh = min option height
				var moh = s.o.minHeight ? s.getVal(s.o.minHeight, 'h') : 'auto';
				if (!ch) {
					if (!dh) {ch = moh;}
					else {
						if (dh > mh) {ch = mh;}
						else if (s.o.minHeight && moh !== 'auto' && dh < moh) {ch = moh;}
						else {ch = dh;}
					}
				}
				else {
					ch = s.o.autoResize && ch > mh ? mh : ch < moh ? moh : ch;
				}
	
				// mow = min option width
				var mow = s.o.minWidth ? s.getVal(s.o.minWidth, 'w') : 'auto';
				if (!cw) {
					if (!dw) {cw = mow;}
					else {
						if (dw > mw) {cw = mw;}
						else if (s.o.minWidth && mow !== 'auto' && dw < mow) {cw = mow;}
						else {cw = dw;}
					}
				}
				else {
					cw = s.o.autoResize && cw > mw ? mw : cw < mow ? mow : cw;
				}
	
				/* s.d.container.css({height: ch, width: cw}); */
				/* s.d.wrap.css({overflow: (dh > ch || dw > cw) ? 'auto' : 'visible'}); */
				s.o.autoPosition && s.setPosition();
			},
			
			setPosition: function () {
				
				var s = this, top, left,
					hc = (w[0]/2) - (s.d.container.outerHeight(true)/2),
					vc = (w[1]/2) - (s.d.container.outerWidth(true)/2);
	
				if (s.o.position && Object.prototype.toString.call(s.o.position) === '[object Array]') {
					
					top = s.o.position[0] || hc;
					left = s.o.position[1] || vc;
					
					var t = top;
					var l = left;
										
				} else {
					top = hc;
					left = vc;
					
					var l = ($(window).width() - s.d.data.outerWidth(true))/2;
					var t = ($(window).height() - s.d.data.outerHeight(true))/2;
				
				}
	
				//var l = ($(window).width() - s.d.data.outerWidth(true))/2;
				//var t = ($(window).height() - s.d.data.outerHeight(true))/2;
	
				if (t < 0)
					t = 0;
					
				s.d.data.css({left:l +'px',top:t +'px'});
				
				/* s.d.container.css({left: left, top: top}); */
			},
			
			close: function () {
				var s = this;
	
				// prevent close when dialog does not exist
				if (!s.d.data) {
					return false;
				}
				
				//detach PIE from the data if specified
				if (s.o.pie == true && typeof(PIE) != 'undefined' && uitools.isIE() == true) {
				
					if (s.o.pieElems != null) {
						$.each($(s.o.pieElems), function(){
							PIE.detach($(this).get(0));
						})						
					} else {
						PIE.detach(s.d.data.get(0));
					}
					
				}
	
				// remove the default events
				s.unbindEvents();
	
				if ($.isFunction(s.o.onClose) && !s.occb) {
					// set the onClose callback flag
					s.occb = true;
	
					// execute the onClose callback
					s.o.onClose.apply(s, [s.d]);
				}

				// if the data came from the DOM, put it back
				if (s.d.placeholder) {
					var ph = $('#simplemodal-placeholder');
					// save changes to the data?
					if (s.o.persist) {
						// insert the (possibly) modified data back into the DOM
						ph.replaceWith(s.d.data.removeClass(s.o.dataId).css('display', s.display));
					}
					else {
						// remove the current and insert the original,
						// unmodified data back into the DOM
						s.d.data.hide().remove();
						ph.replaceWith(s.d.orig);
					}
				}
				else {
					// otherwise, remove it
					s.d.data.hide().remove();
				}

				// remove the remaining elements
				s.d.container.hide().remove();
				s.d.overlay.hide();
				s.d.iframe && s.d.iframe.hide().remove();
				setTimeout(function(){
					// opera work-around
					s.d.overlay.remove();

					// reset the dialog object
					s.d = {};
				}, 10);
				

				if(htmlScroll != null)
					$('html').css('overflow-y',htmlScroll);
					
				$(s.o.appendTo).css({overflow:''});
					
					
				
			}
        	
        } //end impl
        
    };

    $.extend(true, $.modal, haModal);

})(jQuery);

