/*
 * 
 * Iconize 1.0 
 * Copyright (c) 2009 Tim Radnidge (xiaohouzi79 at gmail)
 * 
 * Licensed under the GPLv3 license:
 * http://www.gnu.org/licenses/gpl.html
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

(function($) {
	jQuery.fn.iconize = function(options) {
		return this.each (function () {
			/*** Function default values ***/
			this.defaults = {
				icon: "Knob Valid Green.png",
				icon_draggable: false,			// Allow the icon to be dragged
				icon_follow: true,				// True sets the content position according to the location of the icon when rebuilt, False rebuilds the content in its previous location
				icon_top: false,				// Specify a specific top / left co-ords for icon docking position if you don't want it to dock to a specific element
				icon_left: false,
				content_top: false,				// Specify a specific top / left co-ords where the content will be restored to
				content_left: false,
				dock: false,					// Location to dock the icon
				dock_sortable: false,			// If the docking item supports sortable items
				collapsed: false,				// If set to true the content will start in iconized form
				append_to_dock: true,			// If set to false the content will be prepended to the dock
				append_to_parent: false,		// If set to true the content will be appended to its parent on reload
				before_collapse: function(){},
				after_collapse: function(){},
				before_rebuild: function(){},
				after_rebuild: function(){}
			};			
			//TODO: read in dimensions of passed in icon image, or just restrict to certain size
		
		
			/*** Set config values based upon defaults and options passed in ***/
			this.config = {};
			var config = $.extend(this.config, this.defaults, options);
			
			$(this).attr("config", config);
			
			if (config.dock_sortable == true) {
				config.icon_draggable = false;
			}
			
			// Set your minimizing icon css here (image, position)
			$(this).prepend("<div class='iconizer' style='position:absolute;top:5px;right:5px;width:13px;height:13px;display:block;background:url(\"images/iconizer.jpg\");overflow:hidden;'></div>");
			
			$(this).children(".iconizer").attr("config", config); // Store the config in the object
			
			$(this).children(".iconizer").click(function() {
				var nonfig = $(this).parent().attr("config");
				if ($(this).parent().parent().hasClass("ui-dialog")) { // This is for UI dialog support
					collapse(nonfig, $(this).parent().parent());
				} else {
					collapse(nonfig, $(this).parent());
				}
			});
			
			if (config.collapsed == true) {
				if ($(this).parent().hasClass("ui-dialog")) {	// This is for UI dialog support
					collapse(config, $(this).parent());
				} else {
					collapse(config, $(this));
				}				
			}
			
			if ($(this).parent().hasClass("ui-dialog")) {
				// Change position of iconizer icon
				$(".iconizer").css("right", "35px");
				$(".iconizer").css("top", "19px");
			}
		});
	}
	
	function rebuild(outer, icon_follow, docked, parent, content_top, content_left, append_to_parent, config) {
		var inner = $(outer).children(".iconizer_content").children();
		config.before_rebuild($(inner));
		if (config.content_top || config.content_left) {
			if (!config.content_top) config.content_top = "0";
			if (!config.content_left) config.content_left = "0";	
			var position = new Object();
			position = {top:config.content_top, left:config.content_left};		
			$(inner).css({'top':position.top + 'px', 'left':position.left + 'px'});
		} else if (icon_follow == true) {
			// Sets the content position according to the location of the icon
			var position = $(outer).position();
			$(inner).css({'top':position.top + 'px', 'left':position.left + 'px'});
		}
		if (append_to_parent == true) {
			$(parent).append(inner);
		} else {
			$(parent).prepend(inner);
		}
		$(outer).remove();
		$(inner).css('display', 'block');
		$(inner).removeClass("iconized"); // For querying purposes if you want to check if your content is currently iconized
		config.after_rebuild($(inner));
	}

	function collapse(config, content) {
		config.before_collapse($(content));
		$(content).addClass("iconized"); // For querying purposes if you want to check if your content is currently iconized

		/*** Set the icon position according to the content or co-ordinates specified ***/
		if (config.icon_top || config.icon_left) {
			if (!config.icon_top) config.icon_top = "0";
			if (!config.icon_left) config.icon_left = "0";
			var position = new Object();
			position = {top:config.icon_top, left:config.icon_left};
		} else {
			var position = $(content).position(); // Current position
		}
		
		var parent = $(content).parent(); // Parent of the item
			
		/*** Place icon div around our content ***/
		$(content).wrap("<div class='iconizer_outer' style='background:url(\"./images/" + config.icon + "\");width:32px;height:32px;display:block;top:" + position.top + "px;left:" + position.left + "px;position:absolute;'><div class='iconizer_content' style='display:none;'></div></div>");
		
		/*** Dock item if a dock is specified ***/
		if (config.dock != false) {
			// Add this item to the dock
			config.icon_follow = false;
			$(content).parent().parent(".iconizer_outer").css({"top":"", "left":""}); // Remove positioning from the parent area so that it sits inside the dock
			
			if (config.dock_sortable == true) {
				// Place this item in the sortable list
				$(content).parent().parent(".iconizer_outer").wrap("<li style='height:29px;width:29px;overflow:hidden;display:block;'></li>");
				if (config.append_to_dock == true) {
					$(config.dock).append($(content).parent().parent(".iconizer_outer").parent());
				} else {
					$(config.dock).prepend($(content).parent().parent(".iconizer_outer").parent());
				}
			} else {
				// Place this item on the dock
				if (config.append_to_dock == true) {
					$(config.dock).append($(content).parent().parent(".iconizer_outer"));
				} else {
					$(config.dock).prepend($(content).parent().parent(".iconizer_outer"));
				}
			}
		}
		
		/*** Set the icon to draggable and contain it in its parent if it is dockable ***/
		if (config.icon_draggable == true) {
			if (config.dock != false) {
				$(content).parent().parent(".iconizer_outer").draggable({ containment: 'parent' });
			} else {
				$(content).parent().parent(".iconizer_outer").draggable({ zIndex: 3000 });
			}
		}
		
		/*** Determine how the original content is rebuilt when the icon is clicked ***/
		$(content).parent().parent(".iconizer_outer").dblclick(function() {
			if (config.dock_sortable == true) {
				// Need to ensure that the list element parent is also removed before rebuilding
				$(this).parent("li").after(this).remove();
			}
			if ((config.icon_draggable == true)  && (config.icon_follow == true)) {
				rebuild(this, true, false, parent, config.content_top, config.content_left, config.append_to_parent, config);
			} else {
				if (config.dock != "false") {
					rebuild(this, false, true, parent, config.content_top, config.content_left, config.append_to_parent, config);
				} else {
					rebuild(this, false, false, parent, config.content_top, config.content_left, config.append_to_parent, config);
				}
			}
		});
		
		config.after_collapse($(content));
	}	
})(jQuery);