# graphics/oval.js

    'use strict';

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

    /**
     * Note: this is not used as a subclass for Circle since drawing ovals
     * is much more complex than drawing circles, and there is no point in
     * complicating the drawing just for some code reuse.
     */

    /**
     * @class Oval
     * @augments Thing
     * @param {number} radius - Desired radius
     */
    function Oval(width, height) {
      if (typeof width != 'number' || typeof height != 'number') {
        throw new TypeError('You must pass two numbers to new Oval(width, height)');
      }

      Thing.call(this);
      this.width = width;
      this.height = height;
      this.type = 'Oval';
    }

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

    /**
     * Draws an ellipse centered at this.x and this.y.
     * adapted from http://stackoverflow.com/questions/2172798/
     * how-to-draw-an-oval-in-html5-canvas
     * @param {CodeHSGraphics} __graphics__ - Instance of the __graphics__ module.
     */
    Oval.prototype.draw = function(__graphics__) {
      var context = __graphics__.getContext();

      var w = this.width,
          h = this.height,
          x = this.x - w / 2,
          y = this.y - h / 2;

      var kappa = 0.5522848,
          ox = (w / 2) * kappa, // control point offset horizontal
          oy = (h / 2) * kappa, // control point offset vertical
          xe = x + w,           // x-end
          ye = y + h,           // y-end
          xm = x + w / 2,       // x-middle
          ym = y + h / 2;       // y-middle

      context.beginPath();
      context.moveTo(x, ym);
      context.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
      context.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
      context.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
      context.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);

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

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

      context.closePath();
    };

    /**
     * Gets the height of the oval.
     * @returns {number} Height of the oval.
     */
    Oval.prototype.getHeight = function() {
      return this.height;
    };

    /**
     * Gets the width of the oval.
     * @returns {number} Width of the oval.
     */
    Oval.prototype.getWidth = function() {
      return this.width;
    };

    /**
     * Sets the width of the oval.
     * @param {number} width - Desired width of the resulting oval.
     */
    Oval.prototype.setWidth = function(width) {
      this.width = width;
    };

    /**
     * Sets the height of the oval.
     * @param {number} height - Desired height of the resulting oval.
     */
    Oval.prototype.setHeight = function(height) {
      this.height = height;
    };

    /**
     * Checks if the passed point is contained in the oval.
     * Uses the equation for an oval.
     * @param {number} x - The x coordinate of the point being tested.
     * @param {number} y - The y coordinate of the point being tested.
     * @returns {boolean} Whether the passed point is contained in the circle.
     */
    Oval.prototype.containsPoint = function(x, y) {
      var xRadiusSquared = Math.pow(this.width / 2, 2);
      var yRadiusSquared = Math.pow(this.height / 2, 2);
      var xDifferenceSquared = Math.pow(x - this.x, 2);
      var yDifferenceSquared = Math.pow(y - this.y, 2);

      var result = xDifferenceSquared / xRadiusSquared +
        yDifferenceSquared / yRadiusSquared;

      return result <= 1;
    };

    module.exports = Oval;