/**
 * Pie chart is a javascript class to create pie charts on canvas
 *
 * @since Tue Jun 12 2007
 * @author Ron Rademaker
 **/
var Piechart = Class.create();

Piechart.prototype = {
	/**
	 * initialize
	 *
	 * Initialize a new Piechart 
	 *
	 * @access public
	 * @param string canvasid
	 * @param string background
	 * @since Tue Jun 12 2007
	 * @return void
	 **/
	initialize: function(canvasid, background) {
		this.canvas = $(canvasid);
		this.context = this.canvas.getContext("2d");
		this.background = "white";
		if (background != null) {
			this.background = background;
		}
	},

	/**
	 * shade
	 *
	 * Draws a shade for the piechart
	 *
	 * @since Tue Jun 12 2007
	 * @since Tue Jun 12 2007
	 * @return void
	 **/
	shade: function(centeroffset, intensity) {
		if (/MSIE/.test(navigator.userAgent) ) { //unable to do object testing because createRadialGradient has a (broken) implementation
			// maybe provide alternative
		}
		else {
			var rad = this.context.createRadialGradient(this.getCanvasCenterX() + centeroffset, this.getCanvasCenterY() + centeroffset, Math.floor(this.getCanvasSize() / 2) - intensity, this.getCanvasCenterX() + centeroffset, this.getCanvasCenterY() + centeroffset, Math.floor(this.getCanvasSize() / 2) - centeroffset );
			rad.addColorStop(0, "black");
			rad.addColorStop(1, this.background);
			this.context.fillStyle = rad;
			this.context.fillRect(0, 0, this.canvas.clientWidth, this.canvas.clientHeight);
		}
	},

	/**
	 * draw
	 *
	 * Draws a piechart for data
	 *
	 * @access public
	 * @param object data
	 * @since Tue Jun 12 2007
	 * @return void
	 **/
	draw: function(data) {
		var fields = data.getFields();
		var curangle = -1 * (Math.PI / 2);

		var fielddata = new Array();
		for (var i = 0; i < fields.length; i++) {
			var angle = data.getPortion(fields[i], 2 * Math.PI);
			fielddata.push(new Array(angle, data.getColor(fields[i]) ) );
		}

		// three times to avoid black lines
		this.animateDraw(fielddata, curangle, curangle);
		this.animateDraw(fielddata, curangle, curangle);
		this.animateDraw(fielddata, curangle, curangle);
	},

	/**
	 * animateDraw
	 *
	 * Animates the drawing
	 *
	 * @since Tue Jun 26 2007
	 * @access public
	 * @param array data
	 * @param float startangle
	 * @param float curangle
	 * @return void
	 **/
	animateDraw: function(data, startangle, curangle) {
		if (data.length == 0) {
			return;
		}
		var curpiece = this._getCurPiece(data, startangle, curangle);
		var angle = curangle + 0.1;
		this.context.fillStyle = curpiece[1];
		this.context.beginPath();
		this.context.moveTo(this.getCanvasCenterX(), this.getCanvasCenterY() );
		this.context.arc(this.getCanvasCenterX(), this.getCanvasCenterY(), Math.floor(this.getCanvasSize() / 2) - 5, curangle, angle, false);
		this.context.fill();
		if (angle < (startangle + (2 * Math.PI) ) ) {
			this.animateDraw.applyWithTimeout(this, 5, data, startangle, angle);
		}
	},

	/**
	 * _getCurPiece
	 *
	 * Gets the datapiece at curangle when starting at startangle in data
	 *
	 * @since Tue Jun 26 2007
	 * @access public
	 * @param array data
	 * @param float startangle
	 * @param float curangle
	 * @return void
	 **/
	_getCurPiece: function(data, startangle, curangle) {
		for (var i = 0; i < data.length; i++) {
			startangle += data[i][0];
			if (startangle > curangle) {
				return data[i];
			}
		}
	},

	/**
	 * getCanvasCenterX
	 *
	 * Gets the x position of the center of the canvas
	 *
	 * @access public
	 * @since Tue Jun 12 2007
	 * @return integer
	 **/
	getCanvasCenterX: function() {
		var width = this.canvas.clientWidth;
		return Math.floor(width / 2);
	},

	/**
	 * getCanvasCenterY
	 *
	 * Gets the y position of the center of the canvas
	 *
	 * @access public
	 * @since Tue Jun 12 2007
	 * @return integer
	 **/
	getCanvasCenterY: function() {
		var width = this.canvas.clientHeight;
		return Math.floor(width / 2);
	},
	
	/**
	 * getCanvasSize
	 *
	 * Gets the size of the canvas (either width or height, whichever is smaller)
	 *
	 * @access public
	 * @since Tue Jun 12 2007
	 * @return integer
	 **/
	getCanvasSize: function() {
		return Math.min(this.canvas.clientWidth, this.canvas.clientHeight );
	}
}

