Raphael.fn.pieChart = function (cx, cy, r, seriess, colors, stroke, labelDisplayMode, clickHandler, mouseOverHandler, mouseOutHandler, noDataNotice) {
    var paper = this,
        rad = Math.PI / 180,
        chart = this.set();
    function sector(cx, cy, r, startAngle, endAngle, params) {
		var sector = null;
		if (endAngle - startAngle >= 360) {
			sector = paper.circle(cx, cy, r).attr(params);
		}
		else {
	        var x1 = cx + r * Math.cos(-startAngle * rad),
	            x2 = cx + r * Math.cos(-endAngle * rad),
	            y1 = cy + r * Math.sin(-startAngle * rad),
	            y2 = cy + r * Math.sin(-endAngle * rad);
	        sector = paper.path(["M", cx, cy, "L", x1, y1, "A", r, r, 0, +(endAngle - startAngle > 180), 0, x2, y2, "z"]).attr(params);
		}
		return sector;
    }
    var angle = 0,
        start = 0,
        process = function(i, total, j) {
			var values = seriess[i].values;
			var labels = seriess[i].labels;
			var startplus = ( values.length ? 1.0 / values.length : 0.1 );
			var wedge_r = r - ( seriess.length > 1 ? (i*r/(seriess.length + 1)) : 0 );
			var colorhsba = (colors ? DirectMail.hsbaFromColor(colors[j]) : {h:start, s:1, b:1, a:1});
			var color =  DirectMail.hsbaDeclarationWithValues(colorhsba);
            var value = values[j];

			if (value) {
				var angleplus = 360 * value / total,
	                popangle = angle + (angleplus / 2),
	                ms = 500,
	                delta = 14,
	                p = sector(cx, cy, wedge_r, angle, angle + angleplus, {fill: color, stroke: stroke, "stroke-width": 2}),
					txtX = cx + (r + delta + 55) * Math.cos(-popangle * rad),
					txtY = cy + (r + delta + 25) * Math.sin(-popangle * rad),
                    
					label = labels[j].label,
					txt = paper.text(txtX, txtY, label).attr({fill: "rgba(0,0,0,0.75)", stroke: "none", opacity: 0, "font-family": '"Helvetica Neue", Helvetica, sans-serif', "font-size": "14px"});
                    
				if (labelDisplayMode == 'on') {
					txt.attr({opacity: 1});
				}
                    txt.attr( 'x', cx + ( r + delta + ((txt.getBBox().width/2)* 1.1) ) * Math.cos(-popangle * rad) );
                    txt.attr( 'y', cy + ( r + delta + (txt.getBBox().height/2) + 8 ) * Math.sin(-popangle * rad) );

				p.mouseover(function () {
	                p.animate({scale: [1.05, 1.05, cx, cy]}, ms, "backOut");
					if (labelDisplayMode == 'hover') {
		                txt.animate({opacity: 1}, ms, "backOut");
					}
					$(".label").text(labels[j].label);
					$(".sublabel").text(labels[j].sublabel);
					if (mouseOverHandler) {
						mouseOverHandler(event, seriess[i], labels[j]);
					}
	            }).mouseout(function () {
	                p.animate({scale: [1, 1, cx, cy]}, ms, "elastic");
					if (labelDisplayMode == 'hover') {
		                txt.animate({opacity: 0}, ms);
					}
					$(".label").text('');
					$(".sublabel").text('');
					if (mouseOutHandler) {
						mouseOutHandler(event, seriess[i], labels[j]);
					}
	            });
				if (clickHandler) {
					p.click(function (event) {
						clickHandler(event, seriess[i], labels[j]);
					});
				}

	            angle += angleplus;
				chart.push(p);
	            chart.push(txt);
			}
            start += startplus;
        };
	var totalAcrossAllSeries = 0;
	for (var i = 0, ii = seriess.length; i < ii; i++) {
		var total = 0;

		for (var j = 0, jj = seriess[i].values.length; j < jj; j++) {
			total += seriess[i].values[j];
		}
		
		totalAcrossAllSeries += total;
		
		for (var j = 0, jj = seriess[i].values.length; j < jj; j++) {
			process(i, total, j);
		}
		
		angle = start = 0;
	}
	if (seriess.length > 1 && totalAcrossAllSeries) {
		paper.circle(cx, cy, r/(seriess.length + 1)).attr({stroke: stroke, "stroke-width": 2, fill: "hsl(230deg, .15, .15)"});
	}
	if (!totalAcrossAllSeries && noDataNotice) {
		paper.text(cx, cy, noDataNotice).attr({fill: "gray", "font-family": "'Helvetica Neue', Helvetica, sans-serif", "font-size": 14});
	}
    return chart;
};
