/**
 * layoutpanel - jQuery EasyUI
 * 
 * Licensed under the GPL:
 *   http://www.gnu.org/licenses/gpl.txt
 *
 * Copyright 2010 stworthy [ stworthy@gmail.com ] 
 * 
 */
(function($){
	function removeNode(node){
		node.each(function(){
			$(this).remove();
			if ($.browser.msie){
				this.outerHTML = '';
			}
		});
	}
	
	function setSize(target, param){
		var opts = $.data(target, 'layoutpanel').options;
		var layoutpanel = $.data(target, 'layoutpanel').layoutpanel;
		var pheader = layoutpanel.find('>div.layoutpanel-header');
		var pbody = layoutpanel.find('>div.layoutpanel-body');
		
		if (param){
			if (param.width) opts.width = param.width;
			if (param.height) opts.height = param.height;
			if (param.left != null) opts.left = param.left;
			if (param.top != null) opts.top = param.top;
		}
		
		if (opts.fit == true){
			var p = layoutpanel.parent();
			opts.width = p.width();
			opts.height = p.height();
		}
		layoutpanel.css({
			left: opts.left,
			top: opts.top
		});
		layoutpanel.css(opts.style);
		layoutpanel.addClass(opts.cls);
		pheader.addClass(opts.headerCls);
		pbody.addClass(opts.bodyCls);
		
		if (!isNaN(opts.width)){
			if ($.boxModel == true){
				layoutpanel.width(opts.width - (layoutpanel.outerWidth() - layoutpanel.width()));
				pheader.width(layoutpanel.width() - (pheader.outerWidth() - pheader.width()));
				pbody.width(layoutpanel.width() - (pbody.outerWidth() - pbody.width()));
			} else {
				layoutpanel.width(opts.width);
				pheader.width(layoutpanel.width());
				pbody.width(layoutpanel.width());
			}
		} else {
			layoutpanel.width('auto');
			pbody.width('auto');
		}
		if (!isNaN(opts.height)){
//			var height = opts.height - (layoutpanel.outerHeight()-layoutpanel.height()) - pheader.outerHeight();
//			if ($.boxModel == true){
//				height -= pbody.outerHeight() - pbody.height();
//			}
//			pbody.height(height);
			
			if ($.boxModel == true){
				layoutpanel.height(opts.height - (layoutpanel.outerHeight() - layoutpanel.height()));
				pbody.height(layoutpanel.height() - pheader.outerHeight() - (pbody.outerHeight() - pbody.height()));
			} else {
				layoutpanel.height(opts.height);
				pbody.height(layoutpanel.height() - pheader.outerHeight());
			}
		} else {
			pbody.height('auto');
		}
		layoutpanel.css('height', null);
		
		opts.onResize.apply(target, [opts.width, opts.height]);
		
		layoutpanel.find('>div.layoutpanel-body>div').triggerHandler('_resize');
	}
	
	function movelayoutpanel(target, param){
		var opts = $.data(target, 'layoutpanel').options;
		var layoutpanel = $.data(target, 'layoutpanel').layoutpanel;
		if (param){
			if (param.left != null) opts.left = param.left;
			if (param.top != null) opts.top = param.top;
		}
		layoutpanel.css({
			left: opts.left,
			top: opts.top
		});
		opts.onMove.apply(target, [opts.left, opts.top]);
	}
	
	function wraplayoutpanel(target){
		var layoutpanel = $(target).addClass('layoutpanel-body').wrap('<div class="layoutpanel"></div>').parent();
		layoutpanel.bind('_resize', function(){
			var opts = $.data(target, 'layoutpanel').options;
			if (opts.fit == true){
				setSize(target);
			}
			return false;
		});
		
		return layoutpanel;
	}
	
	function addHeader(target){
		var opts = $.data(target, 'layoutpanel').options;
		var layoutpanel = $.data(target, 'layoutpanel').layoutpanel;
		removeNode(layoutpanel.find('>div.layoutpanel-header'));
		if (opts.title && !opts.noheader){
			var header = $('<div class="layoutpanel-header"><div class="layoutpanel-title">'+opts.title+'</div></div>').prependTo(layoutpanel);
			if (opts.iconCls){
				header.find('.layoutpanel-title').addClass('layoutpanel-with-icon');
				$('<div class="layoutpanel-icon"></div>').addClass(opts.iconCls).appendTo(header);
			}
			var tool = $('<div class="layoutpanel-tool"></div>').appendTo(header);
			if (opts.closable){
				$('<div class="layoutpanel-tool-close"></div>').appendTo(tool).bind('click', onClose);
			}
			if (opts.maximizable){
				$('<div class="layoutpanel-tool-max"></div>').appendTo(tool).bind('click', onMax);
			}
			if (opts.minimizable){
				$('<div class="layoutpanel-tool-min"></div>').appendTo(tool).bind('click', onMin);
			}
			if (opts.collapsible){
				$('<div class="layoutpanel-tool-collapse"></div>').appendTo(tool).bind('click', onToggle);
			}
			if (opts.tools){
				for(var i=opts.tools.length-1; i>=0; i--){
					var t = $('<div></div>').addClass(opts.tools[i].iconCls).appendTo(tool);
					if (opts.tools[i].handler){
						t.bind('click', eval(opts.tools[i].handler));
					}
				}
			}
			tool.find('div').hover(
				function(){$(this).addClass('layoutpanel-tool-over');},
				function(){$(this).removeClass('layoutpanel-tool-over');}
			);
			layoutpanel.find('>div.layoutpanel-body').removeClass('layoutpanel-body-noheader');
		} else {
			layoutpanel.find('>div.layoutpanel-body').addClass('layoutpanel-body-noheader');
		}
		
		function onToggle(){
			if ($(this).hasClass('layoutpanel-tool-expand')){
				expandlayoutpanel(target, true);
			} else {
				collapselayoutpanel(target, true);
			}
			return false;
		}
		
		function onMin(){
			minimizelayoutpanel(target);
			return false;
		}
		
		function onMax(){
			if ($(this).hasClass('layoutpanel-tool-restore')){
				restorelayoutpanel(target);
			} else {
				maximizelayoutpanel(target);
			}
			return false;
		}
		
		function onClose(){
			closelayoutpanel(target);
			return false;
		}
	}
	
	/**
	 * load content from remote site if the href attribute is defined
	 */
	function loadData(target){
		var state = $.data(target, 'layoutpanel');
		if (state.options.href && (!state.isLoaded || !state.options.cache)){
			state.isLoaded = false;
			var pbody = state.layoutpanel.find('>div.layoutpanel-body');
			pbody.html($('<div class="layoutpanel-loading"></div>').html(state.options.loadingMessage));
			pbody.load(state.options.href, null, function(){
				if ($.parser){
					$.parser.parse(pbody);
				}
				state.options.onLoad.apply(target, arguments);
				state.isLoaded = true;
			});
		}
	}
	
	function openlayoutpanel(target, forceOpen){
		var opts = $.data(target, 'layoutpanel').options;
		var layoutpanel = $.data(target, 'layoutpanel').layoutpanel;
		
		if (forceOpen != true){
			if (opts.onBeforeOpen.call(target) == false) return;
		}
		layoutpanel.show();
		opts.closed = false;
		opts.onOpen.call(target);
		
		if (opts.maximized == true) maximizelayoutpanel(target);
		if (opts.minimized == true) minimizelayoutpanel(target);
		if (opts.collapsed == true) collapselayoutpanel(target);
		
		if (!opts.collapsed){
			loadData(target);
		}
	}
	
	function closelayoutpanel(target, forceClose){
		var opts = $.data(target, 'layoutpanel').options;
		var layoutpanel = $.data(target, 'layoutpanel').layoutpanel;
		
		if (forceClose != true){
			if (opts.onBeforeClose.call(target) == false) return;
		}
		layoutpanel.hide();
		opts.closed = true;
		opts.onClose.call(target);
	}
	
	function destroylayoutpanel(target, forceDestroy){
		var opts = $.data(target, 'layoutpanel').options;
		var layoutpanel = $.data(target, 'layoutpanel').layoutpanel;
		
		if (forceDestroy != true){
			if (opts.onBeforeDestroy.call(target) == false) return;
		}
		removeNode(layoutpanel);
		opts.onDestroy.call(target);
	}
	
	function collapselayoutpanel(target, animate){
		var opts = $.data(target, 'layoutpanel').options;
		var layoutpanel = $.data(target, 'layoutpanel').layoutpanel;
		var body = layoutpanel.find('>div.layoutpanel-body');
		var tool = layoutpanel.find('>div.layoutpanel-header .layoutpanel-tool-collapse');
		
		if (tool.hasClass('layoutpanel-tool-expand')) return;
		
		body.stop(true, true);	// stop animation
		if (opts.onBeforeCollapse.call(target) == false) return;
		
		tool.addClass('layoutpanel-tool-expand');
		if (animate == true){
			body.slideUp('normal', function(){
				opts.collapsed = true;
				opts.onCollapse.call(target);
			});
		} else {
			body.hide();
			opts.collapsed = true;
			opts.onCollapse.call(target);
		}
	}
	
	function expandlayoutpanel(target, animate){
		var opts = $.data(target, 'layoutpanel').options;
		var layoutpanel = $.data(target, 'layoutpanel').layoutpanel;
		var body = layoutpanel.find('>div.layoutpanel-body');
		var tool = layoutpanel.find('>div.layoutpanel-header .layoutpanel-tool-collapse');
		
		if (!tool.hasClass('layoutpanel-tool-expand')) return;
		
		body.stop(true, true);	// stop animation
		if (opts.onBeforeExpand.call(target) == false) return;
		
		tool.removeClass('layoutpanel-tool-expand');
		if (animate == true){
			body.slideDown('normal', function(){
				opts.collapsed = false;
				opts.onExpand.call(target);
				loadData(target);
			});
		} else {
			body.show();
			opts.collapsed = false;
			opts.onExpand.call(target);
			loadData(target);
		}
	}
	
	function maximizelayoutpanel(target){
		var opts = $.data(target, 'layoutpanel').options;
		var layoutpanel = $.data(target, 'layoutpanel').layoutpanel;
		var tool = layoutpanel.find('>div.layoutpanel-header .layoutpanel-tool-max');
		
		if (tool.hasClass('layoutpanel-tool-restore')) return;
		
		tool.addClass('layoutpanel-tool-restore');
		
		$.data(target, 'layoutpanel').original = {
			width: opts.width,
			height: opts.height,
			left: opts.left,
			top: opts.top,
			fit: opts.fit
		};
		opts.left = 0;
		opts.top = 0;
		opts.fit = true;
		setSize(target);
		opts.minimized = false;
		opts.maximized = true;
		opts.onMaximize.call(target);
	}
	
	function minimizelayoutpanel(target){
		var opts = $.data(target, 'layoutpanel').options;
		var layoutpanel = $.data(target, 'layoutpanel').layoutpanel;
		layoutpanel.hide();
		opts.minimized = true;
		opts.maximized = false;
		opts.onMinimize.call(target);
	}
	
	function restorelayoutpanel(target){
		var opts = $.data(target, 'layoutpanel').options;
		var layoutpanel = $.data(target, 'layoutpanel').layoutpanel;
		var tool = layoutpanel.find('>div.layoutpanel-header .layoutpanel-tool-max');
		
		if (!tool.hasClass('layoutpanel-tool-restore')) return;
		
		layoutpanel.show();
		tool.removeClass('layoutpanel-tool-restore');
		var original = $.data(target, 'layoutpanel').original;
		opts.width = original.width;
		opts.height = original.height;
		opts.left = original.left;
		opts.top = original.top;
		opts.fit = original.fit;
		setSize(target);
		opts.minimized = false;
		opts.maximized = false;
		opts.onRestore.call(target);
	}
	
	function setBorder(target){
		var opts = $.data(target, 'layoutpanel').options;
		var layoutpanel = $.data(target, 'layoutpanel').layoutpanel;
		if (opts.border == true){
			layoutpanel.find('>div.layoutpanel-header').removeClass('layoutpanel-header-noborder');
			layoutpanel.find('>div.layoutpanel-body').removeClass('layoutpanel-body-noborder');
		} else {
			layoutpanel.find('>div.layoutpanel-header').addClass('layoutpanel-header-noborder');
			layoutpanel.find('>div.layoutpanel-body').addClass('layoutpanel-body-noborder');
		}
	}
	
	function setTitle(target, title){
		$.data(target, 'layoutpanel').options.title = title;
		$(target).layoutpanel('header').find('div.layoutpanel-title').html(title);
	}
	
	$(window).unbind('.layoutpanel').bind('resize.layoutpanel', function(){
		var layout = $('body.layout');
		if (layout.length){
			layout.layout('resize');
		} else {
			$('body>div.layoutpanel').triggerHandler('_resize');
		}
	});
	
	$.fn.layoutpanel = function(options, param){
		if (typeof options == 'string'){
			switch(options){
			case 'options':
				return $.data(this[0], 'layoutpanel').options;
			case 'layoutpanel':
				return $.data(this[0], 'layoutpanel').layoutpanel;
			case 'header':
				return $.data(this[0], 'layoutpanel').layoutpanel.find('>div.layoutpanel-header');
			case 'body':
				return $.data(this[0], 'layoutpanel').layoutpanel.find('>div.layoutpanel-body');
			case 'setTitle':
				return this.each(function(){
					setTitle(this, param);
				});
			case 'open':
				return this.each(function(){
					openlayoutpanel(this, param);
				});
			case 'close':
				return this.each(function(){
					closelayoutpanel(this, param);
				});
			case 'destroy':
				return this.each(function(){
					destroylayoutpanel(this, param);
				});
			case 'refresh':
				return this.each(function(){
					$.data(this, 'layoutpanel').isLoaded = false;
					loadData(this);
				});
			case 'resize':
				return this.each(function(){
					setSize(this, param);
				});
			case 'move':
				return this.each(function(){
					movelayoutpanel(this, param);
				});
			case 'maximize':
				return this.each(function(){
					maximizelayoutpanel(this);
				});
			case 'minimize':
				return this.each(function(){
					minimizelayoutpanel(this);
				});
			case 'restore':
				return this.each(function(){
					restorelayoutpanel(this);
				});
			case 'collapse':
				return this.each(function(){
					collapselayoutpanel(this, param);	// param: boolean,indicate animate or not
				});
			case 'expand':
				return this.each(function(){
					expandlayoutpanel(this, param);	// param: boolean,indicate animate or not
				});
			}
		}
		
		options = options || {};
		return this.each(function(){
			var state = $.data(this, 'layoutpanel');
			var opts;
			if (state){
				opts = $.extend(state.options, options);
			} else {
				var t = $(this);
				opts = $.extend({}, $.fn.layoutpanel.defaults, {
					width: (parseInt(t.css('width')) || undefined),
					height: (parseInt(t.css('height')) || undefined),
					left: (parseInt(t.css('left')) || undefined),
					top: (parseInt(t.css('top')) || undefined),
					title: t.attr('title'),
					iconCls: t.attr('icon'),
					cls: t.attr('cls'),
					headerCls: t.attr('headerCls'),
					bodyCls: t.attr('bodyCls'),
					href: t.attr('href'),
					cache: (t.attr('cache') ? t.attr('cache') == 'true' : undefined),
					fit: (t.attr('fit') ? t.attr('fit') == 'true' : undefined),
					border: (t.attr('border') ? t.attr('border') == 'true' : undefined),
					noheader: (t.attr('noheader') ? t.attr('noheader') == 'true' : undefined),
					collapsible: (t.attr('collapsible') ? t.attr('collapsible') == 'true' : undefined),
					minimizable: (t.attr('minimizable') ? t.attr('minimizable') == 'true' : undefined),
					maximizable: (t.attr('maximizable') ? t.attr('maximizable') == 'true' : undefined),
					closable: (t.attr('closable') ? t.attr('closable') == 'true' : undefined),
					collapsed: (t.attr('collapsed') ? t.attr('collapsed') == 'true' : undefined),
					minimized: (t.attr('minimized') ? t.attr('minimized') == 'true' : undefined),
					maximized: (t.attr('maximized') ? t.attr('maximized') == 'true' : undefined),
					closed: (t.attr('closed') ? t.attr('closed') == 'true' : undefined)
				}, options);
				t.attr('title', '');
				state = $.data(this, 'layoutpanel', {
					options: opts,
					layoutpanel: wraplayoutpanel(this),
					isLoaded: false
				});
			}
			
			if (opts.content){
				$(this).html(opts.content);
				if ($.parser){
					$.parser.parse(this);
				}
			}
			
			addHeader(this);
			setBorder(this);
//			loadData(this);
			
			if (opts.doSize == true){
				state.layoutpanel.css('display','block');
				setSize(this);
			}
			if (opts.closed == true){
				state.layoutpanel.hide();
			} else {
				openlayoutpanel(this);
			}
		});
	};
	
	$.fn.layoutpanel.defaults = {
		title: null,
		iconCls: null,
		width: 'auto',
		height: 'auto',
		left: null,
		top: null,
		cls: null,
		headerCls: null,
		bodyCls: null,
		style: {},
		href: null,
		cache: true,
		fit: false,
		border: true,
		doSize: true,	// true to set size and do layout
		noheader: false,
		content: null,	// the body content if specified
		
		collapsible: false,
		minimizable: false,
		maximizable: false,
		closable: false,
		collapsed: false,
		minimized: false,
		maximized: false,
		closed: false,
		
		// custom tools, every tool can contain two properties: iconCls and handler
		// iconCls is a icon CSS class
		// handler is a function, which will be run when tool button is clicked
		tools: [],	
		
		href: null,
		loadingMessage: 'Loading...',
		onLoad: function(){},
		onBeforeOpen: function(){},
		onOpen: function(){},
		onBeforeClose: function(){},
		onClose: function(){},
		onBeforeDestroy: function(){},
		onDestroy: function(){},
		onResize: function(width,height){},
		onMove: function(left,top){},
		onMaximize: function(){},
		onRestore: function(){},
		onMinimize: function(){},
		onBeforeCollapse: function(){},
		onBeforeExpand: function(){},
		onCollapse: function(){},
		onExpand: function(){}
	};
})(jQuery);
