# graphics/thing.js

    'use strict';

    /**
     * @constructor
     */
    function Thing() {
        this.x = 0;
        this.y = 0;
        this.color = '#000000';
        this.stroke = '#000000';
        this.type = 'Thing';
        this.lineWidth = 1;
        this.filled = true;
        this.hasBorder = false;
    }

    /**
     * Sets a Thing object to filled.
     * Throws an error if an argument is not passed.
     * @param {bool} filled - A boolean of whether or not Thing is filled.
     */
    Thing.prototype.setFilled = function(filled){
        if (arguments.length !== 1) {
            throw new Error('You should pass exactly 1 argument to setFilled');
        }
        this.filled = filled;
    };

    /**
     * Returns if a Thing is filled.
     * @returns {boolean} True if the Thing is filled.
     */
    Thing.prototype.isFilled = function(){
        return this.filled;
    };

    /**
     * Sets a Thing object to filled.
     * Throws an error if an argument is not passed.
     * @param {bool} hasBorder - A boolean of whether or not Thing has a border.
     */
    Thing.prototype.setBorder = function(border){
        if (arguments.length !== 1) {
            throw new Error('You should pass exactly 1 argument to setBorder');
        }
        this.hasBorder = border;
    };

    /**
     * Returns if a Thing has a border.
     * @returns {boolean} True if the Thing has a border.
     */
    Thing.prototype.hasBorder = function(){
        return this.hasBorder;
    };

    /**
     * Sets a Thing object's type.
     * Questionable of whether or not this method is used.
     * @param {type} type - A type to set the Thing to.
     */
    Thing.prototype.setType = function(type){
        if (arguments.length !== 1) {
            throw new Error('You should pass exactly 1 argument to setType');
        }
        this.type = type;
    };

    /**
     * Returns the type of a Thing.
     * @returns {type} The type of the Thing.
     */
    Thing.prototype.getType = function(){
        return this.type;
    };

    /**
     * Sets the position of a Thing.
     * Throws an error if there are fewer than 2 params or if
     * they are not numbers.
     * @param {number} x - The destination x coordinate of this Thing.
     * @param {number} y - The destination y coordinate of this Thing.
     */
    Thing.prototype.setPosition = function(x, y) {
        if (arguments.length !== 2) {
            throw new Error('You should pass exactly 2 arguments to setPosition');
        }
        if (typeof x !== 'number' && isNaN(x)) {
            throw new TypeError('Invalid number for x-coordinate');
        }
        if (typeof y !== 'number' && isNaN(y)) {
            throw new TypeError('Invalid number for y-coordinate');
        }
        this.x = x;
        this.y = y;
    };

    /**
     * Sets the color of a Thing.
     * Throws an error if there are fewer than 1 params or if
     * the param is undefined.
     * @param {Color} color - The resulting color of Thing.
     */
    Thing.prototype.setColor = function(color){
        if (arguments.length !== 1) {
            throw new Error('You should pass exactly 1 argument to setColor.');
        }
        if (color === undefined) {
            throw new TypeError('Invalid color');
        }
        this.color = color;
    };

    /**
     * Gets the color of a Thing.
     * @returns {Color} The destination y coordinate of this Thing.
     */
    Thing.prototype.getColor = function(){
        return this.color;
    };

    /**
     * Sets the border color of a Thing.
     * Throws an error if there are fewer than 1 params or if
     * the param is undefined.
     * @param {Color} color - The resulting color of the Thing's border.
     */
    Thing.prototype.setBorderColor = function(color){
        if (color === undefined) {
            throw new TypeError('Invalid color.');
        }
        this.stroke = color;
        this.hasBorder = true;
        this.hasBorder = true;
    };

    /**
     * Gets the border color of a Thing.
     * @returns {Color} The color of the Thing's border.
     */
    Thing.prototype.getBorderColor = function(){
        return this.stroke;
    };

    /**
     * Sets the width of a Thing's border.
     * Throws an error if there is not 1 argument.
     * @param {number} width - The resulting width of the Thing's border.
     */
    Thing.prototype.setBorderWidth = function(width){
        if (arguments.length !== 1) {
            throw new Error('You should pass exactly 1 argument to setBorderWidth.');
        }
        this.lineWidth = width;
        this.hasBorder = true;
    };

    /**
     * Gets the width of the Thing's border.
     * @returns {number} The width of the Thing's border.
     */
    Thing.prototype.getBorderWidth = function(){
        return this.lineWidth;
    };

    /**
     * Changes the possition of a thing by a specified x and y amount.
     * @param {number} dx - The resulting change in the Thing's x position.
     * @param {number} dy - The resulting change in the Thing's y position.
     */
    Thing.prototype.move = function(dx, dy){
        if (arguments.length !== 2) {
            throw new Error('You should pass exactly 2 arguments to move.');
        }
        if (typeof dx !== 'number' && isNaN(dx)) {
            throw new TypeError('Invalid number for dx.');
        }
        if (typeof dy !== 'number' && isNaN(dy)) {
            throw new TypeError('Invalid number for dy.');
        }
        this.x += dx;
        this.y += dy;
    };

    /**
     * Gets the x position of the Thing.
     * @returns {number} The x position of the Thing.
     */
    Thing.prototype.getX = function(){
        return this.x;
    };

    /**
     * Gets the y position of the Thing.
     * @returns {number} The y position of the Thing.
     */
    Thing.prototype.getY = function(){
        return this.y;
    };

    /**
     * This function is overridden in subclasses of Thing.
     */
    Thing.prototype.draw = function(){

    };

    /**
     * Check if a given point is within the Thing.
     * This function only works in subclasses of Thing.
     * @param {number} x - The x coordinate of the point being checked.
     * @param {number} y - The y coordinate of the point being checked.
     * @returns {boolean} Whether the point x, y is within the Thing.
     */
    Thing.prototype.containsPoint = function(x, y){
        return false;
    };

    module.exports = Thing;