function Barchart(){
	return new BarchartClass();
}
function BarchartClass(){
	DomNodeInterface(this);
	this.bars=[];
	
	this.legendBox={};
	this.valueLabelsBox={width:0,height:0,padding:3};
	
	this._ytitle="";
	this._title="";
	
	this.titleBox={width:0,height:0};
	this.yTitleBox={width:0,height:0};
	this.maxValue=null;
	this.colorPicker=ColorCycler(0,22,22,20000);
	this.valueLabels=[];//Used for multiple values
	this.multipleValues={
		_colors:[],
		_state:1,
		_stack:1,
		_side_by_side:2,
		sideBySide:function(){this._state=this._side_by_side;},
		stack:function(){this._state=this._stack;}};

	this.drawTechnic={
		_state:1
		,_solid:0
		,_gradient:1
		,_solid3d:2
		,solid:function(){this._state=this._solid;}
		,gradient:function(){this._state=this._gradient;}
		,solid3d:function(){this._state=this._solid3d;}
		,isSolid:function(){return this._state==this._solid;}
		,isSolid3d:function(){return this._state==this._solid3d;}		
		,isGradient:function(){return this._state==this._gradient;}		
	};

	this.labelsPlacement={
		_state:0
		,_inBox:0
		,_onBars:1
		,_belowBars:2
		,_none:3
		,inBox:function(){this._state=this._inBox;}
		,onBars:function(){this._state=this._onBars;}
		,belowBars:function(){this._state=this._belowBars;}		
		,none:function(){this._state=this._none;}
		,isInBox:function(){return this._state==this._inBox;}
		,isOnBars:function(){return this._state==this._onBars;}		
		,isBelowBars:function(){return this._state==this._belowBars;}				
		,isNone:function(){return this._state==this._none;}		
	};
	
	this.ypadding=0;
	
	this.titleFont={
				size: "20px"
				,name: 'verdana'
				,color: '#000000'
	};

	this.labelFont={
				size: "20px"
				,name: 'verdana'
				,color: '#000000'
	};
	
	this.valueIndicatorFont={
				size: "20px"
				,name: 'verdana'
				,color: '#000000'
	};

	this.barLabelFont={
				size: "20px"
				,name: 'verdana'
				,color: '#000000'
	};
	
	this.gridColor='#000000';
	
	var body=this.getStyle('canvas barchart title');
	if(body){
		for(var i=0;i<body.style.length;i++){
			switch(body.style[i]){
				case 'font-size':this.titleFont.size=body.style['fontSize'];break;
				case 'color':this.titleFont.color=body.style['color'];break;				
			}
		}
	}
	
	var body=this.getStyle('canvas barchart bar-label');
	if(body){
		for(var i=0;i<body.style.length;i++){
			switch(body.style[i]){
				case 'font-size':this.barLabelFont.size=body.style['fontSize'];break;
				case 'color':this.barLabelFont.color=body.style['color'];break;				
			}
		}
	}
	
	var body=this.getStyle('canvas barchart label');
	if(body){
		for(var i=0;i<body.style.length;i++){
			switch(body.style[i]){
				case 'font-size':this.labelFont.size=body.style['fontSize'];break;
				case 'color':this.labelFont.color=body.style['color'];break;				
			}
		}
	}	
	
	var body=this.getStyle('canvas barchart value-indicator');
	if(body){
		for(var i=0;i<body.style.length;i++){
			switch(body.style[i]){
				case 'font-size':this.valueIndicatorFont.size=body.style['fontSize'];break;
				case 'color':this.valueIndicatorFont.color=body.style['color'];break;				
			}
		}
	}	
}
/*!
 * Sets _title and calculates the titleBox if canvas is set.
 */
BarchartClass.prototype.title = function(title){
	this._title=title;
	this.canvas.oFont(this.titleFont);
	if(this.canvas!=null){
		this.titleBox=this.canvas.textBox(this._title);
	}
};
/*!
 * Sets _ytitle and calculates the titleBox if canvas is set.
 */
BarchartClass.prototype.ytitle = function(title){
	this._ytitle=title;
	this.canvas.oFont(this.labelFont);
	if(this.canvas!=null){
		this.yTitleBox=this.canvas.textBox(this._ytitle);
	}
};

