// Copyright (c) 20011 REDF (jhulbert AT redf DOT com || http://www.redf.com)
// Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
// and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
(function($) {
	var opts = new Array(),
		defaultHeight = 0;

	var methods = {
		init: function(options) {
			opts = $.extend({
				accordion: "dl.accordion",
				defaultOpen:0,
				contentHeight:200,
				scrollContent:true
			}, options);

			var accordion = $(opts.accordion);
			// We loop through these to handle multiple accordions on the same page
			accordion.each(function(i, a) {
				methods.setup(a);
			});
		},
		
		setup: function(accRef) {
			var accObj = $(accRef),
				dt = accObj.find("dt"),
				dd = accObj.find("dd"),
				singleItem = false,
				minHeight = 0;
			
			if(dt.length == 1) singleItem = true;
			
			dt.filter(":first").addClass("active");
			dt.each(function(i) {
				if(singleItem == false) {
					$(this).prepend("<span></span>");
					$(this).css({
						"cursor": "pointer"
					}).click(function() {
						accObj.find(".active").removeClass("active");
						$(this).addClass("active").next("dd").show();
						dt.filter(":not('.active')").next("dd").hide();
					});
				}
			});
			dd.each(function(i, ddEl) {
				defaultHeight = $(ddEl).height();
				$(ddEl).hide();
				// Open the specified default
				if(i == opts.defaultOpen) {
					$(ddEl).show();
				}
				if(opts.contentHeight < defaultHeight && opts.scrollContent == true) {
					// Elements that need a scrollbar
					methods.addScrollBar(ddEl);
				} else {
					// Elements that don't need a scrollbar
					$(ddEl).addClass("fixed");
				}
				// Get a minimum height for fixed height elements
				if($(ddEl).hasClass("fixed") && $(ddEl).height() > minHeight) {
					minHeight = $(ddEl).height();
				}
			});
			// Add minimum height
			dd.filter(".fixed").height(minHeight);
		},
		
		addScrollBar:function(content) {
			var scroller = $("<div class='scroller' \>"),
				scrollBar = $("<div class='scroll-bar' \>"),
				scrollBtn = $("<button class='scroll-btn' \>").appendTo(scrollBar),
				outerDiff = $(content).outerHeight() - defaultHeight,
				scrollHeight = opts.contentHeight + outerDiff,
				activeScroll = null,
				btnPos = 0,
				scrPos = 0;
			
			// Wrap content in scroller
			$(content).wrapInner(scroller);
			// Add scrollbar
			$(content).append(scrollBar);
			// Set standard height based on contentHeight option.
			// Hide overflow for scrolling
			$(content).css({
				"height":scrollHeight,
				"overflow":"hidden"
			});
			scrollBar.height(scrollHeight);
			scrollBtn.height(Math.round((scrollHeight / defaultHeight) * scrollHeight));
			// Attach scrollContent method
			scrollBtn.mousedown(function(evt) {
				btnPos = evt.pageY - scrollBar.offset().top;
				scrollBtn.bind("mousemove", function(evt) {
					activeScroller = $(evt.currentTarget).parent().prev(".scroller");
					scrPos = Math.floor((evt.pageY - scrollBar.offset().top) - btnPos);
					if(scrPos <= 0) {
						scrPos = 0;
					} else if(scrPos >= scrollBar.height() - scrollBtn.height()) {
						scrPos = scrollBar.height() - scrollBtn.height();
					}
					scrollBtn.css("top", scrPos);
					scrollRatio = scrollHeight / scrollBtn.height();
					activeScroller.css({
						"top": -(scrPos*scrollRatio)
					});
					
				}).bind("mouseup mouseleave", function(evt) {
					try {
						scrollBtn.unbind("mousemove");
					} catch(e) {
						
					}
				})
			});
		}
	};

	$.fn.accordion = function(method) {
		if (methods[method]) {
			return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		} else if (typeof method === 'object' || !method) {
			return methods.init.apply(this, arguments);
		} else {
			$.error('The method "' + method + '" does not exist in jQuery.accordion');
		}
	};

})(jQuery);
