/**
 * @author Piotr Salaciak 2011-02-20
 * @version 1.0
 */

/**
 * Enumeration: Orientation
 */
ProgressBar.Orientation = {
	Horizontal : 0,
	Vertical : 1
};

/**
 * Enumeration: Direction
 */
ProgressBar.Direction = {
	LeftToRight : 0,
	RightToLeft : 1,
	TopToBottom : 0,
	BottomToTop : 1
};

/**
 * Enumeration: AnimationStyle
 */
ProgressBar.AnimationStyle = {
	None : 0,
	Static : 1,
	StaticFull : 2,
	Custom : 3,
	CustomFull : 4,
	Flickering1 : 10,
	Flickering2 : 11,
	Flickering3 : 12,
	LeftToRight1 : 20,
	LeftToRight2 : 21,
	RightToLeft1 : 22,
	RightToLeft2 : 23,
	TwoWay : 24
};

/**
 * Enumeration: AnimationSmoothness
 */
ProgressBar.AnimationSmoothness = {
	None : 0,
	Smooth1 : 1,
	Smooth2 : 2,
	Smooth3 : 3,
	Smooth4 : 4
};

/**
 * Enumeration: CreationType
 */
ProgressBar.CreationType = {
	Replace : 0,
	AppendChild : 1
};

/**
 * Creates an instance object of a ProgressBar class
 * @param elementId string HTML Element's id for progress bar wrapper
 * @param config Object Configuration object for progress bar
 */
function ProgressBar(elementId, config){
	var i = 0;
	var that = this;
	
	this.isLoaded = false;
	this.animation = {
		opacity : 1,
		opacityDirection : -1,
		isInitialized : false,
		markerPosition : 0,
		markerDirection : 1,
		timerId : null,
		smoothTimerId : null,
		smoothProgressSteps : []
	};
	this.displayType = 0;
	this.progress = 0.0;
	this.progressPosition = 0;
	this.borderWidth = {left:0, right:0, top:0, bottom:0};
	
	
	this.orientation = (config.orientation || ProgressBar.Orientation.Horizontal);
	this.direction = (config.direction || ProgressBar.Direction.LeftToRight);
	this.creationType = (config.creationType || ProgressBar.CreationType.Replace);
	
	this.value = 0;
	this.initialValue = (config.value || 0);
	this.minValue = (config.minValue || 0);
	this.maxValue = (config.maxValue || 100);
	
	this.showLabel = (typeof config.showLabel == "undefined" ? true : config.showLabel);
	this.labelText = (config.labelText || '');
	
	this.width = (config.width || 300);
	this.height = (config.height || 20);
	this.borderRadius = (config.borderRadius || 0);
	
	if (this.orientation == ProgressBar.Orientation.Horizontal && this.borderRadius > this.height/2)
		this.borderRadius = Math.round(this.height/2);
	if (this.orientation == ProgressBar.Orientation.Vertical && this.borderRadius > this.width/2)
		this.borderRadius = Math.round(this.width/2);

	this.imageUrl = (config.imageUrl || '');
	this.markerUrl = (config.markerUrl || '');
	this.backgroundUrl = (config.backgroundUrl || '');
	
	this.animationStyle = (config.animationStyle || ProgressBar.AnimationStyle.None);
	this.animationSpeed = (config.animationSpeed || 1.0);
	this.animationInterval = (config.animationInterval || 100);
	this.animationSmoothness = (config.animationSmoothness || ProgressBar.AnimationSmoothness.None);
	
	var tempClassNames = ["parent", "background", "wrapper", "left", "middle", "right", "horizontalText", "verticalText", "marker"];
	
	this.extraClassName = {};
	for (i = 0; i < tempClassNames.length; i++){
		if (!config.extraClassName) {
			this.extraClassName[tempClassNames[i]] = "";
		} else if (typeof config.extraClassName == "string"){
			this.extraClassName[tempClassNames[i]] = config.extraClassName;
		} else {
			this.extraClassName[tempClassNames[i]] = (config.extraClassName[tempClassNames[i]] || "");
		}
	}
	
	this.onLoad = (config.onLoad || null);
	this.onValueChanged = (config.onValueChanged || null);
	this.onAnimationStyleChanged = (config.onAnimationStyleChanged || null);
	this.onAnimate = (config.onAnimate || null);
	
	
	if (this.creationType == ProgressBar.CreationType.Replace){
		this.parentElement = document.getElementById(elementId);
	} else {
		this.parentElement = document.createElement("DIV");
		document.getElementById(elementId).appendChild(this.parentElement);
	}
	

	this.image = new Image();
	this.image.onload = function () {that.finishLoading(); };
	this.image.src = this.imageUrl;

}