BarchartClass.prototype.prepare=function(){
	this.legendBox={borderStyle:this.canvas.createStyle(),backgroundStyle:this.canvas.createStyle(),width:0,height:0,padding:3};
	this.legendBox.borderStyle.lineWidth=1;
	this.legendBox.backgroundStyle.a=0;	

	this.valueLabelBox={borderStyle:this.canvas.createStyle(),backgroundStyle:this.canvas.createStyle(),width:0,height:0,padding:3};
	this.valueLabelBox.borderStyle.lineWidth=1;
	this.valueLabelBox.backgroundStyle.a=0;		
	if (this._title != "") {
		this.canvas.oFont(this.titleFont);		
		this.titleBox = this.canvas.textBox(this._title);
	}
	
	if(this._ytitle!=""){      
		this.canvas.oFont(this.labelFont);		
		this.yTitleBox = this.canvas.textBox(this._ytitle);
	}
};


BarchartClass.prototype.draw=function(){
	var lx=this.offsetAbsoluteLeft();	
	var ly=this.offsetAbsoluteTop();	
	var w=this.getWidth();
	var h=this.getHeight();
	var state1=this.canvas.save();
	this.canvas.clipRect(lx,ly,w,h);	
	var legendWidth=(this.labelsPlacement.isInBox())?this.legendBox.width+this.legendBox.padding*2+this.legendBox.borderStyle.lineWidth*2+6:0;
	var legendHeight=(this.labelsPlacement.isInBox())?this.legendBox.height+this.legendBox.padding*2+this.legendBox.borderStyle.lineWidth*2:0;
	var valueWidth=this.valueLabelBox.width+this.valueLabelBox.padding*2+this.valueLabelBox.borderStyle.lineWidth*2+6+14;
	//Find the max value


	if (this._title != "") {			
		this.canvas.oFont(this.titleFont);	
		this.canvas.context.textBaseline="top";
		this.canvas.fillStyle(this.titleFont.color);
		this.canvas.fillText(this._title,lx+(w-this.titleBox.width)/2,ly);
     }

	//Find the max width of the value indicators
	var indicator_max_width=0;
	var value_indicators=[];

	if (this._ytitle != "") {
		this.canvas.oFont(this.labelFont);	
		this.canvas.fillStyle(this.labelFont.color);				
		var state=this.canvas.save();
		this.canvas.rotate(270 * Math.PI / 180);
		this.canvas.context.textBaseline="top";
		this.canvas.fillText(this._ytitle,-this.yTitleBox.width/2-ly-h+(h-this.yTitleBox.height)/2,lx);
		this.canvas.restore(state);
	}

	for (var i = 0; i < (this.maxValue+this.ypadding); i +=(this.maxValue+this.ypadding)/ 5) {
		var box = this.canvas.textBox(i.toFixed(1));		
		value_indicators.push({
			box: box,
			value: i.toFixed(1)
		});
		indicator_max_width=Math.max(indicator_max_width,box.width);
	}

	
	var labelMax=0;	
	if(this.labelsPlacement.isBelowBars()){
		for(index in this.bars){
			labelMax=Math.max(labelMax,this.bars[index].legend.height);
		}	
	}
	
	//Draw the value indicators.
	var topIndicatorY=ly+this.titleBox.height+value_indicators[value_indicators.length-1].box.height/2;
	var bottomIndicatorY=ly+h-value_indicators[0].box.height/2-labelMax;
	
	var indicatorDist=(bottomIndicatorY-topIndicatorY)/5;
	var strokeIndictorLX=lx+this.yTitleBox.height+indicator_max_width+2;
	var strokeIndictorHX=strokeIndictorLX+4;
	this.canvas.strokeStyle(this.gridColor);	
	for (var i  in value_indicators) {
		var y=bottomIndicatorY-i*indicatorDist;
		var indicator=value_indicators[i];
		this.canvas.oFont(this.valueIndicatorFont);
		this.canvas.context.textAlign='left';
		this.canvas.oText({
			style:'fill',
			baseline:'middle',
			rgb: this.valueIndicatorFont.color,
			text: indicator.value,
			x:lx+this.yTitleBox.height+indicator_max_width-indicator.box.width,
			y:y
		});		
		this.canvas.beginPath();
		this.canvas.moveTo(strokeIndictorLX,y);
		this.canvas.lineTo(strokeIndictorHX,y);
		this.canvas.stroke();			
	}	

	
	//Max Bar Height:
	var bar_max_height=h-this.titleBox.height-value_indicators[0].box.height/2-value_indicators[value_indicators.length-1].box.height/2-labelMax;
	var bar_height_adjuster=bar_max_height/(this.maxValue+this.ypadding);	
	var bar_top=ly+this.titleBox.height+value_indicators[value_indicators.length-1].box.height/2;
	
	//bar_height_adjuster-=bar_height_adjuster*this.ypadding;	
    if(this.drawTechnic.isSolid3d()){
		bar_max_height-=20;
		bar_top+=20;
		bar_height_adjuster=bar_max_height/(this.maxValue+this.ypadding);	
		this.canvas.beginPath();
		this.canvas.moveTo(strokeIndictorHX,bar_top);
		this.canvas.lineTo(strokeIndictorHX,bar_max_height+bar_top);
		this.canvas.lineTo(w+lx-Math.max(valueWidth,legendWidth)-6,bar_max_height+bar_top);
		this.canvas.stroke();		
		this.canvas.beginPath();
		this.canvas.moveTo(strokeIndictorHX,bar_max_height+bar_top);
		this.canvas.lineTo(strokeIndictorHX+20,bar_max_height+bar_top-30);
		this.canvas.stroke();
	}else{
		this.canvas.beginPath();
		this.canvas.moveTo(strokeIndictorHX,bar_top);
		this.canvas.lineTo(strokeIndictorHX,bar_max_height+bar_top);
		this.canvas.lineTo(w+lx-Math.max(valueWidth,legendWidth)-6,bar_max_height+bar_top);
		this.canvas.stroke();		
	}
	/*This for reasons beyond my understanding is required to avoid strokeText changing the line color*/
	this.canvas.beginPath();
	this.canvas.closePath();
	
	
	var barStartX=lx+this.yTitleBox.height+indicator_max_width+8;
	var barEndX=lx+w-Math.max(valueWidth,legendWidth);
	
	var barArea=barEndX-barStartX;
	
	var barWidth=(barArea-20)/this.bars.length;
	if(this.labelsPlacement.isInBox()){
		if(this.legendBox.borderStyle.lineWidth>0){
			this.canvas.oStrokeStyle(this.legendBox.borderStyle);
			var ht=Math.floor(this.legendBox.borderStyle.lineWidth/2);		
			this.canvas.strokeRect(
				lx+w+ht-8-this.legendBox.width,
				ly+ht+this.titleBox.height,
				this.legendBox.width+6-ht,
				this.legendBox.height+6-ht
			);
		}
		var legendTextX=lx+w-(this.legendBox.width)-5;
		var legendTextY=ly+3+this.titleBox.height;	
		this.canvas.oFont(this.barLabelFont);
		this.canvas.oFont(this.barLabelFont.color);
		for(index in this.bars){
			this.canvas.fillStyle(this.bars[index].color);
			this.canvas.textBaseline('top');
			this.canvas.fillText(this.bars[index].name,legendTextX,legendTextY);			
			legendTextY+=this.bars[index].legend.height;		
		}	
	}
	
	if(this.valueLabelBox.height>0){
		if(this.valueLabelBox.borderStyle.lineWidth>0){
			this.canvas.oStrokeStyle(this.valueLabelBox.borderStyle);
			var ht=Math.floor(this.valueLabelBox.borderStyle.lineWidth/2);		
			this.canvas.strokeRect(
				lx+w+ht-8-this.valueLabelBox.width-14,
				ly+ht+this.titleBox.height+legendHeight,
				this.valueLabelBox.width+6-ht+14,
				this.valueLabelBox.height+6-ht
			);
		}
		var legendTextX=lx+w-(this.valueLabelBox.width)-5;
		var legendTextY=ly+3+this.titleBox.height+legendHeight;	
		this.canvas.oFont(this.labelFont);
		
		for(index in this.valueLabels){
			this.canvas.fillStyle(this.multipleValues._colors[index].color);
			this.canvas.fillRect(
			  legendTextX-12,
			  legendTextY+2,
			  12,
			  12
			);
			this.canvas.fillStyle(this.labelFont.color);
			this.canvas.oText({style:'fill',baseline:'top',text:this.valueLabels[index].label,x:legendTextX,y:legendTextY});
			legendTextY+=this.valueLabels[index].box.height;		
		}			
	}
	var barMargin=(barArea-barWidth*this.bars.length)/this.bars.length;
	barStartX+=barMargin/2;
	//var barWidth=Math.min(50,(barArea-this.bars.length*20)/this.bars.length);

	this.canvas.oFont(this.barLabelFont);		
	var x=barStartX-(barMargin+barWidth);
	for(index in this.bars){
		x+=barMargin+barWidth;
		var offset=0;
		if(typeof this.bars[index].value=='number'){
			var hh=this.bars[index].value*bar_height_adjuster;	
			if(this.drawTechnic.isGradient()){
				this.setGradientBar(x,0,x+barWidth,0,this.bars[index].light,this.bars[index].lightest,this.bars[index].dark);
				this.canvas.fillRect(
					x,
					bar_top+bar_max_height-hh,			
					barWidth,
					hh);
			}else if(this.drawTechnic.isSolid){
				this.canvas.fillStyle(this.bars[index].color);
				this.canvas.fillRect(
					x,
					bar_top+bar_max_height-hh,			
					barWidth,
					hh);				
			}
			offset=hh;
		}else{
			if(this.multipleValues._state==this.multipleValues._stack){
				for(var i in this.bars[index].value){
					var color=this.multipleValues._colors[i];
					this.setGradientBar(x,0,x+barWidth,0,color.light,color.lightest,color.dark);
					var hh=this.bars[index].value[i]*bar_height_adjuster;
					this.canvas.fillRect(
						x,
						bar_top+bar_max_height-hh-offset,			
						barWidth,
						hh);
					offset+=hh;		
				}
			}else if(this.multipleValues._state==this.multipleValues._side_by_side){
				var innerW=barWidth/this.bars[index].value.length;
				for(var i in this.bars[index].value){
					var hh=this.bars[index].value[i]*bar_height_adjuster;			
					var color=this.multipleValues._colors[i];
					if(this.drawTechnic.isGradient()){					
						this.setGradientBar(x+innerW*i,0,x+innerW*i+innerW,0,color.light,color.lightest,color.dark);
						this.canvas.fillRect(
							x+innerW*i,
							bar_top+bar_max_height-hh,			
							innerW,
							hh);					
					}else  if(this.drawTechnic.isSolid3d()){
						this.canvas.fillStyle(color.light);
						this.canvas.fillRect(
							x+innerW*i,
							bar_top+bar_max_height-hh,			
							innerW,
							hh);										

						this.canvas.fillStyle(color.color);						
						this.canvas.fillPolygon(
							x+innerW*i,bar_top+bar_max_height-hh,
							x+innerW+innerW*i,bar_top+bar_max_height-hh,
							x+innerW+15+innerW*i,bar_top+bar_max_height-hh-15,							
							x+15+innerW*i,bar_top+bar_max_height-hh-15							
						);
						this.canvas.fillStyle(color.color);						
						this.canvas.fillPolygon(
							x+innerW+innerW*i,bar_top+bar_max_height-hh,
							x+innerW+15+innerW*i,bar_top+bar_max_height-hh-15,			
							x+innerW+15+innerW*i,bar_top+bar_max_height-15,								
							x+innerW+innerW*i,bar_top+bar_max_height							
						);						
					}
					offset=Math.max(offset,hh+15);
				}
			}
		}				
		if(this.labelsPlacement.isOnBars()){
			this.canvas.fillStyle("#000000");
			this.canvas.oText({style:'fill',baseline:'top',text:this.bars[index].name,x:x,y:bar_top+bar_max_height-offset-20});
		}else if(this.labelsPlacement.isBelowBars()){
			this.canvas.fillStyle("#000000");
			this.canvas.oText({style:'fill',baseline:'top',text:this.bars[index].name,x:x,y:bar_top+bar_max_height});			
		}
	}
	this.canvas.restore(state1);
};


