/**
 * @id ScrollBar
 * @classDescription Creates and attaches a scrollbar to a DOM element
 * @param {Object} constructor
 * @type {Object} attachTo: DOM element
 */
function ScrollBar(constructor) {
// constructor
// .attachTo: [div]
// .withParentForControl
// Sample usage:
// 	var foo = new ScrollBar({attachTo: document.getElementById('bar')});

	this.repositionScrollHandle = repositionScrollHandle;
	this.getContainerID = getContainerID;

	var uniqueId = (new Date).getTime();
	var scrollBarContainer;
	var scrollHandleContainer;
	var scrollHandleOverlay;
	
	var scrollHandleTop;
	var scrollHandleMid;
	var scrollHandleBot;
	
	var isCurrentlyDragging;
	var scrollToAction = true;

	var interpolationObject;

	var yPosDiff;

	var slideToDest = null;

	var pathPrefix = "/img/scrollbar/";

	initWithDiv();

	/**
	 * @id initWithDiv
	 * @constructor
	 * @method
	 * @memberOf ScrollBar
	 */
	function initWithDiv() {
	
		var fileExtension = (navigator.appName.indexOf("Microsoft Internet Explorer") != -1) ? ".gif" : ".png" ;
	
		scrollBarContainer = document.createElement("div");
		scrollBarContainer.id = "id" + constructor.attachTo.id;
		scrollBarContainer.style.position = "absolute";
		scrollBarContainer.style.top	= constructor.attachTo.offsetTop + "px";
		scrollBarContainer.style.left	= (constructor.attachTo.offsetLeft + constructor.attachTo.offsetWidth + 1) + "px";
		scrollBarContainer.style.width	= "16px";
		scrollBarContainer.style.height	= constructor.attachTo.offsetHeight + "px";
		scrollBarContainer.style.zIndex = "0";

			var scrollBarContainerTop = document.createElement("img");
			scrollBarContainerTop.id = scrollBarContainer.id + "ContainerTop"
			scrollBarContainerTop.style.position = "absolute";
			scrollBarContainerTop.style.top = "0px";
			scrollBarContainerTop.style.left = "0px";
			scrollBarContainerTop.src = pathPrefix + "ScrollContainerTop" + fileExtension;
			scrollBarContainerTop.style.zIndex = "0";
			scrollBarContainer.appendChild(scrollBarContainerTop);

			var scrollBarContainerMid = document.createElement("img");
			scrollBarContainerMid.id = scrollBarContainer.id + "ContainerMid"
			scrollBarContainerMid.style.position = "absolute";
			scrollBarContainerMid.style.top = "16px";
			scrollBarContainerMid.style.left = "0px";
			scrollBarContainerMid.src = pathPrefix + "ScrollContainerMiddle" + fileExtension;
			scrollBarContainerMid.height = (constructor.attachTo.offsetHeight - 32);
			scrollBarContainerMid.width = 16;
			scrollBarContainerMid.style.zIndex = "0";
			scrollBarContainer.appendChild(scrollBarContainerMid);

			var scrollBarContainerBot = document.createElement("img");
			scrollBarContainerBot.id = scrollBarContainer.id + "ContainerBot"
			scrollBarContainerBot.style.position = "absolute";
			scrollBarContainerBot.style.top = (constructor.attachTo.offsetHeight - 16) + "px";
			scrollBarContainerBot.style.left = "0px";
			scrollBarContainerBot.src = pathPrefix + "ScrollContainerBottom" + fileExtension;
			scrollBarContainerBot.style.zIndex = "0";
			scrollBarContainer.appendChild(scrollBarContainerBot);
			
		scrollHandleOverlay = document.createElement("div");
		scrollHandleOverlay.id = scrollBarContainer.id + "scrollHandleOverlay";
		scrollHandleOverlay.style.position	= "absolute";
		scrollHandleOverlay.style.top			= "0px";
		scrollHandleOverlay.style.left		= "0px";
		scrollHandleOverlay.style.width		= "16px";
		scrollHandleOverlay.style.height		= parseInt(Math.round((constructor.attachTo.offsetHeight / ((constructor.attachTo.scrollHeight < constructor.attachTo.offsetHeight) ? constructor.attachTo.offsetHeight : constructor.attachTo.scrollHeight)) * constructor.attachTo.offsetHeight)) + "px";
		scrollHandleOverlay.style.zIndex = "2";
		scrollHandleOverlay.style.backgroundColor = "black";
		scrollBarContainer.appendChild(scrollHandleOverlay);

		scrollHandleContainer = document.createElement("div");
		scrollHandleContainer.id = scrollBarContainer.id + "scrollHandleContainer";
		scrollHandleContainer.style.position	= "absolute";
		scrollHandleContainer.style.top			= "0px";
		scrollHandleContainer.style.left		= "0px";
		scrollHandleContainer.style.width		= "16px";
		scrollHandleContainer.style.height		= parseInt(Math.round((constructor.attachTo.offsetHeight / ((constructor.attachTo.scrollHeight < constructor.attachTo.offsetHeight) ? constructor.attachTo.offsetHeight : constructor.attachTo.scrollHeight)) * constructor.attachTo.offsetHeight)) + "px";
		scrollHandleContainer.style.zIndex = "1";

			scrollHandleTop = document.createElement("img");
			scrollHandleTop.id = scrollBarContainer.id + "ScrollHandleTop";
			scrollHandleTop.style.position = "absolute";
			scrollHandleTop.style.top = "0px";
			scrollHandleTop.style.left = "0px";
			scrollHandleTop.src = pathPrefix + "ScrollHandleTop" + fileExtension;
			scrollHandleTop.style.zIndex = "0";
			scrollHandleContainer.appendChild(scrollHandleTop);


			scrollHandleMid = document.createElement("img");
			scrollHandleMid.id = scrollBarContainer.id + "scrollHandleMid";
			scrollHandleMid.style.position = "absolute";
			scrollHandleMid.style.top = "16px";
			scrollHandleMid.style.left = "0px";
			scrollHandleMid.src = pathPrefix + "ScrollHandleMiddle" + fileExtension;
			scrollHandleMid.height = parseInt(Math.round(((constructor.attachTo.offsetHeight / ((constructor.attachTo.scrollHeight < constructor.attachTo.offsetHeight) ? constructor.attachTo.offsetHeight : constructor.attachTo.scrollHeight)) * constructor.attachTo.offsetHeight) - 32));
			scrollHandleMid.width = 16;
			scrollHandleMid.style.zIndex = "0";
			scrollHandleContainer.appendChild(scrollHandleMid);


			scrollHandleBot = document.createElement("img");
			scrollHandleBot.id = scrollBarContainer.id + "scrollHandleBot";
			scrollHandleBot.style.position = "absolute";
			scrollHandleBot.style.top = parseInt(Math.round(((constructor.attachTo.offsetHeight / ((constructor.attachTo.scrollHeight < constructor.attachTo.offsetHeight) ? constructor.attachTo.offsetHeight : constructor.attachTo.scrollHeight)) * constructor.attachTo.offsetHeight) - 16)) + "px";
			scrollHandleBot.style.left = "0px";
			scrollHandleBot.src = pathPrefix + "ScrollHandleBottom" + fileExtension;
			scrollHandleBot.style.zIndex = "0";
			scrollHandleContainer.appendChild(scrollHandleBot);


		scrollBarContainer.appendChild(scrollHandleContainer);
		scrollBarContainer.onclick = ScrollToHandler;

		if (constructor.attachTo.addEventListener)
			constructor.attachTo.addEventListener('DOMMouseScroll', handleScrollWheel, false);
		
		constructor.attachTo.onmousewheel = handleScrollWheel;
		

		if (scrollHandleOverlay.addEventListener) {
		
			scrollHandleOverlay.addEventListener("mousedown",DragHandler,true);
		
		} else if (scrollHandleOverlay.attachEvent) {
		
			scrollHandleOverlay.attachEvent("onmousedown",DragHandler);
			
		} else {

			scrollHandleOverlay.onmousedown = DragHandler;

		}

		((typeof constructor.withParentForControl != 'undefined' && constructor.withParentForControl != null) ? constructor.withParentForControl : document.body).appendChild(scrollBarContainer)

//		document.body.appendChild(scrollBarContainer);
		
		ChangeOpac(0,scrollHandleOverlay.id);

		if (constructor.attachTo.scrollHeight == constructor.attachTo.offsetHeight) {
		
			$("#" + scrollBarContainer.id).toggle();
		
		} else {

			$("#" + scrollBarContainer.id).fadeIn(500);

		}

	}
	
	/**
	 * Handles initial stage of a drag event
	 * @id DragHandler
	 * @param {Object} e
	 * @method
	 * @memberOf ScrollBar
	 */
	function DragHandler(e) {

		if (!e)
			var e = window.event;

		yPosDiff = e.clientY - scrollBarContainer.offsetTop - scrollHandleContainer.offsetTop;

		if (!isCurrentlyDragging) {
			
			isCurrentlyDragging		= true;
			scrollToAction			= false;
			document.onmousemove	= PerformDrag;
			document.onmouseup		= EndDrag;
						
		}
	
	}

	/**
	 * Handles a drag event while it is occurring
	 * @id PerformDrag
	 * @param {Object} e
	 * @memberOf ScrollBar
	 * @method
	 * @return {BOOL}
	 */
	function PerformDrag(e) {

		if (isCurrentlyDragging) {
			
			if (!e)
				var e = window.event;
			
			
			var theYPos = e.clientY - scrollBarContainer.offsetTop;
		
			window.status = theYPos;
		
			theYPos = ((theYPos - yPosDiff) < 0) ? 0 : theYPos - yPosDiff;
			theYPos = ((theYPos + scrollHandleContainer.offsetHeight) > scrollBarContainer.offsetHeight) ? scrollBarContainer.offsetHeight - scrollHandleContainer.offsetHeight : theYPos;

			scrollHandleContainer.style.top = (theYPos) + "px";
			scrollHandleOverlay.style.top = (theYPos) + "px";

			// BEGIN live tracking

			handlePositionInPercent = (theYPos / (scrollBarContainer.offsetHeight - scrollHandleContainer.offsetHeight));			
			constructor.attachTo.scrollTop = handlePositionInPercent * (constructor.attachTo.scrollHeight - constructor.attachTo.offsetHeight);

			// END live tracking
			
			return false;
	
		}

	}

	/**
	 * Finalizes a drag event
	 * @id EndDrag
	 * @param {Object} e
	 * @memberOf ScrollBar
	 */
	function EndDrag(e) {

		if (!e)
			var e = window.event;
	
		if (isCurrentlyDragging) {

			yPosDiff = null;
			isCurrentlyDragging=false;
			scrollToAction = false;

		}

	}
	
	/**
	 * Handles initial stage of a scroll to event / click on the scroll bar background
	 * @id ScrollToHandler
	 * @param {Object} e
	 * @memberOf ScrollBar
	 */
	function ScrollToHandler(e) {

		if (scrollToAction) {

			if (!e)
				var e = window.event;
			
			yPosDiff = scrollHandleContainer.offsetHeight / 2;

			var theYPos = e.clientY - scrollBarContainer.offsetTop;
	
			handlePositionInPercent = (theYPos / (scrollBarContainer.offsetHeight));			
	
			theYPos = handlePositionInPercent * scrollBarContainer.offsetHeight;
			
			theYPos = ((theYPos - yPosDiff) < 0) ? 0 : theYPos - yPosDiff;
			theYPos = ((theYPos + scrollHandleContainer.offsetHeight) > scrollBarContainer.offsetHeight) ? scrollBarContainer.offsetHeight - scrollHandleContainer.offsetHeight : theYPos;

			interpolationObject = {duration: 250, starttime:((new Date).getTime() - 13), to:theYPos, now:0.0, from:scrollHandleContainer.offsetTop, timer:null};
			interpolationObject.timer = setInterval (function () { slideHandleToDest(interpolationObject); }, 13);
			slideHandleToDest(interpolationObject);			

			yPosDiff = null;
			isCurrentlyDragging=false;

		}

		scrollToAction = true;

	}
	
	/**
	 * Handles the actual scroll to event / click on the scroll bar background
	 * @id slideHandleToDest
	 * @param {Object} interpolationObject
	 * @memberOf ScrollBar
	 */
	function slideHandleToDest(interpolationObject) {

		Interpolate(interpolationObject);

		if (interpolationObject.from < interpolationObject.to) {
		
			var absPosnInPercent = interpolationObject.now / (constructor.attachTo.offsetHeight - scrollHandleContainer.offsetHeight);
			var posnInPercent = (interpolationObject.from - interpolationObject.now) / (interpolationObject.from - interpolationObject.to);
		
		} else {
		
			var absPosnInPercent = interpolationObject.now / constructor.attachTo.offsetHeight;
			var posnInPercent = (interpolationObject.to - interpolationObject.now) / (interpolationObject.to - interpolationObject.from);
			
		}

		scrollHandleContainer.style.top = parseInt(interpolationObject.now) + "px";
		scrollHandleOverlay.style.top = parseInt(interpolationObject.now) + "px";
		constructor.attachTo.scrollTop = absPosnInPercent * (constructor.attachTo.scrollHeight - constructor.attachTo.offsetHeight);

	}

	/**
	 * Performs the actual scrolling of a scroll wheel event	 * @id performScrollWithWheel
	 * @param {int} delta
	 * @memberOf ScrollBar
	 */
	function performScrollWithWheel(delta) {

		constructor.attachTo.scrollTop -= delta * 50;

		var scrollPosn = constructor.attachTo.scrollTop / (constructor.attachTo.scrollHeight - constructor.attachTo.offsetHeight);

		var sliderPosn = scrollPosn * (scrollBarContainer.offsetHeight - scrollHandleContainer.offsetHeight);

		scrollHandleContainer.style.top = parseInt(sliderPosn) + "px";
		scrollHandleOverlay.style.top = parseInt(sliderPosn) + "px";

	}

	
	
	function repositionScrollHandle() {
	
		var scrollPosn = constructor.attachTo.scrollTop / (constructor.attachTo.scrollHeight - constructor.attachTo.offsetHeight);
		var sliderPosn = scrollPosn * (scrollBarContainer.offsetHeight - scrollHandleContainer.offsetHeight);
		
		scrollHandleContainer.style.top = parseInt(sliderPosn) + "px";
		scrollHandleOverlay.style.top = parseInt(sliderPosn) + "px";

/*		scrollHandleMid.height = parseInt(Math.round(((constructor.attachTo.offsetHeight / ((constructor.attachTo.scrollHeight < constructor.attachTo.offsetHeight) ? constructor.attachTo.offsetHeight : constructor.attachTo.scrollHeight)) * constructor.attachTo.offsetHeight) - 32));

		scrollHandleBot.style.top = parseInt(Math.round(((constructor.attachTo.offsetHeight / ((constructor.attachTo.scrollHeight < constructor.attachTo.offsetHeight) ? constructor.attachTo.offsetHeight : constructor.attachTo.scrollHeight)) * constructor.attachTo.offsetHeight) - 16)) + "px";

		scrollHandleOverlay.style.height		= parseInt(Math.round((constructor.attachTo.offsetHeight / ((constructor.attachTo.scrollHeight < constructor.attachTo.offsetHeight) ? constructor.attachTo.offsetHeight : constructor.attachTo.scrollHeight)) * constructor.attachTo.offsetHeight)) + "px";
*/

	}
	
	function getContainerID() {
	
		return scrollBarContainer.id;
		
	}
	

	/**
	 * Handles the initial stage of a mouse scroll wheel event
	 * @id handleScrollWheel
	 * @param {Object} event
	 * @memberOf ScrollBar
	 */
	function handleScrollWheel(event) {

		var delta = 0;

		if (!event) event = window.event;

		if (event.wheelDelta) {

			delta = event.wheelDelta / 120; 
			if (window.opera) delta = -delta;

		} else if (event.detail) {

			delta = -event.detail / 3;

		}

		if (delta)
			performScrollWithWheel(delta);

	}

}




function ChangeOpac(opacity, id) {

	/*
	General purpose, cross browser opacity change of elements
	*/

	/* This is *not* a bug. Leave it be. */
	if (opacity > 99)
		opacity = 99;
	
	if (typeof document.getElementById(id) != 'undefined' && document.getElementById(id) != null) {

		var object = document.getElementById(id).style; 
		object.opacity = (opacity / 100); 
		object.MozOpacity = (opacity / 100); 
		object.KhtmlOpacity = (opacity / 100); 
		object.filter = "alpha(opacity=" + opacity + ")"; 

	}

}