/**
 * @fileOverview Distance measure tool.
 */

/**
 * Distance tool constructor.
 *
 * @class Distance measure tool. Does hook into HMap to draw and measure
 * distance of a polyline. Start drawing by clicking on the map, stop drawing
 * with double-click. The current distance is sent as an argument to the
 * function supplied as a callback.
 *
 * @param {HMap} hmap Instace of Hmap.
 * @param {Function} callback Callback function, should take one argument that
 *        is the current distance in meters.
 * @constructor
 *
 * @example
 * var distanceTool = new HDistanceTool(map, distanceCallback);
 * 
 * function distanceCallback(distance) {
 *   distanceInfoDiv.innerHTML = "Distance: " + meters.toFixed(0) + " m";
 * }
 */
function HDistanceTool(hmap, distanceCallback, pointCallback, doneCallback) {
    this.hmap = hmap;
    this.polyLayer = hmap.getPolyLayer();
    this.distanceCallback = distanceCallback;
    this.pointCallback = pointCallback;
    this.doneCallback = doneCallback;
    
    this.hmap.disableDoubleClickZoom();

    this.polyline = new HPolyline();
    this.polyLayer.addPoly(this.polyline);
    
    this.polyStyle = new HPolyStyle();
    this.polyStyle.strokeOpacity = 0.6;
    this.polyStyle.weight = 8;
    this.polyline.setStyle(this.polyStyle);

    this.polyLayer.setStyle(this.polyLayer.getCtxVolatile(), this.polyStyle);
    
    this.currentDistance = 0;

    // init map event listeners
    var me = this;

    this.listeners = [];    // put them in an array for easy cleanup

    this.listeners.push( HEvent.addListener(this.hmap, HMap.EVENT_MAP_CLICK, function(rt90point) { me.mapClick(rt90point); }) );
    this.listeners.push( HEvent.addListener(this.hmap, HMap.EVENT_MAP_DBLCLICK, function(rt90point) { me.mapDblClick(rt90point); }) );
    this.listeners.push( HEvent.addListener(this.hmap, HMap.EVENT_MAP_MOUSE_MOVE, function(rt90point, point) { me.mapMouseMove(rt90point); }) );
}

/**
 * Stop using distance tool by removing event listeners, removing polyline and clearing canvas.
 */
HDistanceTool.prototype.close = function() {
    this.hmap.enableDoubleClickZoom();

    this.polyLayer.removePoly(this.polyline);
    this.polyLayer.clearAll();
    HEvent.removeListeners(this.listeners);
};

/**
 * Reset current polyline.
 */
HDistanceTool.prototype.reset = function() {
    this.polyline.reset();
    this.polyLayer.clearAll();
    this.isDrawing = false;
};

/**
* Undo last vertex.
*/
HDistanceTool.prototype.undo = function() {
    if (this.isDrawing && this.polyline.getVertexCount() > 0) {
        this.polyline.deleteVertex(this.polyline.getVertexCount() - 1);
        
        this.polyLayer.update();

        this.currentDistance = this.polyline.getLength();

        this.distanceCallback(this.currentDistance);
    }
};

/**
* Draws a polyline from given points.
*/
HDistanceTool.prototype.drawPolyline = function(points) {
    if (!points) return;

    this.reset();
    
    for (var i = 0; i < points.length; i++)
        this.polyline.addVertex(points[i]);

    this.polyLayer.update();

    this.currentDistance = this.polyline.getLength();

    this.distanceCallback(this.currentDistance);
};

/**
 * Event listener for mouse clicks on the map. Add point to polyline.
 *
 * @param {HPointRT90} rt90point RT90 coordinate of click.
 * @private
 */
HDistanceTool.prototype.mapClick = function(rt90point) {
    if (!this.isDrawing) {
        this.reset();
    }
    
    this.isDrawing = true;

    this.polyline.addVertex(rt90point);
    this.polyLayer.update();

    this.currentDistance = this.polyline.getLength();

    this.distanceCallback(this.currentDistance);
    this.pointCallback(rt90point);
};

/**
 * Event listener for mouse double clicks on the map, stop drawing line.
 *
 * @param {HPointRT90} rt90point RT90 coordinate of click.
 * @private
 */
HDistanceTool.prototype.mapDblClick = function(rt90point) {
    this.isDrawing = false;

    this.polyLayer.clear(this.polyLayer.getCtxVolatile());
    
    this.doneCallback();
};

/**
 * Event listener for mouse movement. Draws temporary line if drawing.
 *
 * @param {HPointRT90} rt90point RT90 coordinate of mouse.
 * @private
 */
HDistanceTool.prototype.mapMouseMove = function(rt90point) {
    if (this.isDrawing) {
        var ctx = this.polyLayer.getCtxVolatile();

        this.polyLayer.clear(ctx);

        var fromPoint = this.polyline.getVertex(this.polyline.getVertexCount() - 1);

        this.polyLayer.drawLine(ctx, fromPoint, rt90point);

        this.distanceCallback(this.currentDistance + fromPoint.distanceTo(rt90point));
    }
};


