# graphics/webimage.js

    'use strict';

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

    WebImage.NOT_LOADED = 1;
    WebImage.DONE = 2;

    WebImage.NUM_CHANNELS = 4;
    WebImage.RED = 0;
    WebImage.GREEN = 1;
    WebImage.BLUE = 2;
    WebImage.ALPHA = 3;

    /**
     * @constructor
     * @augments Thing
     * @param {string} filename - Filepath to the image
     */
    function WebImage(filename) {
        if (typeof filename !== 'string') {
            throw new TypeError('You must pass a string to <span class="code">new WebImage(filename)</span> that has the image\'s location.');
        }
        Thing.call(this);
        var self = this;

        this.image = new Image();
        this.image.src = filename;
        this.filename = filename;
        this.width = WebImage.NOT_LOADED;
        this.height = WebImage.NOT_LOADED;
        this.image.onload = function(){
            self.checkDimensions();
            if(self.loadfn){
                self.loadfn();
            }

        };
        this.set = 0;
        this.type = 'WebImage';
    }

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

    /**
     * Set a function to be called when the WebImage is loaded.
     * @param {function} callback - A function
     */
    WebImage.prototype.loaded = function(callback) {
        this.loadfn = callback;
    };

    /**
     * Set the image of the WebImage.
     * @param {string} filename - Filepath to the image
     */
    WebImage.prototype.setImage = function(filename) {
        var self = this;

        this.image = new Image();
        this.image.src = filename;
        this.filename = filename;
        this.width = WebImage.NOT_LOADED;
        this.height = WebImage.NOT_LOADED;
        this.image.onload = function(){
            self.checkDimensions();
            if(self.loadfn){
                self.loadfn();
            }

        };
        this.set = 0;
    };

    /**
     * Reinforce the dimensions of the WebImage based on the image it displays.
     */
    WebImage.prototype.checkDimensions = function() {
        if(this.width == WebImage.NOT_LOADED){
            this.width = this.image.width;
            this.height = this.image.height;
        }
    };

    /**
     * Draws the WebImage in the canvas.
     * @param {CodeHSGraphics} __graphics__ - Instance of the __graphics__ module.
     */
    WebImage.prototype.draw = function(__graphics__) {
        this.checkDimensions();
        var context = __graphics__.getContext();
        context.beginPath();

        context.drawImage(this.image, this.x, this.y, this.width, this.height);
        // context.strokeStyle = this.stroke;
        // context.fillStyle = this.color;
        // context.lineWidth = this.lineWidth;
        /* HACKY */
    //  if(this.set != WebImage.DONE){
     //       context.drawImage(this.image, this.x, this.y, this.width, this.height);
    //      this.data = context.getImageData(this.x, this.y, this.width, this.height);
    //      this.set++;
    //  }else{
    //      /* TODO: Getting called twice??? */
    //      context.putImageData(this.data, this.x, this.y);
    //  }
      context.closePath();
    };

    /**
     * Assign the ImageData of the canvas at the position of the image,
     * essentially assigning the ImageData.
     * Read more at https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData
     */
    WebImage.prototype.getData = function(__graphics__){
        var context = __graphics__.getContext();
        //context.drawImage(this.image, this.x, this.y, this.width, this.height);
        this.data = context.getImageData(this.x, this.y, this.width, this.height);
    };

    /**
     * Checks if the passed point is contained in the WebImage.
     * @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 WebImage.
     */
    WebImage.prototype.containsPoint = function(x, y){
        return x >= this.x && x <= this.x + this.width &&
               y >= this.y && y <= this.y + this.height;
    };

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

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

    /**
     * Sets the size of the WebImage.
     * @param {number} width - The desired width of the resulting WebImage.
     * @param {number} height - The desired height of the resulting WebImage.
     */
    WebImage.prototype.setSize = function(width, height){
        this.width = width;
        this.height = height;
    };

    /* Get and set pixel functions */

    /**
     * Gets a pixel at the given x and y coordinates.
     * Read more here:
     * https://developer.mozilla.org/en-US/docs/Web/API/ImageData/data
     * @param {number} x - The x coordinate of the point being tested.
     * @param {number} y - The y coordinate of the point being tested.
     * @returns {integer} An integer between 0 and 255.
     */
    WebImage.prototype.getPixel = function(x, y){
        var index = WebImage.NUM_CHANNELS * (y * this.width + x);
        var pixel = [
                this.data.data[index + WebImage.RED],
                this.data.data[index + WebImage.GREEN],
                this.data.data[index + WebImage.BLUE],
                this.data.data[index + WebImage.ALPHA]
                    ];
        return pixel;
    };

    /**
     * Get the red value at a given location in the image.
     * @param {number} x - The x coordinate of the point being tested.
     * @param {number} y - The y coordinate of the point being tested.
     * @returns {integer} An integer between 0 and 255.
     */
    WebImage.prototype.getRed = function(x, y){
        return this.getPixel(x, y)[WebImage.RED];
    };

    /**
     * Get the green value at a given location in the image.
     * @param {number} x - The x coordinate of the point being tested.
     * @param {number} y - The y coordinate of the point being tested.
     * @returns {integer} An integer between 0 and 255.
     */
    WebImage.prototype.getGreen = function(x, y){
        return this.getPixel(x, y)[WebImage.GREEN];
    };

    /**
     * Get the blue value at a given location in the image.
     * @param {number} x - The x coordinate of the point being tested.
     * @param {number} y - The y coordinate of the point being tested.
     * @returns {integer} An integer between 0 and 255.
     */
    WebImage.prototype.getBlue = function(x, y){
        return this.getPixel(x, y)[WebImage.BLUE];
    };

    /**
     * Get the alpha value at a given location in the image.
     * @param {number} x - The x coordinate of the point being tested.
     * @param {number} y - The y coordinate of the point being tested.
     * @returns {integer} An integer between 0 and 255.
     */
    WebImage.prototype.getAlpha = function(x, y){
        return this.getPixel(x, y)[WebImage.ALPHA];
    };

    /**
     * Set the `component` value at a given location in the image to `val`.
     * @param {number} x - The x coordinate of the point being tested.
     * @param {number} y - The y coordinate of the point being tested.
     * @param {integer} component - Integer representing the color value to
     * be set. R, G, B = 0, 1, 2, respectively.
     * @param {integer} val - The desired value of the `component` at the pixel.
     * Must be between 0 and 255.
     */
    WebImage.prototype.setPixel = function(x, y, component, val){
        var index = WebImage.NUM_CHANNELS * (y * this.width + x);
        this.data.data[index + component] = val;
    };

    /**
     * Set the red value at a given location in the image to `val`.
     * @param {number} x - The x coordinate of the point being tested.
     * @param {number} y - The y coordinate of the point being tested.
     * @param {integer} val - The desired value of the red component at the pixel.
     * Must be between 0 and 255.
     */
    WebImage.prototype.setRed = function(x, y, val){
        this.setPixel(x, y, WebImage.RED, val);
    };

    /**
     * Set the green value at a given location in the image to `val`.
     * @param {number} x - The x coordinate of the point being tested.
     * @param {number} y - The y coordinate of the point being tested.
     * @param {integer} val - The desired value of the green component at the pixel.
     * Must be between 0 and 255.
     */
    WebImage.prototype.setGreen = function(x, y, val){
        this.setPixel(x, y, WebImage.GREEN, val);
    };

    /**
     * Set the blue value at a given location in the image to `val`.
     * @param {number} x - The x coordinate of the point being tested.
     * @param {number} y - The y coordinate of the point being tested.
     * @param {integer} val - The desired value of the blue component at the pixel.
     * Must be between 0 and 255.
     */
    WebImage.prototype.setBlue = function(x, y, val){
        this.setPixel(x, y, WebImage.BLUE, val);
    };

    /**
     * Set the alpha value at a given location in the image to `val`.
     * @param {number} x - The x coordinate of the point being tested.
     * @param {number} y - The y coordinate of the point being tested.
     * @param {integer} val - The desired value of the alpha component at the
     * pixel.
     * Must be between 0 and 255.
     */
    WebImage.prototype.setAlpha = function(x, y, val){
        this.setPixel(x, y, WebImage.ALPHA, val);
    };

    module.exports = WebImage;