ProgressBar.prototype.finishLoading = function(){
	if (!this.image.width || !this.image.width)
		return;
	
	var tempStyle = "";
		
	this.wrapperElement = null;
	this.backgroundElement = null;
	this.valueElement = null;
	this.leftElement = null;
	this.middleElement = null;
	this.rightElement = null;
	
	this.backgroundElement = document.createElement("DIV");
	this.backgroundElement.className = "progressbar_background" + (this.extraClassName.background ? " " : "") + this.extraClassName.background;
	this.backgroundElement.style.cssText = this.backgroundElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius);

	this.parentElement.appendChild(this.backgroundElement);
	
	var borderRadiusCheck = ["border-radius","border-bottom-right-radius","-moz-border-radius-bottomright","-webkit-border-bottom-right-radius","-khtml-border-radius-bottomright","-khtml-border-bottom-right-radius"];
	var i = 0, temp = "";
	for (i = 0; i < borderRadiusCheck.length; i++){
		temp = ProgressBar._elementCurrentStyle(this.backgroundElement, borderRadiusCheck[i]);
		if (temp || typeof temp == "string")
			break;
	}

	if (temp != "" && ProgressBar._parseInt(temp) != this.borderRadius)
		this.borderRadius = ProgressBar._parseInt(temp);
	
	
	if ((this.orientation == ProgressBar.Orientation.Horizontal && this.image.width >= this.width) || 
		(this.orientation == ProgressBar.Orientation.Vertical && this.image.height >= this.height)){
		// --- background image is larger than progress bar width, so we can use one single element ---
		this.displayType = 0;
	} else {
		// --- background image is smaller than progress bar width, so we should use 3 elements (left side, middle, right side) ---
		this.displayType = 1;
	}
	
	this.parentElement.className = (this.parentElement.className != "" ? " " : "") + "progressbar_parent" + (this.extraClassName.parent ? " " : "") + this.extraClassName.parent;
	
	if (this.displayType == 0){

		this.wrapperElement = document.createElement("DIV");
		this.wrapperElement.className = "progressbar_wrapper" + (this.extraClassName.wrapper ? " " : "") + this.extraClassName.wrapper;

		this.wrapperElement.style.cssFloat = "left";
		this.wrapperElement.style.float = "left";
		this.wrapperElement.style.display = "inline-block";
		this.wrapperElement.style.width = this.width + "px";
		this.wrapperElement.style.height = this.height + "px";
		this.wrapperElement.style.left = "0px";
		this.wrapperElement.style.top = (-this.height) + "px";
		this.wrapperElement.style.backgroundImage = "url('"+ this.imageUrl +"')";
		this.wrapperElement.style.backgroundRepeat = "no-repeat";
		this.wrapperElement.style.position = "relative";
		this.wrapperElement.style.cssText = this.wrapperElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius);

		this.parentElement.appendChild(this.wrapperElement);
		
		this.borderWidth = {
				left: ProgressBar._parseInt(ProgressBar._elementCurrentStyle(this.wrapperElement,"border-left-width")), 
				right: ProgressBar._parseInt(ProgressBar._elementCurrentStyle(this.wrapperElement,"border-right-width")), 
				top: ProgressBar._parseInt(ProgressBar._elementCurrentStyle(this.wrapperElement,"border-top-width")), 
				bottom: ProgressBar._parseInt(ProgressBar._elementCurrentStyle(this.wrapperElement,"border-bottom-width"))
			};
		
	} else if (this.displayType == 1){
			
		if (this.orientation == ProgressBar.Orientation.Horizontal){
			
			if (this.image.width < this.borderRadius)
				this.borderRadius = this.image.width;
			
			if (this.borderRadius > this.width / 2)
				this.borderRadius = this.width;
			
		} else if (this.orientation == ProgressBar.Orientation.Vertical) {
			
			if (this.image.height < this.borderRadius)
				this.borderRadius = this.image.height;
			
			if (this.borderRadius > this.height / 2)
				this.borderRadius = this.height;
			
		}
		
		this.valueElement = document.createElement("DIV");
		this.valueElement.className = "";

		this.leftElement = document.createElement("DIV");
		this.middleElement = document.createElement("DIV");
		this.rightElement = document.createElement("DIV");

		
		this.leftElement.className = "progressbar_left" + (this.extraClassName.left ? " " : "") + this.extraClassName.left;
		this.middleElement.className = "progressbar_middle" + (this.extraClassName.middle ? " " : "") + this.extraClassName.middle;
		this.rightElement.className = "progressbar_right" + (this.extraClassName.right ? " " : "") + this.extraClassName.right;
		
		
		this.leftElement.style.cssFloat = "left";
		this.leftElement.style.float = "left";
		this.leftElement.style.display = "inline-block";
		this.leftElement.style.backgroundImage = "url('"+ this.imageUrl +"')";
		this.leftElement.style.backgroundRepeat = "no-repeat";
		this.leftElement.style.position = "relative";
		
		this.rightElement.style.cssFloat = "right";
		this.rightElement.style.float = "right";
		this.rightElement.style.display = "inline-block";
		this.rightElement.style.backgroundImage = "url('"+ this.imageUrl +"')";
		this.rightElement.style.backgroundRepeat = "no-repeat";
		this.rightElement.style.position = "relative";
		
		this.middleElement.style.cssFloat = "left";
		this.middleElement.style.float = "left";
		this.middleElement.style.display = "inline-block";
		this.middleElement.style.margin = "0px";
		this.middleElement.style.overflow = "hidden";
		this.middleElement.style.position = "relative";
		
		this.valueElement.style.backgroundImage = "url('"+ this.imageUrl +"')";
		this.valueElement.style.position = "relative";
			
		if (this.orientation == ProgressBar.Orientation.Horizontal){
			
			this.leftElement.style.width = this.borderRadius + "px";
			this.leftElement.style.height = this.height + "px";
			this.leftElement.style.top = -this.height + "px";
			this.leftElement.style.left = "0px";
			this.leftElement.style.borderRight = 'none';
			this.leftElement.style.cssText = this.leftElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius, 0, 0, this.borderRadius);
		
			this.rightElement.style.width = this.borderRadius + "px";
			this.rightElement.style.height = this.height + "px";
			this.rightElement.style.top = -this.height + "px";
			this.rightElement.style.borderLeft = 'none';
			this.rightElement.style.backgroundPosition = this.borderRadius +'px 0px';
			this.rightElement.style.cssText = this.rightElement.style.cssText + ProgressBar._createBorderRadiusCss(0, this.borderRadius, this.borderRadius, 0);

			this.middleElement.style.width = (this.width - (this.borderRadius*2)) + "px";
			this.middleElement.style.height = this.height + "px";
			this.middleElement.style.top = -this.height + "px";
			
			
			this.valueElement.style.width = "0px";
			this.valueElement.style.height = this.height + "px";
		} else if (this.orientation == ProgressBar.Orientation.Vertical) {
			
			this.leftElement.style.width = this.width + "px";
			this.leftElement.style.height = this.borderRadius + "px";
			this.leftElement.style.top = (-this.height) + "px";
			this.leftElement.style.left = "0px";
			this.leftElement.style.borderBottom = 'none';
			this.leftElement.style.cssText = this.leftElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius, this.borderRadius, 0, 0);
	
			this.rightElement.style.width = this.width + "px";
			this.rightElement.style.height = this.borderRadius + "px";
			this.rightElement.style.top = (-this.height) + "px";
			this.rightElement.style.left = "0px";
			this.rightElement.style.borderTop = 'none';
			this.rightElement.style.backgroundPosition = '0px ' + this.borderRadius +'px';
			this.rightElement.style.cssText = this.rightElement.style.cssText + ProgressBar._createBorderRadiusCss(0, 0, this.borderRadius, this.borderRadius);

			this.middleElement.style.width = this.width + "px";
			this.middleElement.style.height = this.height-this.borderRadius *2 + "px";
			this.middleElement.style.top = (-this.height) + "px";
			this.middleElement.style.left = "0px";
			this.middleElement.style.borderTop = 'none';
			this.middleElement.style.borderBottom = 'none';
			
			this.valueElement.style.width = this.width + "px";
			this.valueElement.style.height = "0px";
		}
		
		
		this.middleElement.appendChild(this.valueElement);

		this.parentElement.appendChild(this.leftElement);
		this.parentElement.appendChild(this.middleElement);
		this.parentElement.appendChild(this.rightElement);
		
		if (this.orientation == ProgressBar.Orientation.Horizontal){
			if (this.borderRadius == 0){
				
				this.middleElement.style.borderLeftWidth = ProgressBar._elementCurrentStyle(this.leftElement, 'border-left-width');
				this.middleElement.style.borderLeftStyle = ProgressBar._elementCurrentStyle(this.leftElement, 'border-left-style');
				this.middleElement.style.borderLeftColor = ProgressBar._elementCurrentStyle(this.leftElement, 'border-left-color');
				this.middleElement.style.borderRightWidth = ProgressBar._elementCurrentStyle(this.rightElement, 'border-right-width');
				this.middleElement.style.borderRightStyle = ProgressBar._elementCurrentStyle(this.rightElement, 'border-right-style');
				this.middleElement.style.borderRightColor = ProgressBar._elementCurrentStyle(this.rightElement, 'border-right-color');
				
				this.leftElement.style.display = 'none';
				this.rightElement.style.display = 'none';
			} else {
				this.middleElement.style.borderLeft = 'none';
				this.middleElement.style.borderRight = 'none';
			}
		}

		
		if (this.orientation == ProgressBar.Orientation.Horizontal){
			this.borderWidth = {
					left: ProgressBar._parseInt(ProgressBar._elementCurrentStyle(this.leftElement,"border-left-width")), 
					right: ProgressBar._parseInt(ProgressBar._elementCurrentStyle(this.rightElement,"border-right-width")), 
					top: ProgressBar._parseInt(ProgressBar._elementCurrentStyle(this.middleElement,"border-top-width")), 
					bottom: ProgressBar._parseInt(ProgressBar._elementCurrentStyle(this.middleElement,"border-bottom-width"))
				};
		} else if (this.orientation == ProgressBar.Orientation.Vertical) {
			this.borderWidth = {
					left: ProgressBar._parseInt(ProgressBar._elementCurrentStyle(this.middleElement, "border-left-width")), 
					right: ProgressBar._parseInt(ProgressBar._elementCurrentStyle(this.middleElement, "border-right-width")), 
					top: ProgressBar._parseInt(ProgressBar._elementCurrentStyle(this.leftElement, "border-top-width")), 
					bottom: ProgressBar._parseInt(ProgressBar._elementCurrentStyle(this.rightElement, "border-bottom-width"))
				};
		}
	}
	
	this.parentElement.style.width = (this.width + this.borderWidth.left + this.borderWidth.right) + "px";
	this.parentElement.style.height = (this.height + this.borderWidth.top + this.borderWidth.bottom) + "px";
	
	this.backgroundElement.style.cssFloat = "left";
	this.backgroundElement.style.float = "left";
	this.backgroundElement.style.display = "inline-block";
	this.backgroundElement.style.width = (this.width + this.borderWidth.left + this.borderWidth.right) + "px";

	this.backgroundElement.style.height = this.height + "px";
	if (this.backgroundUrl != '')
		this.backgroundElement.style.backgroundImage = "url('"+ this.backgroundUrl +"')";	
	this.backgroundElement.style.position = "relative";
	
	if (this.displayType == 0)
		this.backgroundElement.style.width = (this.width + this.borderWidth.left + this.borderWidth.right) + "px";
	this.backgroundElement.style.top = this.borderWidth.top + "px";
		
	this.markerElement = document.createElement("DIV");
	this.markerElement.className = "progressbar_marker" + (this.extraClassName.marker ? " " : "") + this.extraClassName.marker;
	this.markerElement.style.display = "inline-block";
	this.markerElement.style.zoom = "1.0";
	this.markerElement.style.width = this.width + "px";
	this.markerElement.style.height = this.height + "px";
	
	this.markerElement.style.top = (-this.height * 2 - this.borderWidth.top) + "px";
	this.markerElement.style.left = this.borderWidth.left + "px";

	
	if (this.markerUrl != '')
		this.markerElement.style.backgroundImage = "url('"+ this.markerUrl +"')";
	this.markerElement.style.lineHeight = (this.height) + "px";
	this.markerElement.style.position = "relative";
	
	this.parentElement.appendChild(this.markerElement);

	this.textElement = document.createElement("DIV");
	if (this.orientation == ProgressBar.Orientation.Horizontal){
		this.textElement.className = "progressbar_text_horizontal" + (this.extraClassName.horizontalText ? " " : "") + this.extraClassName.horizontalText;
	} else {
		this.textElement.className = "progressbar_text_vertical" + (this.extraClassName.verticalText ? " " : "") + this.extraClassName.verticalText;
	}
	this.textElement.style.display = "inline-block";
	this.textElement.style.width = this.width + "px";
	this.textElement.style.height = this.height + "px";
	this.textElement.style.top = (- this.height*2 - this.height - this.borderWidth.top) + "px";
	this.textElement.style.left = this.borderWidth.left + "px";
	this.textElement.style.lineHeight = (this.height) + "px";
	this.textElement.style.position = "relative";

	this.parentElement.appendChild(this.textElement);

	this.isLoaded = true;

	this.setAnimationStyle(this.animationStyle);

	this.setValue(this.initialValue);

	if (this.onLoad != null)
		this.onLoad();
};


