/* Copyright (c) 2010 Josef Freundorfer (josef@freundorfer.info || http://www.freundorfer.info) 
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * Version: 0.1b1
 */




jQuery.fn.customScrollbar = function(settings) {
	settings = jQuery.extend( {
		scollerWidth : 20
	}, settings);
	return this
			.each(function() {
				var scrollTopOverflow = function() {
					var o_h = scrollable_content.outerHeight(true);
					var marg_t = parseInt($(scrollable_content.children().get(0)).css('margin-top'));
					if (marg_t == Number.NaN)
						marg_t = 0;
					var marg_b = parseInt($(scrollable_content.children().slice(-1)).css('margin-bottom'));
					if (marg_b == Number.NaN)
						marg_b = 0;
					var i_h = scrollable.innerHeight();
					return o_h + marg_t + marg_b - i_h;
				};
				var scrollTopPercent = function(e) {
					var t = e.scrollTop();
					var p = scrollTopOverflow();
					return t / p;
				};
				var clearTimers = function() {
					if (intervals.up != false) {
						window.clearInterval(intervals.up);
						intervals.up = false;
					}
					if (intervals.down != false) {
						window.clearInterval(intervals.down);
						intervals.down = false;
					}
					if (timeouts.up != false) {
						window.clearInterval(timeouts.up);
						timeouts.up = false;
					}
					if (timeouts.down != false) {
						window.clearInterval(timeouts.down);
						timeouts.down = false;
					}
				};

				var s = function(value, moveSelector, scroller) {
					var before = scrollable.scrollTop();
					scrollable.scrollTop(before + value);
					if (before == scrollable.scrollTop())
						clearTimers();
					if (moveSelector) {
						var ma_h = move_area.innerHeight();
						var m_h = mover.outerHeight();
						var t2 = parseInt((ma_h - m_h) * scrollTopPercent(scrollable));
						mover.css('top', t2 + 'px');
					}
				};

				/*
				 * Events
				 */
				var eventArrowBottomMouseDown = function() {
					clearTimers();
					s(step, true);
					timeouts.down = window.setTimeout(function() {
						intervals.down = window.setInterval(function() {
							s(step / 5, true);
						}, 10);
					}, 300);
				};
				var eventArrowTopMouseDown = function() {
					clearTimers();
					s(-step, true);
					timeouts.up = window.setTimeout(function() {
						intervals.up = window.setInterval(function() {
							s(-step / 5, true);
						}, 10);
					}, 300);
				};
				var eventKeyPress = function(event) {
					clearTimers();
					if(!hover)
						return;
					switch (event.keyCode) {
					case 38: // up
						s(-step, true);
						break;
					case 40: // down
						s(step, true);
						break;
					case 33: // page up
						s(-(3 * step), true);
						break;
					case 34: // page down
						s((3 * step), true);
						break;
					default:
						return;
					}
					event.preventDefault();
				};
				var eventMouseWheel = function(event, delta) {
					clearTimers();
					s(-delta * step, true);
					event.preventDefault();
				};
				var eventMoverMouseDown = function(event) {
					clearTimers();
					md = true;
					md_y = event.pageY;
					start_y = parseInt(mover.css('top'));
					scrollOverflow = scrollTopOverflow();
					event.preventDefault();
				};
				var eventMouseMove = function(event) {
					if (md == true) {
						console.log('in' + moveable_height);
						var new_y = start_y + event.pageY - md_y;
						new_y = (new_y < 0 ? 0 : new_y > moveable_height ? moveable_height : new_y);
						mover.css('top', new_y + 'px');
						scrollable.scrollTop(new_y * (scrollOverflow / moveable_height));
					}
				};
				var eventMouseUp = function() {
					md = false;
					clearTimers();
				};
				var eventMoveAreaClick = function(event) {
					clearTimers();
					if (mover.offset().top > event.pageY)
						s(-(3 * step), true);
					if (mover.offset().top + mover.outerHeight() < event.pageY)
						s((3 * step), true);
					event.preventDefault();
				};
				var eventMoverClick = function(event) {
					event.stopPropagation();
				};

				var eventResize = function() {
					if (scrollable.css('position') == 'absolute') {
						scroller.css( {
							'position' : 'absolute',
							'left' : scrollable.position().left + scrollable.outerWidth() - settings.scollerWidth,
							'height' : scrollable.outerHeight(),
							'top' : scrollable.position().top,
							'width' : settings.scollerWidth + 'px'
						});
					} else {
						scroller.css( {
							'position' : 'relative',
							'left' : $(this).outerWidth() - settings.scollerWidth,
							'height' : $(this).outerHeight(),
							'top' : '-' + $(this).outerHeight(),
							'width' : settings.scollerWidth + 'px'
						});
					}

					if (scrollTopOverflow() <= 0) {
						scroller.hide();
					} else {
						scroller.show();
					}
					moveable_height = move_area.innerHeight() - mover.outerHeight();
				};
				
				var registerEvents = function() {
					arrow_bottom.mousedown(eventArrowBottomMouseDown);
					arrow_top.mousedown(eventArrowTopMouseDown);
					scrollable.mousewheel(eventMouseWheel);
					scroller.mousewheel(eventMouseWheel);
					mover.mousedown(eventMoverMouseDown);
					mover.click(eventMoverClick);
					move_area.click(eventMoveAreaClick);

					scrollable.mouseover(function() { hover=true; });
					scroller.mouseover(function() { hover=true; });
					scrollable.mouseout(function() { hover=false; });
					scroller.mouseout(function() { hover=false; });
					
					$(document).keypress(eventKeyPress);
					$(document).mouseup(eventMouseUp);
					$(document).mousemove(eventMouseMove);
					//window.setInterval(eventResize,100);
					$(window).resize(eventResize);
				};
				

				var createScroller = function() {
					scrollable.css('overflow', 'hidden');

					var tmp = $(document.createElement("div"));
					scrollable.wrapInner(tmp);
					scrollable_content = $(scrollable.children().get(0));

					arrow_top =  $(document.createElement("div")).addClass('arrow_top');
					arrow_bottom =  $(document.createElement("div")).addClass('arrow_bottom');
					mover =  $(document.createElement("div")).addClass('mover');
					move_area =  $(document.createElement("div")).addClass('mover_area');
					scroller = $(document.createElement("div")).addClass('scroller');
					
					move_area.append(mover);
					scroller.append(arrow_top);
					scroller.append(arrow_bottom);
					scroller.append(move_area);
				
				};


				var md = false;
				var md_y;
				var start_y;
				var moveable_height;
				var scrollOverflow;
				var hover=false;
				
				var step = 16;
				var timeouts = {
					up : false,
					down : false
				};
				var intervals = {
					up : false,
					down : false
				};

				
				var scrollable = $(this);
				var scrollable_content;
				var arrow_top;
				var arrow_bottom;
				var mover;
				var move_area;
				var scroller;
				
				createScroller();
				eventResize();
				registerEvents();
				$(this).after(scroller);


			});
};
