/*
 * Dialogic v1.0.0 - jQuery modal window plugin
 * https://github.com/seogrady/dialogic-jquery
 *
 * Licensed under the MIT:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright (c) 2011 Shane O'Grady
 */
(function($) {
	
	// Standalone mode
  $.dialogic = function(data, options) { setup(arguments) }

 /*
  * Public, $.fn methods
  */
  $.fn.dialogic = function(config) {
    if ($(this).length == 0){ return }		
    return this.live('click.dialogic', function(e){
			if(e){ e.stopPropagation(); e.preventDefault() }
  		if(config instanceof Object){ $.extend($.dialogic.config,config) }		
  		else if(typeof config == 'string'){ $.extend($.dialogic.config,{theme:config}) }		
			setup($(e.target))
		})
  }

 /*
	* Public methods
	*/
	$.extend($.dialogic, {
		config: {
			theme:'heroku',
			overlay:0.3,
			div:'.dialogic-div',
			loader:'.dialogic-loader',
			error:'.dialogic-error'		
		},	
		defaults: {
			theme: 'heroku',
			overlay: true,
			overlay_close: true,
			dialogic_to: 'body',
			append_to:'.wrapper',
			inner_html: null,		
			loader_html: null,
			error_html: null,
			width: null,
			height: null,
			margin_top: null,
			fade_in: 300,
			fade_out: 300,
			fade_between: 300,
			animate: false,
			cache: false
		},
		cache: [],
		theme: function(theme,opts,fn){
			if(typeof theme == 'string' && opts instanceof Object){ this.theme[theme] = $.extend({}, this.defaults, {theme:theme}, opts) }
			if(fn instanceof Object){
				$.each(fn, function(i,v){ $(document).bind(i+'.dialogic_'+theme, v) })	
			}
			if(this.theme[theme]){ return this.theme[theme]}
			else{ return {} }
		},
		overlay: function(fade_in){
			if($('#dialogic .overlay').length == 0){
				this.config.dialog.append($('<div class="overlay"/>').opacity(0));
			}
			var overlay = $('#dialogic .overlay'), opacity = overlay?this.config.overlay:overlay;
			if(fade_in){ overlay.opacity(opacity, fade_in); } else { overlay.opacity(opacity); }
		}, 	
	  close: function(options){
			if(this.config.open && !this.config.active){
				$(document).trigger('before_close.dialogic_'+dialogic.settings.theme)
				var self = this, overlay = $('#dialogic div.overlay'); 
				self.config.container.fadeOut(self.settings.fade_out, function(){ 
					var iframe = $('#dialogic iframe'); 
					if(iframe.length!=0){ iframe.remove() } // IE fix
					self.config.wrapper.empty();
					self.config.open = false;
					$(document).trigger('after_close.dialogic_'+dialogic.settings.theme)
				});
				overlay.opacity(0,self.settings.fade_out, function(){ overlay.remove() });				
			}	
	  }
	})

	/*
	 * Private methods
	 */

	var dialogic = $.dialogic;	
	
	function init(){
		if(dialogic.config.init){ return true }	
		$(dialogic.settings.dialogic_to).append('<div id="dialogic"><div class="container" style="position:absolute;top:0;"><div class="wrapper" style="position:relative;"/></div>');
		dialogic.config.dialog = $('#dialogic');
		dialogic.config.container = $('#dialogic .container').opacity(0);	
		dialogic.config.wrapper = $('#dialogic .wrapper');		
		dialogic.config.init = true;
		$(document).trigger('after_initialize.dialogic_'+dialogic.settings.theme)		
	}
	
	function setup(object){
		dialogic.config.active = true;
		var input, options, theme, action;
		if(object.jquery){
			dialogic.config.obj = object;		
			input = object.data('dialogic-action') || object.attr('href');
			options = object.data('dialogic');		
		} else {		
			input = object[0];			
			options = object[1];
		}	
		if(typeof options == 'string'){
			var theme =  options.match(/^(\w*):(\w*)$/);
			if(theme){
				options = theme[1];				
				action = theme[2]; 
			}
		}
		if(typeof input == 'string'){
			if(!action){
				action = input ? input.match(/#/) ? 'div' : input.match(/\.(png|jpg|jpeg|gif)(\?.*)?$/) ? 'image' : object.jquery ? 'ajax' : 'html' : 'static';						
			}
		} else {
			action = Object.keys(input)[0];
			input = object[0][action];			
		}
		dialogic.config.input = input;
		dialogic.settings = extend(options);
		init();
		if(dialogic.settings.overlay){ dialogic.overlay(dialogic.settings.fade_in) }
		$(document).trigger('before_'+action+'.dialogic_'+dialogic.settings.theme)
		dialogic.action[action]();		
	}
	
	function extend(options){
		var settings = typeof options == 'string' ? {theme:options} : options instanceof Object ? options : {theme:dialogic.config.theme},
				theme_opts = dialogic.theme(settings.theme);
		if(theme_opts.theme){ settings.theme = theme_opts.theme }		
		return $.extend({}, dialogic.defaults, theme_opts, settings)
	}
	
	function clone(div){
		var html = dialogic.config.obj != undefined && dialogic.config.obj.length != 0 ? dialogic.config.obj.next(div) : $(div+':first');
		if(html.length == 0){ html = $(div+':first') }	
	  if(html.length != 0){ return html.contents().clone() }
		else { return div }
	}
	
	function identify(div){
		var theme = dialogic.settings.klass || dialogic.settings.theme;
		div.attr({'id':'dialogic','class':'dialogic '+theme});
	}

	function styleDialogic(container, options){
		container.attr('style','').css({position:'fixed',opcaity:0,width:options.width,height:options.height});
		var height = options.height == null || options.height == false ? container.height() : options.height;
				width = container.width(), width = options.width == null || options.width == false ? $.browser.mozilla ? width+1 : width : options.width;
		var scrollheight = $(window).scrollTop(),
				windowHeight = $(window).height(),
				result = windowHeight/2 - height/2 + scrollheight,
				limitedResult = result < 0 ? scrollheight : result,
				topLimitedResult = options.margin_top != null && options.margin_top != false && options.margin_top < limitedResult ? options.margin_top + scrollheight : limitedResult;
		if(!dialogic.config.open){ container.attr('style','position:relative;margin:0 auto;') }
		return {'top':topLimitedResult,'width':width,'height':height,opacity:1}
	}
	
	
	function resizeDialogic(data, callback){
		var copy = copyDialogic(data),
				css = styleDialogic(copy.children(':first-child'), dialogic.settings);
		if(dialogic.settings.fade_out){ dialogic.config.wrapper.opacity(0,dialogic.settings.fade_out, function(){
				dialogic.config.wrapper.html(dialogic.settings.inner_html);
				dialogic.config.container.css(css).find(dialogic.settings.append_to).html(data); 
				if(dialogic.settings.fade_in){ dialogic.config.wrapper.opacity(1,dialogic.settings.fade_in, function(){
					if(callback instanceof Function){ callback.call(this) }
				})
				}	else { dialogic.config.wrapper.opacity(1); if(callback instanceof Function){ callback.call(this) } }
			})
		} else { dialogic.config.wrapper.html(dialogic.settings.inner_html);
			dialogic.config.container.css(css).find(dialogic.settings.append_to).html(data);
			if(callback instanceof Function){ callback.call(this) }
		}		
		copy.remove()
	}
	
	
	function animateDialogic(data, callstart, callend){
		var copy = copyDialogic(data), img = copy.find('img');
		var animate = function(){
			var style = styleDialogic(copy.find('.container'), dialogic.settings);
			dialogic.config.wrapper.opacity(0, dialogic.settings.fade_between, function(){
				dialogic.config.wrapper.html(dialogic.settings.inner_html);
				if(callstart instanceof Function){ callstart.call(this); }		
				dialogic.config.container.animate(style, dialogic.settings.animate, function(){
					dialogic.config.container.children(':first-child').html(dialogic.settings.inner_html);
					dialogic.config.container.find(dialogic.settings.append_to).html(data);
					dialogic.config.container.children(':first-child').opacity(1, dialogic.settings.fade_between, function(){			
						if(callend instanceof Function){ callend.call(this); }	
						copy.remove();						
					});
				});
			});	
		}	
		if(img.length>0){ img.imagesLoaded(animate()) }
	}
	
	function copyDialogic(data){
		var theme = dialogic.settings.klass || dialogic.settings.theme;
		if ($('#dialogic-tmp').length == 0){ $(dialogic.settings.dialogic_to).append('<div id="dialogic-tmp" style="visibility:hidden;"><div class="container" style="position:absolute;top:0;left:0;opacity:0;"><div class="wrapper"/></div></div>')}
		var copy = $('#dialogic-tmp').attr('class','dialogic '+theme);
		copy.children(':first-child').attr('style','').css({position:'fixed',top:0})
		.children(':first-child').html(dialogic.settings.inner_html).parent().find(dialogic.settings.append_to).html(data);
		return copy;
	}
	
	function staticDialogic(html, trigger){
		identify(dialogic.config.dialog);		
		if(dialogic.settings.inner_html){ dialogic.config.wrapper.html(dialogic.settings.inner_html) }
		$('#dialogic '+dialogic.settings.append_to).html(html);
		dialogic.config.container.css(styleDialogic(dialogic.config.container, dialogic.settings)).hide();
		if(dialogic.settings.fade_in){ dialogic.config.container.fadeIn(dialogic.settings.fade_in) }	
		else { dialogic.config.container.fadeIn() }
		dialogic.config.open = true;
		if(trigger=='complete'){ dialogic.config.active = false }
		$(document).trigger('after_'+trigger+'.dialogic_'+dialogic.settings.theme)
	}
	
	var transferDialogic = function(html, trigger){
		if(!trigger){ trigger = 'complete' }
		$(document).trigger('before_'+trigger+'.dialogic_'+dialogic.settings.theme)
		if(!dialogic.config.open){			
			staticDialogic(html, trigger)			
		} else {
	 		if(!dialogic.settings.animate){
				resizeDialogic(html, function(){
					identify(dialogic.config.dialog);
					dialogic.config.active = false;
					$(document).trigger('after_'+trigger+'.dialogic_'+dialogic.settings.theme)
				})
			} else {	
				animateDialogic(html, function(){
				  identify(dialogic.config.dialog);
				}, function(){
					dialogic.config.active = false;
					$(document).trigger('after_'+trigger+'.dialogic_'+dialogic.settings.theme)
				});
			}
		}
	}
	
	var action = {
		static: function(){ transferDialogic(clone(dialogic.config.div)) },
		div: function(){ transferDialogic(clone(dialogic.config.input)) },
		html: function(){ transferDialogic(dialogic.config.input) },
		image: function(){ 
			transferDialogic(clone(dialogic.config.loader), 'load');
			var image = new Image();
			image.onload = function(){ 
				var data = '<img src="'+image.src+'"/>';
				transferDialogic(data)
			}
			image.onerror = function(){ transferDialogic(dialogic.settings.error_html || clone(dialogic.config.error)) }
			image.src = dialogic.config.input
		},		
		ajax: function(){
		  var container = dialogic.config.container,
					collect = dialogic.settings.collect == true ? '#'+dialogic.settings.id+' ' : typeof dialogic.settings.collect == 'string' ? dialogic.settings.collect : false, data = dialogic.cache[dialogic.config.input],
					complete = function(data){
						if(data.settings){ $.extend(dialogic.settings, data.settings) }
						if(data.html){ transferDialogic(data.html)	}
					}	
			if(data==undefined){
				var loader = dialogic.settings.loader_html || clone(dialogic.config.loader);
				transferDialogic(loader, 'load');				
				var result = $.getJSON(dialogic.config.input, function(response){data=response});	
				result.complete(function(xhr, status){
					if(status!='success'){ data = {'html':dialogic.settings.error_html || clone(dialogic.config.error),'settings':{}}}
					else if(dialogic.settings.cache){ dialogic.cache[dialogic.config.input] = data }
					complete(data)
				})
			} else { complete(data) }
		}
	}
	$.extend(dialogic, {action:action, transfer:transferDialogic});

	// custom functions
	jQuery.fn.opacity = function(val, animate, func){
		var self = $(this), opacity = val==undefined?self.css('opacity')>=0.5?0:1:val;
		return self.each(function(){
			if(animate==false||animate==undefined){ 
				self.css({'opacity':opacity});
				if(func instanceof Function){ func.call(this); }
			}	else {
				self.animate({'opacity':opacity}, animate, func);
			}
		});
	}
	
	// $('img.photo',this).imagesLoaded(myFunction)
	// execute a callback when all images have loaded.
	// needed because .load() doesn't work on cached images

	// mit license. paul irish. 2010.
	// webkit fix from Oren Solomianik. thx!

	// callback function is passed the last image to load
	//   as an argument, and the collection as `this`
	
	$.fn.imagesLoaded = function( callback ){
	  var elems = this.find( 'img' ),
	      elems_src = [],
	      self = this,
	      len = elems.length;

	  if ( !elems.length ) {
	    if(callback){ callback.call( this ) }
	    return this;
	  }

	  elems.one('load error', function() {
	    if ( --len === 0 ) {
	      // Rinse and repeat.
	      len = elems.length;
	      elems.one( 'load error', function() {
	        if ( --len === 0 ) {
	          callback.call( self );
	        }
	      }).each(function() {
	        this.src = elems_src.shift();
	      });
	    }
	  }).each(function() {
	    elems_src.push( this.src );
	    // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
	    // data uri bypasses webkit log warning (thx doug jones)
	    this.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
	  });

	  return this;
	};
	
	
	/*
   * Bindings
   */

	$('#dialogic-close, #dialogic div.overlay').live('click', function(e){
		if($(e.target).get(0) == $('#dialogic div.overlay').get(0) && !dialogic.settings.overlay_close){ return; }
		if(e) e.stopImmediatePropagation();
		if(e) e.preventDefault();
		dialogic.close();
	});
	
	$(document).keyup(function(e) { 
	  if (e.keyCode == 27 && $.dialogic.config.open) { 
			dialogic.close();
	  } 
	});

})(jQuery);