ProgressBar.prototype.setValue = function(newValue){
	
	if (newValue !== null && newValue < this.minValue)
		newValue = this.minValue;
	if (newValue !== null && newValue > this.maxValue)
		newValue = this.maxValue;
	
		
	if (newValue !== null && this.animationSmoothness != ProgressBar.AnimationSmoothness.None){
		
		if (this.animation.smoothTimerId != null)
			clearInterval(this.animation.smoothTimerId);
		
		this.animation.smoothProgressSteps = [];

		var temp = this.value;
		var i = newValue - this.value, j = 0;
		while (Math.abs(i) > 1){
			if (this.animationSmoothness == ProgressBar.AnimationSmoothness.Smooth1){
				j = i/2;
				if (Math.abs(j) > Math.abs(this.maxValue - this.minValue) * 0.1)
					j = (j > 0 ? 1 : -1) * Math.abs(this.maxValue - this.minValue) * 0.1;
			} else if (this.animationSmoothness == ProgressBar.AnimationSmoothness.Smooth2){
				j = i/3;
				if (Math.abs(j) > Math.abs(this.maxValue - this.minValue) * 0.1)
					j = (j > 0 ? 1 : -1) * Math.abs(this.maxValue - this.minValue) * 0.1;
			} else if (this.animationSmoothness == ProgressBar.AnimationSmoothness.Smooth3){
				j = i/4;
				if (Math.abs(j) > Math.abs(this.maxValue - this.minValue) * 0.1)
					j = (j > 0 ? 1 : -1) * Math.abs(this.maxValue - this.minValue) * 0.1;
			} else if (this.animationSmoothness == ProgressBar.AnimationSmoothness.Smooth4){
				j = i/4;
				if (Math.abs(j) > Math.abs(this.maxValue - this.minValue) * 0.2)
					j = (j > 0 ? 1 : -1) * Math.abs(this.maxValue - this.minValue) * 0.2;
			} else {
				break;
			}
			
			this.animation.smoothProgressSteps.push(temp + j);
			temp = temp + j;
			i = newValue - temp;
		}
		this.animation.smoothProgressSteps.push(newValue);
		this.animation.smoothProgressSteps.reverse();

		var that = this;
		this.animation.smoothTimerId = setInterval(function() {
			that.setValue(null);
		}, this.animationInterval);
		
		return;
	} 
	
	if (newValue === null){
		if (this.animation.smoothProgressSteps.length > 0)
			this.value = this.animation.smoothProgressSteps.pop();
		
		if (this.animation.smoothProgressSteps.length == 0 &&
			this.animation.smoothTimerId != null)
			clearInterval(this.animation.smoothTimerId);

	} else {
		this.value = newValue;
	}
	

	
	if (this.isLoaded){
		var progress = 0.0;
		
		if (this.orientation == ProgressBar.Orientation.Horizontal){
			progress = (this.value/this.maxValue) * this.width;
			this.progressPosition = progress;
			
			if (this.displayType == 0){
				
				if (this.direction == ProgressBar.Direction.LeftToRight){
					this.wrapperElement.style.backgroundPosition = (-this.image.width + progress) +"px 0px";
				} else {
					this.wrapperElement.style.backgroundPosition = (this.width - progress) +"px 0px";
				}
				
			} else if (this.displayType == 1){
				
				if (this.direction == ProgressBar.Direction.LeftToRight){
					
					if (progress <= this.borderRadius){
						this.leftElement.style.backgroundPosition = (-this.image.width+progress) +"px 0px";
						this.rightElement.style.backgroundPosition = (-this.image.width) +"px 0px";
						this.valueElement.style.width = "0px";	
						
					} else if (progress >= this.width - this.borderRadius){
						this.leftElement.style.backgroundPosition = "0px 0px";
						this.rightElement.style.backgroundPosition = (-this.image.width - (this.width - progress - this.borderRadius)) +"px 0px";
						this.valueElement.style.width = this.middleElement.style.width;
		
					} else {
						this.leftElement.style.backgroundPosition = "0px 0px";
						this.rightElement.style.backgroundPosition = (-this.image.width) +"px 0px";
						this.valueElement.style.width = (progress - this.borderRadius) + "px";
		
					}
					
				} else {
					
					if (progress <= this.borderRadius){
						this.leftElement.style.backgroundPosition = (this.image.width) +"px 0px";
						this.rightElement.style.backgroundPosition = (this.image.width - progress) +"px 0px";
						this.valueElement.style.width = "0px";
						
					} else if (progress >= this.width - this.borderRadius){
						this.leftElement.style.backgroundPosition = (this.width - progress) +"px 0px";
						this.rightElement.style.backgroundPosition = "0px 0px";
						this.valueElement.style.left = "0px";
						this.valueElement.style.width = this.middleElement.style.width;
		
					} else {
						this.leftElement.style.backgroundPosition = this.image.width +"px 0px";
						this.rightElement.style.backgroundPosition = "0px 0px";
						this.valueElement.style.left = (this.width - progress - this.borderRadius) + "px";
						this.valueElement.style.width = (progress - this.borderRadius) + "px";
		
					}
					
				}
			}
			
			if (progress > 0){
				if (this.animationStyle != ProgressBar.AnimationStyle.StaticFull && this.animationStyle != ProgressBar.AnimationStyle.CustomFull){
					this.markerElement.style.width = progress + "px";
				} else {
					this.markerElement.style.width = this.width + "px";
				}
				
				if (this.animationStyle != ProgressBar.AnimationStyle.None)
					this.markerElement.style.visibility = "visible";
			} else {
				this.markerElement.style.width = this.width + "px";
				
				if (this.animationStyle != ProgressBar.AnimationStyle.StaticFull && this.animationStyle != ProgressBar.AnimationStyle.CustomFull)
					this.markerElement.style.visibility = "hidden";
			}
			
			if (this.animationStyle != ProgressBar.AnimationStyle.StaticFull && this.animationStyle != ProgressBar.AnimationStyle.CustomFull){
				if (this.direction == ProgressBar.Direction.LeftToRight){
					this.markerElement.style.left = this.borderWidth.left + "px";
				} else {
					this.markerElement.style.left = (this.width - progress + this.borderWidth.left) + "px";
				}
			} else {
				this.markerElement.style.left = this.borderWidth.left + "px";
			}
			
			var initTextTop = (- this.height * 2 - this.height - this.borderWidth.top);
			var initMarkerTop = (-this.height * 2 - this.borderWidth.top);
			
			if (progress == 0 || this.width == progress){
				this.textElement.style.top = initTextTop + "px";
				this.markerElement.style.top = initMarkerTop + "px";
				this.markerElement.style.height = this.height + "px";
				this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius);
				
			} else if (progress < this.borderRadius){
				var markerHeight = this.height - 2.25*(this.borderRadius - Math.sqrt(Math.pow(this.borderRadius, 2) - Math.pow(this.borderRadius - progress, 2)));
				var markerTop = initMarkerTop + (this.height / 2) - (markerHeight / 2);
				var textTop = initTextTop - 2*(initMarkerTop - markerTop);
				
				this.textElement.style.top = textTop + "px";
				this.markerElement.style.top = markerTop + "px";
				this.markerElement.style.height = markerHeight + "px";
				if (this.direction == ProgressBar.Direction.LeftToRight){
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius, 0, 0, this.borderRadius);
				} else {
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(0, this.borderRadius, this.borderRadius, 0);
				}
				
			} else if (this.width - progress < this.borderRadius){
				var tempRoundness = ((this.borderRadius - (this.width - progress))*2 + (this.borderRadius - Math.sqrt(Math.pow(this.borderRadius, 2) - Math.pow(this.borderRadius - (this.width - progress), 2))))/3;

				if (this.direction == ProgressBar.Direction.LeftToRight){
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius, tempRoundness, tempRoundness, this.borderRadius);
				} else {
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(tempRoundness, this.borderRadius, this.borderRadius, tempRoundness);
				}
				
			} else {
				this.textElement.style.top = initTextTop + "px";
				this.markerElement.style.top = initMarkerTop + "px";
				this.markerElement.style.height = this.height + "px";
				
				if (this.direction == ProgressBar.Direction.LeftToRight){
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius, 0, 0, this.borderRadius);
				} else {
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(0, this.borderRadius, this.borderRadius, 0);
				}
			}
			
		} else if (this.orientation == ProgressBar.Orientation.Vertical){

			progress = (this.value/this.maxValue) * this.height;
			this.progressPosition = progress;
			
			if (this.displayType == 0){
				
				if (this.direction == ProgressBar.Direction.TopToBottom){
					this.wrapperElement.style.backgroundPosition = "0px "+ (progress - this.image.height) +"px";
				} else {
					this.wrapperElement.style.backgroundPosition = "0px "+ (this.height - progress) +"px";
				}
				
			} else if (this.displayType == 1){
				
				if (this.direction == ProgressBar.Direction.TopToBottom){
					
					if (progress <= this.borderRadius){
						this.leftElement.style.backgroundPosition = "0px " + (-this.image.height + progress) +"px";
						this.rightElement.style.backgroundPosition = "0px " + (-this.image.height) +"px";
						this.valueElement.style.height = "0px";	
						
					} else if (progress >= this.height - this.borderRadius){
						this.leftElement.style.backgroundPosition = "0px 0px";
						this.rightElement.style.backgroundPosition = "0px " + (-this.image.height - (this.height - progress - this.borderRadius)) +"px";
						this.valueElement.style.height = this.middleElement.style.height;
		
					} else {
						this.leftElement.style.backgroundPosition = "0px 0px";
						this.rightElement.style.backgroundPosition = "0px " + (-this.image.height) +"px";
						this.valueElement.style.height = (progress - this.borderRadius) + "px";
		
					}
				} else {
					
					if (progress <= this.borderRadius){
						this.leftElement.style.backgroundPosition = "0px " + (this.borderRadius) + "px";
						this.rightElement.style.backgroundPosition = "0px " + (this.borderRadius - progress) +"px";
						this.valueElement.style.height = "0px";
						
					} else if (progress >= this.height - this.borderRadius){
						this.leftElement.style.backgroundPosition = "0px " + (this.height - progress) +"px";
						this.rightElement.style.backgroundPosition = "0px 0px";
						this.valueElement.style.top = "0px";
						this.valueElement.style.height = this.middleElement.style.height;
		
					} else {
						this.leftElement.style.backgroundPosition = "0px " + this.borderRadius +"px";
						this.rightElement.style.backgroundPosition = "0px 0px";
						this.valueElement.style.top = (this.height - progress - this.borderRadius) + "px";
						this.valueElement.style.height = (progress + this.borderRadius*2) + "px";
		
					}
					
				}
			}
			
			if (progress > 0){
				if (this.animationStyle != ProgressBar.AnimationStyle.StaticFull && this.animationStyle != ProgressBar.AnimationStyle.CustomFull){
					this.markerElement.style.height = progress + "px";
				} else {
					this.markerElement.style.height = this.height + "px";
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius);
				}
				
				if (this.animationStyle != ProgressBar.AnimationStyle.None)
					this.markerElement.style.visibility = "visible";
			} else {
				this.markerElement.style.height = 0 + "px";
				
				if (this.animationStyle != ProgressBar.AnimationStyle.StaticFull && this.animationStyle != ProgressBar.AnimationStyle.CustomFull)
					this.markerElement.style.visibility = "hidden";
			}
			
			var initTextLeft = this.borderWidth.left;
			var initMarkerLeft = this.borderWidth.left;
			
			if (progress == 0 || this.height == progress){
				this.markerElement.style.left = initMarkerLeft + "px";
				this.markerElement.style.width = this.width + "px";
				this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius);
				
			} else if (progress < this.borderRadius){
				var markerWidth = 2.5*progress; // this.width - (this.borderRadius - Math.sqrt(Math.pow(this.borderRadius, 2) - Math.pow(this.borderRadius - progress, 2)));
				if (markerWidth > this.width) markerWidth = this.width;
				var markerLeft = initMarkerLeft + (this.width / 2) - (markerWidth / 2);
					
				this.markerElement.style.left = markerLeft + "px";
				this.markerElement.style.width = markerWidth + "px";
				
				if (this.direction == ProgressBar.Direction.BottomToTop){
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(0, 0, this.borderRadius, this.borderRadius);
				} else {
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius, this.borderRadius, 0, 0);
				}
				
			} else if (this.height - progress < this.borderRadius){
				var tempRoundness = ((this.borderRadius - (this.height - progress))*2 + (this.borderRadius - Math.sqrt(Math.pow(this.borderRadius, 2) - Math.pow(this.borderRadius - (this.height - progress), 2))))/3;

				if (this.direction == ProgressBar.Direction.BottomToTop){
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(tempRoundness, tempRoundness, this.borderRadius, this.borderRadius);
				} else {
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius, this.borderRadius, tempRoundness, tempRoundness);
				}
				
			} else {
				this.markerElement.style.left = initMarkerLeft + "px";
				this.markerElement.style.width = this.width + "px";
				
				if (this.direction == ProgressBar.Direction.BottomToTop){
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(0, 0, this.borderRadius, this.borderRadius);
				} else {
					this.markerElement.style.cssText = this.markerElement.style.cssText + ProgressBar._createBorderRadiusCss(this.borderRadius, this.borderRadius, 0, 0);
				}
			}
			
			if (this.animationStyle != ProgressBar.AnimationStyle.StaticFull && this.animationStyle != ProgressBar.AnimationStyle.CustomFull){
				this.textElement.style.top = -(this.height * 2 + progress + this.borderWidth.top) + "px";
			} else {
				this.textElement.style.top = -(this.height *3 + this.borderWidth.top) + "px";
			}
			
			if (this.animationStyle != ProgressBar.AnimationStyle.StaticFull && this.animationStyle != ProgressBar.AnimationStyle.CustomFull){
				if (this.direction == ProgressBar.Direction.TopToBottom){
					this.markerElement.style.top = (-this.height*2 - this.borderWidth.top) + "px";
				} else {
					this.markerElement.style.top = (-this.height - progress - this.borderWidth.top) + "px";
				}
			} else {
				this.markerElement.style.top = (-this.height*2 - this.borderWidth.top) + "px";
			}
			
		}
		
		this.progress = (this.value/this.maxValue);
		
		if (this.showLabel){
			this.textElement.style.display = "";
			if (this.labelText != ""){
				var tempLabelText = this.labelText;
				
				if (tempLabelText.indexOf("{value") != -1){
					var i = 0;
					
					while(tempLabelText.indexOf("{value}") != -1)
						tempLabelText = tempLabelText.replace("{value}", this.value);
					while(tempLabelText.indexOf("{value,") != -1){
						var decimalDigits = tempLabelText;
						decimalDigits = decimalDigits.substr(decimalDigits.indexOf("{value,") + 7);
						decimalDigits = decimalDigits.substr(0, decimalDigits.indexOf("}"));
						var replaceWith = "";
						
						if (parseInt(decimalDigits) > 0){
							replaceWith = String(Math.round(this.value * Math.pow(10, parseInt(decimalDigits))) / Math.pow(10, parseInt(decimalDigits)));
							
							if (replaceWith.indexOf(".") == -1)
								replaceWith += ".";

							var currentDigits = replaceWith.substr(replaceWith.indexOf(".") + 1).length;
							
							if (currentDigits < parseInt(decimalDigits))
								for (i = currentDigits; i < parseInt(decimalDigits); i++)
									replaceWith += "0";
						} else {
							replaceWith = Math.round(this.value);
						}
						tempLabelText = tempLabelText.replace("{value," + decimalDigits + "}", replaceWith);
					}
				}
				while(tempLabelText.indexOf("{progress}") != -1)
					tempLabelText = tempLabelText.replace("{progress}", Math.round((this.value/this.maxValue)*100));
				
				this.textElement.innerHTML = tempLabelText;
			} else {
				this.textElement.innerHTML = Math.round((this.value/this.maxValue)*100) + "%";
			}
			
		} else {
			this.textElement.style.display = "none";
		}


	}
	
	if (this.onValueChanged != null)
		this.onValueChanged();
};

