text: 'use strict';
  
  import defaults from '../core/core.defaults';
  import Element from '../core/core.element';
  import helpers from '../helpers';
  const TAU = Math.PI * 2;
  
  defaults._set('global', {
  	elements: {
  		arc: {
  			backgroundColor: defaults.global.defaultColor,
  			borderColor: '#fff',
  			borderWidth: 2,
  			borderAlign: 'center'
  		}
  	}
  });
  
  function clipArc(ctx, arc) {
  	var startAngle = arc.startAngle;
  	var endAngle = arc.endAngle;
  	var pixelMargin = arc.pixelMargin;
  	var angleMargin = pixelMargin / arc.outerRadius;
  	var x = arc.x;
  	var y = arc.y;
  
  	// Draw an inner border by cliping the arc and drawing a double-width border
  	// Enlarge the clipping arc by 0.33 pixels to eliminate glitches between borders
  	ctx.beginPath();
  	ctx.arc(x, y, arc.outerRadius, startAngle - angleMargin, endAngle + angleMargin);
  	if (arc.innerRadius > pixelMargin) {
  		angleMargin = pixelMargin / arc.innerRadius;
  		ctx.arc(x, y, arc.innerRadius - pixelMargin, endAngle + angleMargin, startAngle - angleMargin, true);
  	} else {
  		ctx.arc(x, y, pixelMargin, endAngle + Math.PI / 2, startAngle - Math.PI / 2);
  	}
  	ctx.closePath();
  	ctx.clip();
  }
  
  function drawFullCircleBorders(ctx, vm, arc, inner) {
  	var endAngle = arc.endAngle;
  	var i;
  
  	if (inner) {
  		arc.endAngle = arc.startAngle + TAU;
  		clipArc(ctx, arc);
  		arc.endAngle = endAngle;
  		if (arc.endAngle === arc.startAngle && arc.fullCircles) {
  			arc.endAngle += TAU;
  			arc.fullCircles--;
  		}
  	}
  
  	ctx.beginPath();
  	ctx.arc(arc.x, arc.y, arc.innerRadius, arc.startAngle + TAU, arc.startAngle, true);
  	for (i = 0; i < arc.fullCircles; ++i) {
  		ctx.stroke();
  	}
  
  	ctx.beginPath();
  	ctx.arc(arc.x, arc.y, vm.outerRadius, arc.startAngle, arc.startAngle + TAU);
  	for (i = 0; i < arc.fullCircles; ++i) {
  		ctx.stroke();
  	}
  }
  
  function drawBorder(ctx, vm, arc) {
  	var inner = vm.borderAlign === 'inner';
  
  	if (inner) {
  		ctx.lineWidth = vm.borderWidth * 2;
  		ctx.lineJoin = 'round';
  	} else {
  		ctx.lineWidth = vm.borderWidth;
  		ctx.lineJoin = 'bevel';
  	}
  
  	if (arc.fullCircles) {
  		drawFullCircleBorders(ctx, vm, arc, inner);
  	}
  
  	if (inner) {
  		clipArc(ctx, arc);
  	}
  
  	ctx.beginPath();
  	ctx.arc(arc.x, arc.y, vm.outerRadius, arc.startAngle, arc.endAngle);
  	ctx.arc(arc.x, arc.y, arc.innerRadius, arc.endAngle, arc.startAngle, true);
  	ctx.closePath();
  	ctx.stroke();
  }
  
  class Arc extends Element {
  
  	constructor(props) {
  		super(props);
  	}
  
  	inRange(chartX, chartY) {
  		var vm = this._view;
  
  		if (vm) {
  			var pointRelativePosition = helpers.getAngleFromPoint(vm, {x: chartX, y: chartY});
  			var angle = pointRelativePosition.angle;
  			var distance = pointRelativePosition.distance;
  
  			// Sanitise angle range
  			var startAngle = vm.startAngle;
  			var endAngle = vm.endAngle;
  			while (endAngle < startAngle) {
  				endAngle += TAU;
  			}
  			while (angle > endAngle) {
  				angle -= TAU;
  			}
  			while (angle < startAngle) {
  				angle += TAU;
  			}
  
  			// Check if within the range of the open/close angle
  			var betweenAngles = (angle >= startAngle && angle <= endAngle);
  			var withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius);
  
  			return (betweenAngles && withinRadius);
  		}
  		return false;
  	}
  
  	getCenterPoint() {
  		var vm = this._view;
  		var halfAngle = (vm.startAngle + vm.endAngle) / 2;
  		var halfRadius = (vm.innerRadius + vm.outerRadius) / 2;
  		return {
  			x: vm.x + Math.cos(halfAngle) * halfRadius,
  			y: vm.y + Math.sin(halfAngle) * halfRadius
  		};
  	}
  
  	tooltipPosition() {
  		var vm = this._view;
  		var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2);
  		var rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius;
  
  		return {
  			x: vm.x + (Math.cos(centreAngle) * rangeFromCentre),
  			y: vm.y + (Math.sin(centreAngle) * rangeFromCentre)
  		};
  	}
  
  	draw(ctx) {
  		var vm = this._view;
  		var pixelMargin = (vm.borderAlign === 'inner') ? 0.33 : 0;
  		var arc = {
  			x: vm.x,
  			y: vm.y,
  			innerRadius: vm.innerRadius,
  			outerRadius: Math.max(vm.outerRadius - pixelMargin, 0),
  			pixelMargin: pixelMargin,
  			startAngle: vm.startAngle,
  			endAngle: vm.endAngle,
  			fullCircles: Math.floor(vm.circumference / TAU)
  		};
  		var i;
  
  		ctx.save();
  
  		ctx.fillStyle = vm.backgroundColor;
  		ctx.strokeStyle = vm.borderColor;
  
  		if (arc.fullCircles) {
  			arc.endAngle = arc.startAngle + TAU;
  			ctx.beginPath();
  			ctx.arc(arc.x, arc.y, arc.outerRadius, arc.startAngle, arc.endAngle);
  			ctx.arc(arc.x, arc.y, arc.innerRadius, arc.endAngle, arc.startAngle, true);
  			ctx.closePath();
  			for (i = 0; i < arc.fullCircles; ++i) {
  				ctx.fill();
  			}
  			arc.endAngle = arc.startAngle + vm.circumference % TAU;
  		}
  
  		ctx.beginPath();
  		ctx.arc(arc.x, arc.y, arc.outerRadius, arc.startAngle, arc.endAngle);
  		ctx.arc(arc.x, arc.y, arc.innerRadius, arc.endAngle, arc.startAngle, true);
  		ctx.closePath();
  		ctx.fill();
  
  		if (vm.borderWidth) {
  			drawBorder(ctx, vm, arc);
  		}
  
  		ctx.restore();
  	}
  }
  
  Arc.prototype._type = 'arc';
  
  export default Arc;
  