BarchartClass.prototype.setGradientBar=function(x1,y1,x2,y2,l,ll,d){
	var gradient=this.canvas.createLinearGradient(x1,y1,x2,y2);    
	gradient.addColorStop(0,d);
	gradient.addColorStop(0.3,l);
	gradient.addColorStop(0.5,ll);
	gradient.addColorStop(0.7,l);
	gradient.addColorStop(1,d);
	this.canvas.fillStyle(gradient);
};

BarchartClass.prototype.Bar=function(){
	return {value:0,name:''};
};
/*!
  This function add a value label, Value labels are used
  when each bar consists of several values.
 */
BarchartClass.prototype.addValueLabel=function(label){	
	this.canvas.oFont(this.labelFont);
	var box=this.canvas.textBox(label);	
	this.valueLabelBox.width=Math.max(box.width,this.valueLabelBox.width);
	this.valueLabelBox.height+=box.height+2;
	this.valueLabels.push({label:label,box:box});	
};
BarchartClass.prototype.setLabelPlacementByString=function(str){
	switch(str){
		case 'belowBars':this.labelsPlacement.belowBars();break;		
		case 'onBars':this.labelsPlacement.onBars();break;
		case 'inBox':this.labelsPlacement.inBox();break;				
		case 'none':this.labelsPlacement.none();break;		
	}
};
BarchartClass.prototype.addBar=function(bar){
	this.canvas.oFont(this.barLabelFont);
	var box=this.canvas.textBox(bar.name);
	this.legendBox.width=Math.max(box.width,this.legendBox.width);
	this.legendBox.height+=box.height+2;
	bar.legend=box;
	this.bars.push(bar);
	var v=0;
	if(typeof bar.value =='number'){
		this.colorPicker.next();
		bar.color=this.colorPicker.getRGBString(.6);
		bar.light=this.colorPicker.getRGBString(.50);
		bar.dark=this.colorPicker.getRGBString(.3);
		bar.lightest=this.colorPicker.getRGBString(.80);	
		v=bar.value;
	}else{
		for(var i=this.multipleValues._colors.length;i<bar.value.length;i++){
			this.colorPicker.next();
			this.multipleValues._colors.push({
				color:this.colorPicker.getRGBString(.6)
				,light:this.colorPicker.getRGBString(.50)
				,dark:this.colorPicker.getRGBString(.3)
				,lightest:this.colorPicker.getRGBString(.80)
			});				
		}
		if(this.multipleValues._state==this.multipleValues._stack){
			for(var i in bar.value){				
				v+=bar.value[i];
			}
		}else if(this.multipleValues._state==this.multipleValues._side_by_side){	
			for(var i in bar.value){				
				v=Math.max(v,bar.value[i]);
			}			
		}
	}
	if(this.bars.length==1){
		this.maxValue=v;
	}else{
		this.maxValue=Math.max(this.maxValue,v);
	}
};

