/*  _____             _____   _____
 * |  _  \           |___  | |___  |
 * | | | |              _| |    _| |
 * | | | |  o  o  o    |_  {   |_  {
 * | |_| |            ___| |  ___| |
 * |_____/           |_____/ |_____/
 *
 *   __   ___   _   _   ___   _    _        _    _
 * /  _| |  _| | | | | |  _| | \  | |      | \__/ |
 * | |   | |_  | | | | | |_  |  \ | |      |      |
 *  \ \  |  _| \ \ / / |  _| | |\\| |      | |\/| |
 *  _| | | |_   \   /  | |_  | | \  |      | |  | |
 * |__/  |___|   \_/   |___| |_|  |_|      |_|  |_|
 *
 *
 * Copyright (C) D33 Internet GmbH and SEVEN M GmbH
 * All rights reserved
 * 
 * @autor: hv@seven-m.de
 * 
 * ==============================================================
 *	jQuery Floating Folder Plugin 
 * ==============================================================
 * @requires jQuery v1.4.2 or later *
 *
 * 
 * --------------------------------------------------------------  
 *  Usage:
 * --------------------------------------------------------------  
 *  
 *  To initialize call once per page:
 * --------------------------------------------------------------  
 *  $.FloatFolderFactory.initFactory();
 *
 *
 *	for each folder call:
 * --------------------------------------------------------------  
 *	$("#selector of our div").createFloatingFolder({
 *		width_maximized: 30,
 *		height_maximized: 30,
 *		offset_top: 0,				// (optional, default 0)
 *		horizontal_align: "left",	// (optional, default "left" possible values: "left" or "right")
 *		height_minimized: 30,		// (optional if not set it has the same value as maximized)
 *		width_minimized: 30			// (optional if not set it has the same value as maximized)
 *	});
 *  
 *
 *  for binding buttons to a folder call:
 * --------------------------------------------------------------  
 *  - Toggle Button:
 *  	$(".selector of button(s)").bindToggleButton({
 *  		linkedFolder: $("#selector of our folder div"), // custom callback optional
 *   		callbackMin: function(){}, 						//(optional) callback function when minimize is done
 * 			callbackMax: function(){} 						// (optional) callback function when maximize is done
 *  	});
 *  - maximize Button:
 *  	$(".selector of button(s)").bindMaximizeButton({
 *  		linkedFolder: $("#selector of our folder div"), // custom callback optional
 * 			callbackMax: function(){} 						// (optional) callback function when maximize is done
 *  	});
 *  - minimize Button:
 *  	$(".selector of button(s)").bindMinimizeButton({
 * 			linkedFolder: $("#selector of our folder div"), // custom callback optional
 *   		callbackMin: function(){}, 						//(optional) callback function when minimize is done
 *  	});
 *  
 *  Note: 
 *  Each folder can only have one call back for maximize and one for minimize
 *  if you assign more than one the old callback function is overwritten.
 *  
 */


