﻿/***************************************************************************\
*                               POINT OBJECT                                *
\***************************************************************************/

/// <summary>
/// Represents a basic point for polygon drawing.
/// </summary>
/// <param name="x">The x coordinate of the point.</param>
/// <param name="y">The y coordinate of the point.</param>
function Point(x, y) {
    this.x = x;
    this.y = y;
    
    /// <summary>
    /// Creates a rectangle for the current point.
    /// </summary>
    /// <param name="radius">The radius of the bounds around the point.</param>
    this.createBounds = function(radius) {
        return new Rectangle(this.x - radius, this.y - radius, radius * 2, radius * 2);
    }
}

/***************************************************************************\
*                               RECTANGLE OBJECT                            *
\***************************************************************************/

/// <summary>
/// Represents a basic rectangle for drawing.
/// </summary>
/// <param name="x">The x coordinate of the rectangle.</param>
/// <param name="y">The y coordinate of the rectangle.</param>
function Rectangle(x, y, width, height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    
    /// <summary>
    /// Determines if the specified point is within the rectangle.
    /// </summary>
    /// <param name="point">The point to do a hit test on.</param>
    this.hitTest = function(point) {
        return point.x >= this.x 
            && point.y > this.y 
            && point.x < (this.x + this.width) 
            && point.y < (this.y + this.height);
    }
}

/***************************************************************************\
*                               POLYGON OBJECT                              *
\***************************************************************************/

/// <summary>
/// Represents a basic polygon for polygon drawing.
/// </summary>
function Polygon() {
    this.points             = new Array();
    this.currentPoint       = null;
    this.isEditing          = true;
    this.dragPointIndex     = -1;
    this.expandPointIndex   = -1;

    /// <summary>
    /// Adds the specified point to the polygon.
    /// </summary>
    /// <param name="point">The point to be added to the polygon.</param>
    this.addPoint = function(point) {
        this.points.push(point);
    }
    
    /// <summary>
    /// Begins the edit process of a point.
    /// <summary>
    /// <param name="point">The point to do a hit test on.</param>
    this.beginEdit = function(point) {
        var i;
        var _radius;
        
        for (i = 0; i < this.points.length; i++) {
            if (i == this.expandPointIndex)
                _radius = EDIT_BOX_HOVER_RADIUS;
            else
                _radius = EDIT_BOX_RADIUS;
                
            if (this.points[i].createBounds(_radius).hitTest(point)) {
                this.dragPointIndex = i;
                break;
            }
        }
        
        if (i == this.points.length) {
            // No point was found to edit... add one.
            this.addPoint(point);
            this.dragPointIndex = this.points.length - 1;
        }
    }
    
    /// <summary>
    /// Draws the edit regions of the polygon.
    /// </summary>
    this.drawEditRegions = function() {
        var _canvas = GetMapCanvas();
        var _radius;
        
        // Set the stroke styles.
        _canvas.strokeStyle = EDIT_LINE_COLOR;
        _canvas.lineWidth = EDIT_LINE_WIDTH;
        _canvas.lineCap = EDIT_LINE_CAP;
        _canvas.fillStyle = EDIT_FILL_COLOR;

        for (var i = 0; i < this.points.length; i++) {
            _canvas.beginPath();
            
            if (i == this.expandPointIndex)
                _radius = EDIT_BOX_HOVER_RADIUS;
            else
                _radius = EDIT_BOX_RADIUS;
            
            if (EDIT_BOX_SHAPE == "circle")
                _canvas.arc(this.points[i].x, this.points[i].y, _radius, 0, 2 * Math.PI, false);

            _canvas.closePath();
            _canvas.fill();
            _canvas.stroke();
        }
    }
    
    /// <summary>
    /// Draws the polygon on the map canvas.
    /// </summary>
    /// <param name="canEdit">Whether or not the polygon can be edited.</param>
    this.drawPolygon = function(canEdit) {
        var _canvas;
    
        if (this.points.length == 0) return;

        _canvas = GetMapCanvas();
        
        if (canEdit) {
            _canvas.strokeStyle = CURRENT_LINE_COLOR;
            _canvas.lineWidth = CURRENT_LINE_WIDTH;
            _canvas.lineCap = CURRENT_LINE_CAP;
            _canvas.fillStyle = CURRENT_FILL_COLOR;
        }
        
        // Start the polygon at the first point.
        _canvas.beginPath();
        _canvas.moveTo(this.points[0].x, this.points[0].y);

        // Begin drawing lines to all the other points.
        for (var i = 1; i < this.points.length; i++) {
            _canvas.lineTo(this.points[i].x, this.points[i].y);
        }
        
        // Draw the current point if we are drawing the current polygon.
        if (this.isEditing && this.currentPoint != null && this.dragPointIndex == -1)
            _canvas.lineTo(this.currentPoint.x, this.currentPoint.y);

        // Show the polygon.
        _canvas.closePath();
        _canvas.fill();
        _canvas.stroke();
        
        // If this is the current polygon, draw the editable squares.
        if (canEdit)
            this.drawEditRegions();
    }
    
    /// <summary>
    /// Expands the correct point.
    /// </summary>
    /// <param name="point">The point to be expanded.</param>
    this.expandPoint = function(point) {
        var _radius;
        
        for (i = 0; i < this.points.length; i++) {
            _radius = EDIT_BOX_RADIUS;
            
            if (i == this.expandPointIndex)
                _radius = EDIT_BOX_HOVER_RADIUS;
            else
                _radius = EDIT_BOX_RADIUS;
                
            if (this.points[i].createBounds(_radius).hitTest(point)) {
                this.expandPointIndex = i;
                return;
            }
        }
        
        this.expandPointIndex = -1;
    }
    
    /// <summary>
    /// Sets the current point.
    /// </summary>
    /// <param name="point">The new point.</param>
    this.setCurrentPoint = function(point) {
        if (this.dragPointIndex == -1) {
            this.currentPoint = point;
            this.expandPoint(point);
        } else {
            this.points[this.dragPointIndex] = point;
        }
    }
    
    /// <summary>
    /// Stops the editing of points.
    /// </summary>
    this.stopEdit = function() {
        this.dragPointIndex = -1;
    }
}

/***************************************************************************\
*                               BOX                                         *
\***************************************************************************/

/// <summary>
/// Represents a box for drawing.
/// </summary>
function Box(x, y, width, height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    
    /// <summary>
    /// Draws the current box on the canvas.
    /// </summary>
    this.drawBox = function() {
        var _canvas;
        
        _canvas = GetMapCanvas();
        
        _canvas.strokeStyle = BOX_LINE_COLOR;
        _canvas.lineWidth = BOX_LINE_WIDTH;
        _canvas.fillStyle = BOX_FILL_COLOR;
        
        _canvas.strokeRect(x, y, width, height);
        _canvas.fillRect(x, y, width, height);
    }
}