if(typeof(JCanvasDSLClass)=='function'){
	JCanvasDSLClass.prototype.rootNode.barchart=function(self,node,parent){
	
		var ele=Barchart();
		parent.appendChild(ele);
		ele.prepare();	
		self.mapAttributes(node,ele,[
				['x','x',parseInt],
				['y','y',parseInt],
				['color','rgb',self.colorSolverRGBA],
				['width','width',parseInt],
				['height','height',parseInt],	
				['ytitle','ytitle'],		
				['title','title'],
				['labelPlacement','setLabelPlacementByString']
				]
		);	
		var c=self.firstChild(node);
		while(c){
			switch(c.nodeName){
				case 'valueLabel':
					self.mapAttributes(c,ele,[
							['label','addValueLabel']
							]);		
					var border=ele.legendBox.backgroundStyle;							
					self.mapAttributes(c,border,[
							['background-color','rgba',self.colorSolverRGBA]					
							]);		
				break;					
				case 'legend':
					var border=ele.legendBox.borderStyle;
					self.mapAttributes(c,border,[
							['color','rgba',self.colorSolverRGBA]
							,['borderThickness','lineWidth',parseInt]						
							]);		
					var border=ele.legendBox.backgroundStyle;							
					self.mapAttributes(c,border,[
							['background-color','rgba',self.colorSolverRGBA]					
							]);		
				break;				
				case 'bar':
					var bar=ele.Bar();
					self.mapAttributes(c,bar,[
							['value','value',self.parseFloats]
							,['color','color',self.colorSolverRGBA]
							,['name','name']
							]);
					ele.addBar(bar);				
				break;
			}
			c=self.nextSibling(c);
		}		
	};
}
