'use strict';

/**
 * @namespace Arc
 */

var Thing = require('./thing.js');

/* The angles are always stored in radians.
 * Based on the unit (by default, degrees), the angles might be converted
 * when calling getters or setters on the start/end angles.
 */

/**
 * @class Arc
 * @augments Thing
 * @param {number} radius - Desired radius of the arc.
 * @param {number} startAngle - Start angle of the arc.
 * @param {number} endAngle - End angle of the arc.
 * @param {number} angleUnit - Integer representing unit.
 * Degrees ===0, Radians ===1
 */
function Arc(radius, startAngle, endAngle, angleUnit) {
  if (typeof radius != 'number') {
    throw new TypeError('You must pass four numbers to new' +
                  'Arc(radius, startAngle, endAngle, angleUnit)');
  }
  var ArcThing = new Thing();
  ArcThing.call(this);

  this.radius = radius;
  this.angleUnit = angleUnit || Arc.DEGREES;
  this.counterclockwise = Arc.COUNTER_CLOCKWISE;
  this.type = 'Arc';

  if (this.angleUnit == Arc.DEGREES) {
    startAngle = degreesToRadians(startAngle);
    endAngle = degreesToRadians(endAngle);
  }

  this.startAngle = startAngle;
  this.endAngle = endAngle;
}

Arc.prototype = new Thing();
Arc.prototype.constructor = Arc;

// Constants for Arcs.
Arc.COUNTER_CLOCKWISE = true;
Arc.CLOCKWISE = false;
Arc.DEGREES = 0;
Arc.RADIANS = 1;

/**
 * Draws the arc in the canvas.
 * @param {CodeHSGraphics} __graphics__ - Instance of the __graphics__ module.
 */
Arc.prototype.draw = function(__graphics__) {
  var context = __graphics__.getContext();
  context.beginPath();
  context.arc(this.x, this.y, this.radius, prepareAngle(this.startAngle), prepareAngle(this.endAngle), this.counterclockwise);
  context.lineTo(this.x, this.y);

  if(this.hasBorder) {
    context.lineWidth = this.lineWidth;
    context.strokeStyle = this.stroke.toString();
    context.stroke();
  }

  context.fillStyle = this.color.toString();
  context.fill();
};

/* Sets the starting angle of the arc.
 * Note: All angles are stored in radians, so we must first convert
 * to radians (if the unit is degrees) before storing the new angle.
 * @param {number} angle - The desired start angle of the arc.
 */
Arc.prototype.setStartAngle = function(angle) {
  if (this.angleUnit == Arc.DEGREES) {
    angle = degreesToRadians(angle);
  }
  this.startAngle = angle;
};

/* Sets the ending angle of the arc.
 * Note: All angles are stored in radians, so we must first convert
 * to radians (if the unit is degrees) before storing the new angle.
 * @param {number} angle - The desired end angle of the arc.
 */
Arc.prototype.setEndAngle = function(angle) {
  if (this.angleUnit == Arc.DEGREES) {
    angle = degreesToRadians(angle);
  }
  this.endAngle = angle;
};

/* Gets the starting angle of the arc.
 * @returns {number} The start angle of the arc.
 */
Arc.prototype.getStartAngle = function() {
  var angle = this.startAngle;
  if (this.angleUnit == Arc.DEGREES) {
    angle = radiansToDegrees(this.startAngle);
  }

  return Math.round(angle);
};

/* Gets the starting angle of the arc.
 * @returns {number} The start angle of the arc.
 */
Arc.prototype.getEndAngle = function() {
  var angle = this.endAngle;
  if (this.angleUnit == Arc.DEGREES) {
    angle = radiansToDegrees(this.endAngle);
  }
  return Math.round(angle);
};

/* Gets the direction of the arc (CW or CCW).
 * @param {boolean} val - Boolean representing CW or CCW.
 * `True` sets counterclockwise to true.
 */
Arc.prototype.setDirection = function(val) {
  this.counterclockwise = val;
};


/**
 * Prepares an angle to be drawn.
 * @memberof Arc
 * @param {number} angle - The angle to be prepared.
 * @returns {number} The prepared angle.
 */
var prepareAngle = function(angle) {
  // First, convert to degrees (may lose some accuracy)
  angle = radiansToDegrees(angle);
  angle = Math.round(angle);

  // The canvas arc angles go clockwise, but we want them
  // to go counterclockwise (like the unit circle). Here,
  // we adjust the angle for that.
  angle = (360 - angle) % 360;
  angle = degreesToRadians(angle);

  return angle;
};

/**
 * Helper to convert degrees to radians.
 * @memberof Arc
 * @param {number} angleInDegrees - The angle represented as degrees.
 * @returns {number} The angle represented as radians.
 */
var degreesToRadians = function(angleInDegrees) {
  return angleInDegrees / 180 * Math.PI;
};

/**
 * Helper to convert radians to degrees.
 * @memberof Arc
 * @param {number} angleInDegrees - The angle represented as radians.
 * @returns {number} The angle represented as degrees.
 */
var radiansToDegrees = function(angleInRadians) {
  return angleInRadians / Math.PI * 180;
};

module.exports = Arc;