ProgressBar.prototype.setForeground = function(url){
	this.imageUrl = url;
	if (this.isLoaded){
		
		this.image = new Image();
		this.image.src = this.imageUrl;

		if (this.displayType == 0){
			this.wrapperElement.style.backgroundImage = "url('"+ this.imageUrl +"')";
		} else {
			this.leftElement.style.backgroundImage = "url('"+ this.imageUrl +"')";
			this.rightElement.style.backgroundImage = "url('"+ this.imageUrl +"')";
			this.valueElement.style.backgroundImage = "url('"+ this.imageUrl +"')";
		}
		this.setValue(this.value);
	}
};
ProgressBar.prototype.setBackground = function(url){
	this.backgroundUrl = url;
	if (this.isLoaded){
		this.backgroundElement.style.backgroundImage = "url('"+ this.backgroundUrl +"')";
		this.setValue(this.value);
	}
};
ProgressBar.prototype.setMarkerImage = function(url){
	this.markerUrl = url;
	if (this.isLoaded){
		this.markerElement.style.backgroundImage = "url('"+ this.markerUrl +"')";
		this.setValue(this.value);
	}
};

ProgressBar.prototype.setAnimationStyle = function(style){
	
	this.animation.isInitialized = false;
	
	this.animationStyle = (style || ProgressBar.AnimationStyle.None);
	
	if (this.animationStyle == ProgressBar.AnimationStyle.None) {
		this.markerElement.style.visibility = "hidden";
	} else {
		this.markerElement.style.visibility = "visible";
	}
	
	this.animation.opacity = 1;	
	this.markerElement.style.opacity = this.animation.opacity;
	this.markerElement.style.backgroundPosition = "0px 0px";
	
	if (this.animationStyle == ProgressBar.AnimationStyle.Flickering1 ||
		this.animationStyle == ProgressBar.AnimationStyle.Flickering2 ||
		this.animationStyle == ProgressBar.AnimationStyle.Flickering3){
		
		this.markerElement.style.backgroundRepeat = "repeat";
		this.animation.markerPosition = 0;
		this.animation.opacity = 0.5;
		
	} else if (
		this.animationStyle == ProgressBar.AnimationStyle.LeftToRight1 ||
	    this.animationStyle == ProgressBar.AnimationStyle.LeftToRight2 ||
	    this.animationStyle == ProgressBar.AnimationStyle.RightToLeft1 ||
	    this.animationStyle == ProgressBar.AnimationStyle.RightToLeft2 ||
	    this.animationStyle == ProgressBar.AnimationStyle.TwoWay){
			   
		if (this.animationStyle == ProgressBar.AnimationStyle.LeftToRight1 ||
			this.animationStyle == ProgressBar.AnimationStyle.RightToLeft1 ||
			this.animationStyle == ProgressBar.AnimationStyle.TwoWay){
			this.markerElement.style.backgroundRepeat = "no-repeat";
		} else {
			this.markerElement.style.backgroundRepeat = "repeat";
		}

		if (this.orientation == ProgressBar.Orientation.Horizontal){
			this.animation.markerPosition = -this.image.width;
		} else {
			this.animation.markerPosition = -this.image.height;
		}
		
		this.animation.opacity = 0.5;	
		
	} else {
		this.markerElement.style.backgroundRepeat = "repeat";
	}
	
	if (this.animation.timerId != null)
		clearInterval(this.animation.timerId);
	
	this.setValue(this.value);
	
	if (this.onAnimationStyleChanged)
		this.onAnimationStyleChanged();
	
	if (this.animationStyle != ProgressBar.AnimationStyle.None){
		var that = this;
		this.animation.timerId = setInterval(function () {that.blink(); }, this.animationInterval);
	}
};

