/**
 * @author Leonard Martin <leonard.martin@heathwallace.com>
 * @author Luke Cuthbertson <luke.cuthbertson@heathwallace.com>
 * @version 1.3.3
 */

(function($){

	$.fn.accordion = function(options) {
		var $this = $(this);

		var defaults = {
			node: 		'div.node',
			heading:	'h2',
			content:	'div.content',
			open:		'open',
			speed:		'slow',
			update:		[],
			forceClose:	true,
			blockLinks:	true
		};
		
		var opts = $.extend(defaults, options);
		
		return $(this).each(function(){
			var nodes = $(opts.node,this);
			var openElm = null;
	
			//if you do not supply a node - then all nodes will close/open
			$(this).bind('close', function(e, node){
				closeElem(node,function(){
					update(node,true);
					openElm = null;
				});
			})
			$(this).bind('open', function(e, node){
				var n = nodes || $(node);
				n.each(function(){
					if(!$(this).data('open'))
					if(toggleElem(this)) {
						openElm = this;
					}					
				});
			})			
			
			nodes.each(function(){

				var obj = this;

				
				
				setDims(this);
				
				if($(this).hasClass(opts.open) && (!openElm || !opts.forceClose)) {
					openElm = obj;
					update(obj,true);
					setTimeout(function(){$this.trigger('onopen',obj);}, 0);
					$(this).data('open', true);
					$(this).data('closed', false);
				}
				else {
					$(this).removeClass(opts.open);
					$(opts.content,this).hide();
					update(obj,false);
					setTimeout(function(){$this.trigger('onclose',obj);}, 0);
					$(this).data('open', false);
					$(this).data('closed', true);
				};
				
				//make sure the content is relatively positioned - IE
				$(opts.content, obj).css('position', 'relative');
				
				$(this).find(opts.heading)
					.each(function(i){
						if($(this).attr('checked')){
							/**
							 * @todo set open/closed
							 */
						};
					})
					.css({cursor:'pointer'})
					.click(function(e){
						//FF fires click event on input as well as label, IE does not
						//to even out cancel event on label and manually trigger event on input
						var tag = $(this).attr('nodeName').toLowerCase();
						var type = $(this).attr('type');
						if(tag == 'label'){
							$('#'+$(this).attr('htmlFor')).click();
							return false;
						};
						//

						if(openElm && openElm != obj && opts.forceClose) {
							closeElem(openElm,function(){
								if(toggleElem(obj)) {
									openElm = obj;
								}
							});
						}
						else {		
							if (openElm && $this.find(opts.heading).attr('type') == 'radio') {
								return;
							};								
							if(toggleElem(obj)) {
								openElm = obj;
								//update(obj,true);
							};
						};
						//cancel default on things that would cause page to reload
						if (tag == 'a' || tag == 'input' && type == 'submit') {
							return false;
						};
						return false;
					})
					.find('a').each(function(){
						if(opts.blockLinks) {
							$(this).click(function(e){e.preventDefault();});
						};
					});
					
			});
		});
		
		function setDims(node) {
			$(opts.content,node)
				.show()
				/*.each(function(){
					var w = this.offsetWidth,
						h = this.offsetHeight;
					$(this).css({width:w+'px',height:h+'px'});
				});*/
			if (!$(node).hasClass(opts.open)) {
				$(opts.content,node).hide();
			};
			
		};
		
		function closeElem(node,callback) {
			if ($(opts.content, node||$this).length > 0) {
				$(opts.content, node||$this).slideUp(opts.speed, function(){
					$this.trigger('onclose',node);
					if (node) {
						$(node)
						.data('open', false)
						.removeClass(opts.open);
					}
					else{
						$this
						.find(opts.node)
						.data('open', false)
						.removeClass(opts.open);
					}					
					callback();
				});
			}
			else{
				$(node).removeClass(opts.open);
				$this.trigger('onclose',node)
				callback();				
			};
			update(node,false);
		};
		
		function update(node,isopen) {
			for(var i=0;i<opts.update.length;i++) {
				$(opts.update[i].selector,node).html(opts.update[i].text[isopen?0:1]).click(function(e){e.preventDefault()});
			};
		};
		
		function toggleElem(node) {
			if(!$(node).data('open')){
				$(node).addClass(opts.open);
				$this.trigger('onopen',node);
			};
			$(node).data('open', !$(node).data('open'))
			if ($(opts.content, node).length > 0) {
				if ($(node).data('open')) {
					$(opts.content, node).slideDown(opts.speed, function(){
						$('*', node).css({
							height: ''
						});
					});
				}
				else{
					$(opts.content, node).slideUp(opts.speed, function(){
						if (!$(node).data('open')) {
							$(node).removeClass(opts.open);
							$this.trigger('onclose', node);
						}
					});	
				}
			}
			update(node,$(node).data('open'));
			return open;
		};
		
	};

})(jQuery);
