/*
 * OUI (Other User Interface) - jQuery components
 *   ---> POPIN component
 *
 * Copyright © 2009 Raphaël BENITTE
 *   http://www.undes1gn.org/
 * 
 * Depends:
 *  oui.js
 */

/*
TODO
 + Fix IE6 problem with fixed positioning
 + BGIframe like fix for form elements overlay
 + More built in presets/methods for alerts/errors/images...
 + More AJAX !
 + Auto detect popin type when it's not dirctly constructed with new $.oui.Popin()
*/

(function($) {
	
	$.extend( $.oui, {
		
		Popin: function(options)
		{
			var self = this; // this alias
			
			this.settings = jQuery.extend( {}, $.oui.Popin.defaults, options || {} );
			this.isOpen = false;
			this.header;
			this.blocker;
			
			if ( !this.settings.pos.x ) this.settings.pos.x = $(window).width()  / 2;
			if ( !this.settings.pos.y ) this.settings.pos.y = $(window).height() / 2;
			
			$.oui.higherDepth += this.settings.block ? 2 : 1;
			this.depth = $.oui.higherDepth;
			
			if ( this.settings.url ) {
				$.get( this.settings.url, function(data){ self.content = data; });
			}
			if ( this.settings.fromDom ) this.content = this.settings.fromDom;
			if ( this.settings.content ) this.content = this.settings.content;
			
			var wrapper = $('<div />').addClass('oui-popin oui-popin-' + this.settings.theme);
			
			this.win = $('<div />').addClass('oui-popin-window oui-popin-window-' + this.settings.theme).ouiRC('all', 5);

			var contentWrap = $('<div />');
			contentWrap.addClass('oui-popin-content oui-popin-content-' + this.settings.theme)
					   .html(this.content);

			this.win.append(contentWrap)
					.appendTo('body')
					.wrap(wrapper);
			
			this.wrapper = this.win.parent();
			this.wrapper.css('z-index', self.depth)
						.mousedown( function(){ self.bringFront(true) } )
						.ouiRC('all', 8);
			
			if ( this.settings.title || this.settings.draggable || this.settings.closable ) {
				this.buildHeader();
			}
			
			if ( this.settings.title ) this.setTitle(this.settings.title);
			if ( this.settings.closable ) this.enableClose();
			if ( this.settings.draggable ) this.enableDrag();
			if ( this.settings.resizable ) this.enableResize();
			if ( this.settings.block ) this.enableBlocker();
			
			if ( this.settings.autopen ) this.open();
		}
	});
	
	$.oui.Popin.prototype = {
		
		enableBlocker: function() {
			if ( !this.blocker ) {
				var blocker = $('<div />');
				blocker.addClass('oui-popin-blocker oui-popin-blocker-' + this.settings.theme)
					   .css( { opacity: this.settings.blockerOpacity,
							   'z-index': this.depth - 1 } );
				$('body').append(blocker);
				this.blocker = blocker;
			}
			return this;
		},
		
		enableClose: function() {
			
			var self = this; // this alias
			
			$('<a />').addClass('oui-popin-close oui-popin-close-' + this.settings.theme)
					  .attr('href', 'javascript:;')
					  .click(function(){ self.close(); })
					  .prependTo(this.header);
		},
		
		enableResize: function() {
			
			var self = this; // this alias
			
			var sizer = $('<span />');
			sizer.addClass('oui-popin-sizer oui-popin-sizer-' + this.settings.theme);
			
			sizer.mousedown(function(e){
				$(document).bind( 'mousemove',
								  { self: self,
									exo: e.pageX,
									eyo: e.pageY,
									ow: self.win.outerWidth(),
									oh: self.win.outerHeight() },
								  self.resizeupdt)
						   .mouseup(function(){ $(document).unbind('mousemove', self.resizeupdt); });
			});
			
			var footer = $('<div />');
			footer.addClass('oui-popin-footer oui-popin-footer-' + this.settings.theme)
				  .append(sizer);
			
			this.win.append(footer);
		},
		
		resizeupdt: function(e) {
			var self = e.data.self;
			self.win.width(  e.pageX - e.data.exo + e.data.ow )
					.height( e.pageY - e.data.eyo + e.data.oh );
		},
		
		enableDrag: function() {
			
			var self = this;
			
			this.header.mousedown(function(e) {
				self.header.addClass('oui-popin-header-dragging oui-popin-header-dragging-' + self.settings.theme);
					$(document).bind( 'mousemove', {
						self: self,
						mxo: e.pageX - self.wrapper.offset().left,
						myo: e.pageY - self.wrapper.offset().top },
						self.dragUpdt
					);
			})
			.mouseup(function(e) {
				$(document).unbind('mousemove', self.dragUpdt);
				self.header.removeClass('oui-popin-header-dragging oui-popin-header-dragging-' + self.settings.theme);
			})
			.bind('selectstart', function(){ return false; })
			.css('MozUserSelect', 'none');
		},
		
		dragUpdt: function(e) {
			e.data.self.wrapper.css({ top: e.pageY-e.data.myo, left: e.pageX-e.data.mxo });
		},
		
		setSize: function(size) {
			var w = size.w;
			var h = size.h;
			this.win.width(w).height(h);
			return this;
		},
		
		close: function() {
			
			if ( this.isOpen ) {
				
				var self = this;
				this.isOpen = false;
			
				if ( this.settings.animate == true ) {
					this.wrapper.fadeOut(this.settings.closeDuration, function() {
						if ( self.settings.closeRmv == true ) {
							self.wrapper.remove();
						}
					});
				} else {
					if ( this.settings.closeRmv == true ) {
						this.wrapper.remove();
					} else {
						this.wrapper.hide();
					}
				}
				
				if ( this.settings.block ) this.blocker.hide();
			}
			
			return this;
		},
		
		open: function() {
			
			if ( !this.isOpen ) {
				
				var self = this;
				this.isOpen = true;
				this.bringFront(true);

				var contentSize = this.getContentSize();
				var width  = this.settings.width == 'auto' ? contentSize.w  : this.settings.width;
				var height = this.settings.height == 'auto' ? contentSize.h : this.settings.height;
				
				if ( this.settings.animate == true ) {
					var content = this.win.find('.oui-popin-content');
					content.hide();

					this.win.width(0).height(0).show();

					this.wrapper.show();

					var animo = {
						duration: this.settings.openDuration,
						step: function(){
							self.wrapper.css({ top:  self.settings.pos.y - self.wrapper.outerHeight() / 2,
											   left: self.settings.pos.x - self.wrapper.outerWidth()  / 2 });
						},
						complete: function(){
							content.fadeIn('slow');
							if ( self.settings.width  == 'auto' ) self.win.width('auto');
							if ( self.settings.height == 'auto' ) self.win.height('auto');
						}
					};

					this.win.animate( { width: width, height: height }, animo );
			
				} else {
					this.wrapper.show();
					this.center();
				}
				
				if ( this.settings.block ) this.blocker.show();
			}
			
			return this;
		},
		
		bringFront: function(popinOnly) {
			
			var popinOnly = popinOnly || false;
			
			if ( !popinOnly ) {
				if ( this.depth < $.oui.higherDepth ) {
					$.oui.higherDepth += this.settings.block ? 2 : 1;
					this.depth = $.oui.higherDepth;
					this.wrapper.css('z-index', this.depth);
					if ( this.settings.block ) this.blocker.css('z-index', this.depth-1);
				}
			} else {
				var popins = $('.oui-popin');
			}
			return this;
		},
		
		setContent: function(content) {
			this.win.find('.oui-popin-content').html(content);
			if ( this.settings.width  != 'auto' ) this.win.width(this.settings.width);
			if ( this.settings.height != 'auto' ) this.win.height(this.settings.height);
			return this;
		},
		
		getContentSize: function() {
			var hideWrapper = false;
			var wrapperLeft = this.wrapper.offset().left;

			if ( !this.wrapper.is(':visible') ) {
				this.wrapper.css('left', -9999).show();
				hideWrapper = true;
			}
			
			var content = this.win.find('.oui-popin-content');
			var hideContent = false;
			if ( !content.is(':visible') ) {
				content.css('left', -9999);
				hideContent = true;
			}
			
			var width  = this.win.outerWidth();
			var height = this.win.outerHeight();
			
			if ( hideWrapper ) this.wrapper.hide().css('left', wrapperLeft);
			if ( hideContent ) content.hide();
			
			return { w: width, h: height };
		},
		
		buildHeader: function() {
			var header = $('<div />').addClass('oui-popin-header oui-popin-header-' + this.settings.theme)
									 .ouiRC('top', 3)
									 .prependTo(this.win);
			this.header = header;
		},
		
		setTitle: function(title) {
			
			var headerTitle = this.header.find('.oui-popin-header-title');
			
			if ( headerTitle.size() == 0 ) {
				headerTitle = $('<div />');
				headerTitle.addClass('oui-popin-header-title oui-popin-header-title-' + this.settings.theme);
				this.header.append(headerTitle);
			}
			
			headerTitle.html(title);
			
			return this;
		},
		
		center: function() {
			var winWidth    = $(window).width();
			var winHeight   = $(window).height();
			var popinHeight = this.wrapper.height();  
			var popinWidth  = this.wrapper.width();

			this.wrapper.css( { 'top'  : winHeight / 2 - popinHeight / 2,  
								'left' : winWidth  / 2 - popinWidth  / 2 } );
		}
	};
	
	$.fn.extend({
		ouiPopin: function()
		{
			
		}
	});
	
	$.extend( $.oui.Popin, {
		
		defaults: {
			title:         false,
			closable:      true,
			draggable:     false,
			resizable:     false,
			position:      'auto',
			theme:         'default',
			block:         false,
			blockerOpacity: .6,
			closeRmv:      true,
			autopen:       true,
			animate:       true,
			openDuration:  600,
			closeDuration: 400,
			width:         'auto',
			height:        'auto',
			pos:           {}
		},
		
		confirm: function( msg, confirmed, options ) {
			
			var loadingDefaults = jQuery.extend( {}, $.oui.Popin.defaults,
				{ autopen: true } );
			
			var settings = jQuery.extend( loadingDefaults, options || {} );

			var confirmwrapper = $('<div />');
		
			var ok = $('<a href="javascript:;">OK</a>');
			ok.addClass('oui-btn oui-btn-' + settings.theme)
			  .ouiRoundCorners('all', 5);
			
			var cancel = $('<a href="javascript:;">annuler</a>');
			cancel.addClass('oui-btn oui-btn-' + settings.theme)
			      .ouiRoundCorners('all', 5);
			
			confirmwrapper.append( $('<div></div>').html(msg) )
						  .append( $('<div></div>').css( { 'text-align': 'center',
						 								   'margin-top': 5 } )
						  .append(ok).append('&nbsp;').append(cancel) );
			
			// override incompatible options
			settings = jQuery.extend( settings, {
				content:   confirmwrapper,
				closable:  false,
				closeRmv:  true,
				resizable: false
			});

			var pi = new $.oui.Popin(settings);
			
			cancel.click( function(){ pi.close() } );
			
			ok.click( function(){ confirmed(pi); pi.close(); } );
			
			return pi;
		},
		
		// display a progress bar
		loading: function( options ) {
			
			var loadingDefaults = jQuery.extend( {}, $.oui.Popin.defaults,
				{ animate: false } );
			
			var settings = jQuery.extend( loadingDefaults, options || {} );
		
			var loading = $('<div />');
			loading.addClass('oui-loading oui-loading-' + settings.theme)
				   .ouiRoundCorners('all', 3)
				   .css('margin', '10px 0');
			
			// override incompatible options
			settings = jQuery.extend( settings, {
				content:   loading,
				closable:  false,
				resizable: false
			});

			return new $.oui.Popin(settings);
		}
	});
	
})(jQuery);