ProgressBar.prototype.blink = function(){
	
	this.animation.isInitialized = true;
	
	if (this.onAnimate)
		this.onAnimate();
	
	if (this.animationStyle == ProgressBar.AnimationStyle.Flickering1 ||
		this.animationStyle == ProgressBar.AnimationStyle.Flickering2 ||
		this.animationStyle == ProgressBar.AnimationStyle.Flickering3){
		
		var params = null;
		
		if (this.animationStyle == ProgressBar.AnimationStyle.Flickering1)
			params = {step : 0.05, growSpeed : 3, decSpeed : 1, maxOpacity : 0.75, minOpacity : 0.2};
		if (this.animationStyle == ProgressBar.AnimationStyle.Flickering2)
			params = {step : 0.05, growSpeed : 1, decSpeed : 1, maxOpacity : 0.75, minOpacity : 0.2};
		if (this.animationStyle == ProgressBar.AnimationStyle.Flickering3)
			params = {step : 0.05, growSpeed : 1, decSpeed : 3, maxOpacity : 0.75, minOpacity : 0.2};
		
		params.step = params.step * this.animationSpeed;
	
		if (this.animation.opacity < 0) this.animation.opacity = 0;
		if (this.animation.opacity > 1) this.animation.opacity = 1;
		
		this.animation.opacity += params.step * this.animation.opacityDirection * (this.animation.opacityDirection > 0 ? params.growSpeed : params.decSpeed);
		if (this.animation.opacity >= params.maxOpacity || this.animation.opacity <= params.minOpacity){
			this.animation.opacityDirection = -this.animation.opacityDirection;
			if (this.animation.opacity > params.maxOpacity)
				this.animation.opacity = params.maxOpacity;
			if (this.animation.opacity < params.minOpacity)
				this.animation.opacity = params.minOpacity;
		}
		
		this.markerElement.style.opacity = this.animation.opacity;
		//this.markerElement.style.filter = "alpha(opacity = 50)";

	
	} else if (this.animationStyle == ProgressBar.AnimationStyle.LeftToRight1 ||
			   this.animationStyle == ProgressBar.AnimationStyle.LeftToRight2 ||
			   this.animationStyle == ProgressBar.AnimationStyle.RightToLeft1 ||
			   this.animationStyle == ProgressBar.AnimationStyle.RightToLeft2 ||
			   this.animationStyle == ProgressBar.AnimationStyle.TwoWay){
		
		if (this.orientation == ProgressBar.Orientation.Horizontal){
			if (this.animationStyle == ProgressBar.AnimationStyle.LeftToRight1 || this.animationStyle == ProgressBar.AnimationStyle.LeftToRight2){
				this.animation.markerPosition += 20 * this.animationSpeed;
				if (this.animation.markerPosition > this.width*2)
					this.animation.markerPosition = -this.image.width;
			
			} else if (this.animationStyle == ProgressBar.AnimationStyle.RightToLeft1 || this.animationStyle == ProgressBar.AnimationStyle.RightToLeft2){
				this.animation.markerPosition -= 20 * this.animationSpeed;
				if (this.animation.markerPosition < -this.image.width)
					this.animation.markerPosition = this.width*2;
		
			} else if (this.animationStyle == ProgressBar.AnimationStyle.TwoWay){
				this.animation.markerPosition += 20 * this.animationSpeed * this.animation.markerDirection;
				if (this.animation.markerPosition >= this.progressPosition - this.borderRadius*2 || this.animation.markerPosition <= -this.borderRadius*20)
					this.animation.markerDirection = -this.animation.markerDirection;
			}
			this.markerElement.style.backgroundPosition = (this.animation.markerPosition) +"px 0px";
		} else {
			if (this.animationStyle == ProgressBar.AnimationStyle.LeftToRight1 || this.animationStyle == ProgressBar.AnimationStyle.LeftToRight2){
				this.animation.markerPosition += 20 * this.animationSpeed;
				if (this.animation.markerPosition > this.height*2)
					this.animation.markerPosition = -this.image.height;
			
			} else if (this.animationStyle == ProgressBar.AnimationStyle.RightToLeft1 || this.animationStyle == ProgressBar.AnimationStyle.RightToLeft2){
				this.animation.markerPosition -= 20 * this.animationSpeed;
				if (this.animation.markerPosition < -this.image.height)
					this.animation.markerPosition = this.height*2;
		
			} else if (this.animationStyle == ProgressBar.AnimationStyle.TwoWay){
				this.animation.markerPosition += 20 * this.animationSpeed * this.animation.markerDirection;
				if (this.animation.markerPosition >= this.progressPosition - this.borderRadius*2 || this.animation.markerPosition <= -this.borderRadius*20)
					this.animation.markerDirection = -this.animation.markerDirection;
			}
			this.markerElement.style.backgroundPosition = "0px " + (this.animation.markerPosition) +"px";
		}
	}
	
};


