'use strict';

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

/**
 * @class Text
 * @augments Thing
 * @param {string} label - The words of the text.
 * @param {string} font - String of the desired font of the text.
 */
var Text = function(label, font) {
    Thing.call(this);
    this.label = label;
    this.type = 'Text';

    this.font = font == undefined ? '20pt Arial' : font;

    // Text needs a graphics context for computing height and width
    // we set this by default on running any graphics program, but
    // then it can get over-written the first time we call draw.
    this.context = null;

    this.resetDimensions();
}

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

Text.defaultContext = null;

/**
 * Define a default context for the text.
 * Text objects need access to some 2d graphics context to compute
 * height and width. This might be done before a draw call.
 * @param {CodeHSGraphics} __graphics__ - Instance of the graphics module.
 */
Text.giveDefaultContext = function(__graphics__){
    Text.defaultContext = __graphics__.getContext();
}

/**
 * Reset the dimensions of the text to the size in the context.
 */
Text.prototype.resetDimensions = function(){
    var context = this.context || Text.defaultContext;
    context.font = this.font;
    this.width = context.measureText(this.label).width;
    this.height = context.measureText('m').width * 1.2; /* No height provided */
}

/**
 * Draw the text in the current context.
 * @param {CodeHSGraphics} __graphics__ - Instance of the graphics module.
 */
Text.prototype.draw = function(__graphics__){
    var context = __graphics__.getContext();
    this.context = context;
    context.fillStyle = this.color.toString();
    context.beginPath();
    context.font = this.font;
    this.resetDimensions();
    context.fillText(this.label, this.x,this.y);
    context.closePath();
    context.fill();
}

/**
 * Set the font of the text.
 * Re-calculates the dimensions of the font after font change.
 * @param {string} font - String of the desired font for the text.
 */
Text.prototype.setFont = function(font){
    this.font = font;
    this.resetDimensions();
}

/**
 * Set the label of the text.
 * Re-calculates the dimensions of the font after font change.
 * @param {string} label - String of the desired label for the text.
 */
Text.prototype.setLabel = function(label){
    this.label = label;
    this.resetDimensions();
}

/**
 * Equivalent to `setLabel`. Likely created to prevent errors on
 * accidental calls.
 * Re-calculates the dimensions of the font after font change.
 * @param {string} label - String of the desired label for the text.
 */
Text.prototype.setText = function(label){
    this.label = label;
    this.resetDimensions();
}

/**
 * Returns the label of a Text object.
 * @returns {string} String of the Text's current label.
 */
Text.prototype.getLabel = function(label){
    return this.label;
}

/**
 * Equivalent to `getLabel`.  Likely created to prevent errors on accidental
 * calls.
 * Returns the label of a Text object.
 * @returns {string} String of the Text's current label.
 */
Text.prototype.getText = function(label){
    return this.label;
}

/**
 * Returns the width of a Text object.
 * @returns {number} The width of the text.
 */
Text.prototype.getWidth = function(){
    return this.width;
}

/**
 * Returns the height of a Text object.
 * @returns {number} The height of the text.
 */
Text.prototype.getHeight = function(){
    return this.height;
}

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

module.exports = Text;