(function($){
	/**
	 * ==============================================================
	 * 		Floating Folder Object
	 * ==============================================================
	 * 
	 * @param jqObj selector object
	 * @param params see $.FloatingFolderFactory.addFF
	 */
	function FolderObject( jqObj, params )
	{
		// jquery selector folder object
		this.jqSelector = jqObj;
		
		this.isMaximized = false;
		
		this.widthMinimized = params.width_minimized;
		
		this.widthMaximized = params.width_maximized;
		
		this.heightMinimized = params.height_minimized;
		
		this.heightMaximized = params.height_maximized;
	
		this.offsetTop = params.offset_top;
		
		this.halign = params.horizontal_align;
		
		// blank functions if we don't need a callback
		this.callbackFuncMinimized = function(){return true;};
		this.callbackFuncMaximized = function(){return true;};
		// init style		
		this.jqSelector.css({'width':this.widthMinimized+'px', 'height': this.heightMinimized+'px' });
	}
	
	
	/**
	 * ==============================================================
	 * 		Floating Folder Object Functions
	 * ==============================================================
	 */
	/**
	 * updates the ancor position of our folder
	 * is called by resize and scroll event
	 */
	FolderObject.prototype.updateAncor = function()
	{
		var myX = 0;
		if( this.halign == "right" ) 
		{
			if ( this.isMaximized == false) 
			{
				myX = $(window).width() - this.widthMinimized;
			} else if (this.isMaximized == true) {
				myX = $(window).width() - this.widthMaximized;
			}
		} else if( this.halign == "left" ) {
			// nothing to do here
		}
			
		var offsetT = this.offsetTop;
		if( $(window).height() < (this.offsetTop + this.heightMaximized ) ) 
			offsetT = $(window).height() - this.heightMaximized;
		
		if( offsetT < 0 ) 
			offsetT = 0;

		this.jqSelector.css({'left':myX}); 
		
		if ( ($(window).scrollTop()+offsetT) != this.jqSelector.css('top') )
		{
			this.jqSelector.animate({top: ($(window).scrollTop()+offsetT) +"px" },{queue: false, duration: 500});
		}	
	}
	
	
	/**
	 * is called when the maximize progress starts
	 * calls also a custom callback function if one is defined
	 */
	FolderObject.prototype.maximize = function()
	{
		if( this.isMaximized == false ) 
		{
			if( this.halign == "right" ) 
			{
				var pos = $(window).width() - this.widthMaximized;
				this.jqSelector.animate(
					{ "left": pos+"px", "width": this.widthMaximized+"px"}, 
					{ "duration":"fast", "complete": this.callbackFuncMaximized() }
				);
			} else if( this.halign == "left" ) {
				
				this.jqSelector.animate(
					{ "width": this.widthMaximized+"px" }, 
					{ "duration":"fast", "complete": this.callbackFuncMaximized() }
				);
			}
			this.isMaximized = true;
			
		}
	}
	
	/**
	 * is called when the minimize progress starts
	 * calls also a custom callback function if one is defined
	 */
	FolderObject.prototype.minimize = function()
	{
		if( this.isMaximized == true ) 
		{
			if( this.halign == "right" ) 
			{
				var pos = $(window).width() - this.widthMinimized;
				this.jqSelector.animate(
					{ "left": pos+"px","width": this.widthMinimized+"px" },
					{ "duration":"fast", "complete": this.callbackFuncMinimized() }
				);
			
			} else if( this.halign == "left" ) {
				this.jqSelector.animate(
					{ "width": this.widthMinimized+"px" },
					{ "duration":"fast", "complete": this.callbackFuncMinimized() }
				);
			}
			this.isMaximized = false;
			
		}
	}
	
	/**
	 * Event btnToggle
	 */
	FolderObject.prototype.btnToogle = function()
	{
		if( this.isMaximized == false ) 
		{
			this.maximize();
		} else {
			this.minimize();
		}
	}
	
	/**
	 * Event btnMinimize
	 */
	FolderObject.prototype.btnMinimize = function()
	{
		if( this.isMaximized == true ) 
		{
			this.minimize();
		}
	}
	
	/**
	 * Event btnMaximize
	 */
	FolderObject.prototype.btnMaximize = function()
	{
		if( this.isMaximized == false ) 
		{
			this.maximize();
		} 
	}
	
	
	
	/**
	 * ==============================================================
	 * 		Floating Folder Factory
	 * ==============================================================
	 * 
	 * manages all floating folders
	 */
	$.FloatFolderFactory = {
		
		/**
		 * Array where all folders as FolderObject are stored
		 */	
		arrFolders: new Array(),
		
		/**
		 * register events for float handlers
		 */
		initFactory : function()
		{
			//now making sure we are registered to all required window events
			if( !$.FloatFolderFactory.registeredEvents ) 
			{
				$(window).bind("resize", $.FloatFolderFactory.onChange);
				$(window).bind("scroll", $.FloatFolderFactory.onChange);
				$.FloatFolderFactory.registeredEvents = true;
			}	
		},
		
		/**
		 * adds a new Floating Folder 
		 * 
		 * @param selector
		 * @param params:
		 * 		width_maximized: 30,
		 *		height_maximized: 30,
		 *		offset_top: 0,				// (optional, default 0)
		 *		horizontal_align: "left",	// (optional, default "left" possible values: "left" or "right")
		 *		height_minimized: 30,		// (optional if not set it has the same value as maximized)
		 *		width_minimized: 30			// (optional if not set it has the same value as maximized)
		 * 
		 */
		addFF: function( selector, params )
		{
			// make sure every needed param is preset
			var w_max = params.width_maximized;
			var w_min = params.width_minimized;
			var h_max = params.height_maximized;
			var h_min = params.height_minimized;
			var offTop = params.offset_top;
			var halign = params.horizontal_align;
			
			if( w_min == null )
				w_min = w_max;
			
			if( h_min == null )
				h_min = h_max;
			
			if( offTop == null )
				offTop = 0;
			
			if( halign == null || (halign != "left" && halign != "right") )
				halign = "left";
			
					
			var settings =  $.extend({
					width_maximized: w_max,
					height_maximized: h_max,
					offset_top: offTop,
					horizontal_align: halign,
					height_minimized: h_min,
					width_minimized: h_min
				}, 
				params||{}
			);
			
			var fobj = new FolderObject(selector,settings);
			fobj.updateAncor();
			
			$.FloatFolderFactory.arrFolders.push(fobj);
			
		}, 
		
		/**
		 * set one or more buttons for min/max/toggle the folder
		 * 
		 * @param selector the selector for our buttons 
		 * @param params:
		 * 		btntype: can be "min", "max", or "toggle"
		 * 		linkedFolder: selector of the folder you want to link the button
		 * 		callbackMin: (optional) callback function when minimize is done
		 * 		callbackMax: (optional) callback function when maximize is done
		 */
		setFolderButton: function( selector, params )
		{
			$.each( $.FloatFolderFactory.arrFolders, function( foldIdx, currFolder ) { 
				
				if( currFolder.jqSelector.attr("id") == params.linkedFolder.attr("id") ) 
				{
		
					if( typeof params.callbackMin == 'function' ){
						currFolder.callbackFuncMinimized = function() { return params.callbackMin() };
					}
					if( params.callbackMax != null && typeof params.callbackMax == 'function' ){
						currFolder.callbackFuncMaximized = function() { return params.callbackMax() };
					}
					
					if( params.btntype == "max" ) {
						selector.bind("click", function(){ 
							 currFolder.btnMaximize();
						});  
					} else if( params.btntype == "min" ) {
						selector.bind("click", function(){ 
							 currFolder.btnMinimize();
						});  
					} else if( params.btntype == "toggle" ) {
						selector.bind("click", function(){ 
							 currFolder.btnToogle();
						});  
					}
				}
			});
		},
		
		/**
		 * Event onChange
		 * is bind on resize and scroll (browserwindow)
		 * by initFactory
		 */
		onChange: function()
		{
			for( var i = 0 ; i < $.FloatFolderFactory.arrFolders.length ; i++ )
			{
				 currFolder = $.FloatFolderFactory.arrFolders[i];
				 currFolder.updateAncor();
			}
		
		}
		
	};
	/**
	 * ==============================================================
	 * 		Floating Folder public functions
	 * ==============================================================
	 * 
	 */
	
	/**
	 * create a new Floating Folder
	 * 
	 * @param params see $.FloatingFolder.addFF
	 */
	$.fn.createFloatingFolder = function( params )
	{
		if( !this.length ) {
			alert("no selector for Float Folder found!");
			return this;
    	}
    	// we only operate on the first selected object.
    	// if you want to add more than one folder call this function 
    	// again with different selector and parameters
		var obj = this.eq(0); 
		//$.FloatFolderFactory.initFactory();
		$.FloatFolderFactory.addFF(obj,params);
		//$.FloatFolder.updateAncor();
		return obj;
	};
	
	
	/**
	 * Bind one or more buttons for maximizing the folder
	 * 
	 * @param params:
	 * 		linkedFolder: selector of the folder you want to link the button
	 * 		callbackMin: (optional) callback function when minimize is done
	 * 		callbackMax: (optional) callback function when maximize is done
	 */
	$.fn.bindMaximizeButton = function( params )
	{
		if( !this.length ) {
			alert("no selector for Button found!");
			return this;
    	}
		if( params.linkedFolder == null ) {
			alert("no linkedFolder param set!");
			return this;
	    }
		var settings =  $.extend(
			{ btntype: "max" }, params||{}
		);
		$.FloatFolderFactory.setFolderButton( this, settings );
		
	}
	
	/**
	 * Bind one or more buttons for minimizing the folder
	 * 
	 * @param params:
	 * 		linkedFolder: selector of the folder you want to link the button
	 * 		callbackMin: (optional) callback function when minimize is done
	 * 		callbackMax: (optional) callback function when maximize is done
	 */
	$.fn.bindMinimizeButton = function( params )
	{
		if( !this.length ) {
			alert("no selector for Button found!");
			return this;
    	}
		if( params.linkedFolder == null ) {
			alert("no linkedFolder param set!");
			return this;
	    }
		var settings = $.extend(
			{ btntype: "min" }, params||{}
		);
		$.FloatFolderFactory.setFolderButton( this, settings );
		
	}
		 
	/**
	 * Bind one or more buttons for toggling the folder
	 * 
	 * @param params:
	 * 		linkedFolder: selector of the folder you want to link the button
	 * 		callbackMin: (optional) callback function when minimize is done
	 * 		callbackMax: (optional) callback function when maximize is done
	 */
	$.fn.bindToggleButton = function( params )
	{
		if( !this.length ) {
			alert("no selector for Button found!");
			return this;
    	}
		if( params.linkedFolder == null ) {
			alert("no linkedFolder param set!");
			return this;
	    }
		var settings =  $.extend(
			{ btntype: "toggle" }, params||{}
		);
		
		$.FloatFolderFactory.setFolderButton( this, settings );
		
	}
})(jQuery);