// --- some useful methods ---
ProgressBar._elementCurrentStyle = function(element, styleName){
	if (element.currentStyle){
		var i = 0, temp = "", changeCase = false;
		for (i = 0; i < styleName.length; i++){
			if (styleName.charAt(i) && (styleName.charAt(i) != '-' || styleName.charAt(i).toString() != '-')){
				if (styleName.charAt(i).toString){
					temp = temp + (changeCase ? styleName.charAt(i).toString().toUpperCase() : styleName.charAt(i).toString());
				} else {
					temp = temp + (changeCase ? styleName.charAt(i).toUpperCase() : styleName.charAt(i));
				}
				changeCase = false;
			} else {
				changeCase = true;
			}
		}

		styleName = temp;
		return element.currentStyle[styleName];
	} else {
		return getComputedStyle(element, null).getPropertyValue(styleName);
	}
};

ProgressBar._parseInt = function(val){
	var ret = parseInt(val);
	if (isNaN(ret)) 
		ret = 0;
	return ret;
};
ProgressBar._createBorderRadiusCss = function (leftTopRadius, rightTopRadius, rightBottomRadius, leftBottomRadius){
	if (leftTopRadius != null && rightTopRadius == null && rightBottomRadius == null && leftBottomRadius == null){
		return "; -moz-border-radius: "+ leftTopRadius +"px; -ms-border-radius: "+ leftTopRadius +"px; -o-border-radius: "+ leftTopRadius +"px; -webkit-border-radius: "+ leftTopRadius +"px; -khtml-border-radius: "+ leftTopRadius +"px; border-radius: "+ leftTopRadius +"px;";
	} else {
		leftTopRadius = (leftTopRadius || 0);
		rightTopRadius = (rightTopRadius || 0);
		rightBottomRadius = (rightBottomRadius || 0);
		leftBottomRadius = (leftBottomRadius || 0);
		return "; -moz-border-radius: "+ leftTopRadius +"px "+ rightTopRadius +"px "+ rightBottomRadius +"px "+ leftBottomRadius +"px; -ms-border-radius: "+ leftTopRadius +"px "+ rightTopRadius +"px "+ rightBottomRadius +"px "+ leftBottomRadius +"px; -o-border-radius: "+ leftTopRadius +"px "+ rightTopRadius +"px "+ rightBottomRadius +"px "+ leftBottomRadius +"px; -webkit-border-radius: "+ leftTopRadius +"px "+ rightTopRadius +"px "+ rightBottomRadius +"px "+ leftBottomRadius +"px; -khtml-border-radius: "+ leftTopRadius +"px "+ rightTopRadius +"px "+ rightBottomRadius +"px "+ leftBottomRadius +"px; border-radius: "+ leftTopRadius +"px "+ rightTopRadius +"px "+ rightBottomRadius +"px "+ leftBottomRadius +"px;";
	}
};

