/***
MeasureControl.js
library for handling the map measure functions.

Dependencies:
MapLib/map.js
MapLib/mapImage.js
wz_jsgraphics

***/

MeasureControl = function (newId, newMapObject, newMapId)
{
  if (arguments.length > 0)
    this.init(newId, newMapObject, newMapId);
};

MeasureControl.prototype = new Object();
MeasureControl.constructor = MeasureControl;
 
MeasureControl.prototype.init = function (newId, newMapObject, newMapId)
{
  this.id = newId;
  if (newMapId!=null)
  {
    this.mapObject = OBJECT_MANAGER.getControl(newMapId);
    this.mapId = newMapId;
  }
  else
  {
    this.mapObject = newMapObject;
    this.mapId = newMapObject.id;
  }
  this.mapObject.measureControl = this;
  this.measureRadioButtonGroup = null;
  this.measurePoints = new Array();
  this.measurePointImages = new Array();
  this.distanceDisplayElement = null;
  this.areaDisplayElement = null;
  this.gfxContext = null;
  this.canvasEnabled = false;
  this.liveUpdate = false;
  this.drawArea = false;
};

MeasureControl.prototype.setDisplayElement = function(newElement)
{
  this.distanceDisplayElement = newElement;
};

MeasureControl.prototype.setAreaDisplayElement = function(newElement)
{
  this.areaDisplayElement = newElement;
};

MeasureControl.prototype.initialize = function()
{
  this.sourceMarkerIMG = document.createElement("IMG");
  this.sourceMarkerIMG.src = './'+GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/measurePointMarker.png';
  this.distanceSourceUnits = 'FT';
  this.distanceUnits = 'FT';
  this.gfx = new jsGraphics(this.mapObject.mapImage.drawPlaneNode.id);
  this.gfx.setColor("#FF0000");
  this.gfx.setStroke(2);
};

MeasureControl.prototype.setConfig = function(config)
{
  this.sourceMarkerIMG = document.createElement("IMG");
  this.sourceMarkerIMG.src = './'+GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/measurePointMarker.png';
  this.distanceSourceUnits = config.distanceSourceUnits;
  this.distanceUnits = config.distanceMeasureUnits;
  if (this.mapObject.mapImage.measureCanvas)
  {
    this.gfxContext = this.mapObject.mapImage.measureCanvas.getContext("2d");
    this.gfxContext.clearRect(0,0,this.mapObject.mapImage.width(),this.mapObject.mapImage.height());
    this.gfxContext.strokeStyle = config.distanceColor;
    this.gfxContext.lineWidth = config.distanceThickness;
    this.gfxContext.fillStyle="rgba(255,0,0,0.25)";
    this.canvasEnabled = true;
  }
  else
  {
    this.gfxContext = null;
    this.gfx.setColor(config.distanceColor);
    this.gfx.setStroke(config.distanceThickness);
  }
};

MeasureControl.prototype.distanceReset = function()
{
  if (this.distanceDisplayElement!= null)
    this.distanceDisplayElement.innerHTML = '';
  if (this.areaDisplayElement!= null)
    this.areaDisplayElement.innerHTML = '';
  if (document.getElementById('measurePanelAcreageContainer')!=null)
    document.getElementById('measurePanelAcreageContainer').innerHTML = '';
  for (var lcv=0;lcv < this.measurePointImages.length;lcv++)
  {
    this.mapObject.mapImage.element.removeChild(this.measurePointImages[lcv]);
    delete(this.measurePointImages[lcv]);
  }
  delete(this.measurePointImages);
  delete(this.measurePoints);
  this.measurePoints = new Array();
  this.measurePointImages = new Array();
  if (this.gfxContext)
  {
    this.gfxContext.clearRect(0,0,this.mapObject.mapImage.width(),this.mapObject.mapImage.height());
    this.gfxContext.beginPath();
  }
  else
    this.gfx.clear();
};

MeasureControl.prototype.distanceAddPoint = function(x,y)
{
  var pos = this.measurePoints.length;
  this.measurePoints[pos] = new Array();
  this.measurePoints[pos].x = x;
  this.measurePoints[pos].y = y;
};

MeasureControl.prototype.distanceAddPointImage = function(measurePointX,measurePointY,Z)
{
  var dx = 29;
  var dy = 0;
  var pos = this.measurePointImages.length;
  var img = document.createElement("IMG");
  var tooltip = 'Measure Point #'+(pos+1);
  img.setAttribute('title',tooltip);
  img.style.position = 'absolute';
  img.src = this.sourceMarkerIMG.src;
  this.mapObject.mapImage.element.appendChild(img);
  xZIndex(img,Z);
  
  //force size to 10x10; IE has a problem with determining image size of source image
  var imgWidth = 10;  
  var imgHeight = 10;
  xWidth(img,imgWidth);
  xHeight(img,imgHeight);
  
  //anchor by lower right point
  var centerX = measurePointX - imgWidth-dx;
  var centerY = measurePointY - imgHeight;
  xMoveTo(img,centerX,centerY);
  xMoveTo(img,centerX,centerY);
  xShow(img);
  img.realX = measurePointX;
  img.realY = measurePointY;
  this.measurePointImages[pos] = img;
  // add the line
  this.draw();
};

MeasureControl.prototype.draw = function()
{
  //draw line and optionally fill area
  var dx = 29;
  var dy = 0;
  var pos = this.measurePointImages.length-1;
  if (pos > 0)
  {
    var lastPt = this.measurePointImages[pos-1];
    if (this.gfxContext)
    {
      //refresh points
      this.gfxContext.clearRect(0,0,this.mapObject.mapImage.width(),this.mapObject.mapImage.height());
      this.gfxContext.beginPath();
      this.gfxContext.moveTo(this.measurePointImages[0].realX-dx,this.measurePointImages[0].realY-dy);
      for (var currentPoint=0;currentPoint<this.measurePoints.length;currentPoint++)
      {
        this.gfxContext.lineTo(this.measurePointImages[currentPoint].realX-dx,this.measurePointImages[currentPoint].realY-dy);
      }
      this.gfxContext.stroke();  //note - IE and Safari implicitly close the path here.
      this.gfxContext.closePath();  //bring firefox into sync
      if (this.drawArea)
      {
        //draw area
        this.gfxContext.beginPath();
        this.gfxContext.moveTo(this.measurePointImages[0].realX-dx,this.measurePointImages[0].realY-dy);
        for (var currentPoint=0;currentPoint<this.measurePoints.length;currentPoint++)
        {
          this.gfxContext.lineTo(this.measurePointImages[currentPoint].realX-dx,this.measurePointImages[currentPoint].realY-dy);
        }
        this.gfxContext.fill();
      }
    }
    else
    {
      this.gfx.drawLine(lastPt.realX-dx,lastPt.realY-dy,this.measurePointImages[pos].realX-dx,this.measurePointImages[pos].realY-dy);
      this.gfx.paint();
    }
  }
};

MeasureControl.prototype.distanceCalculate = function()
{
  if (this.liveUpdate&&(arguments.length>0)&&(this.measurePoints.length>0))
    this.measurePoints.push(arguments[0]);
  var dist = 0;
  var distStr = '0'+this.distanceUnits.toLowerCase();
  if (this.measurePoints.length > 1)
  {
    var segment = 0;
    var previousSegmentStr = 0;
    for (var lcv=0;lcv < this.measurePoints.length-1;lcv++)
    {
      var pt1 = this.measurePoints[lcv];
      var pt2 = this.measurePoints[lcv+1];
      previousSegment = Math.floor(this.convertUnits(segment)*100)/100+''+this.distanceUnits.toLowerCase();
      segment = Math.sqrt( Math.pow(pt2.x - pt1.x,2) + Math.pow(pt2.y - pt1.y,2) );
      if ((lcv > 0)&&(arguments.length==0))
      {
        var tooltip = 'Measure Point #'+(lcv+1);
        tooltip += ', '+'Distance = '+distStr;
        tooltip += ', '+'Segment = '+previousSegment;
        this.measurePointImages[lcv].setAttribute('title',tooltip);
      }
      dist += segment;
      distStr = Math.floor(this.convertUnits(dist)*100)/100+' '+this.distanceUnits.toLowerCase();
    }
    lcv = this.measurePoints.length-1;
    if ((lcv > 0)&&(arguments.length==0))
    {
      previousSegment = Math.floor(this.convertUnits(segment)*100)/100+''+this.distanceUnits.toLowerCase();
      var tooltip = 'Measure Point #'+(lcv+1);
      tooltip += ', Distance = '+distStr;
      tooltip += ', '+'Segment = '+previousSegment;
      this.measurePointImages[lcv].setAttribute('title',tooltip);
    }
  }
  else
  {
    if ((this.measurePoints.length == 1)&&(arguments.length>0)&&(this.liveUpdate))
    {
      var pt1 = arguments[0];
      dist = Math.sqrt( Math.pow(pt1.x,2) + Math.pow(pt1.y,2) );
      distStr = Math.floor(this.convertUnits(dist)*100)/100+' '+this.distanceUnits.toLowerCase();
    }
  }
  if (this.distanceDisplayElement != null)
    this.distanceDisplayElement.innerHTML = distStr;
  if (this.liveUpdate&&(arguments.length>0))
    this.measurePoints.pop();
  return(dist);
};

MeasureControl.prototype.areaCalculate = function()
{
  var area = 0;
  if (this.liveUpdate&&(arguments.length>0))
    this.measurePoints.push(arguments[0]);
  var numPoints = this.measurePoints.length;
  if (numPoints > 2)
  {
    for (var i=0; i<numPoints; i++)
    {
      var j = (i+1) % numPoints;
      area += (this.convertUnits(this.measurePoints[i].x) * this.convertUnits(this.measurePoints[j].y));
      area -= (this.convertUnits(this.measurePoints[j].x) * this.convertUnits(this.measurePoints[i].y));
    }
    area /= 2;
    area = Math.abs(Math.floor(area*100)/100.0);
  }
  if (this.areaDisplayElement != null)
    this.areaDisplayElement.innerHTML = area+' sq. '+this.distanceUnits.toLowerCase();
  var acreage = this.acreageCalculate(area,this.distanceUnits);  
  if (this.liveUpdate&&(arguments.length>0))
    this.measurePoints.pop();
  return area;
};

MeasureControl.prototype.acreageCalculate = function(area,units)
{
  var acreage = 0;
  if (area > 0)
  {
    var newArea = 0;
    //convert to sq ft
    switch (units)
    {
      case 'FT':
        newarea = area;
        break;
      case 'YD':
        newarea = area * 9;
        break;
      case 'MI':
        newarea = area * (5280*5280);
        break;
      case 'M':
        newarea = area * (3.2808399*3.2808399);
        break;
      case 'KM':
        newarea = area * (3280.8399*3280.8399);
        break;
    }
    //convert to acres
    acreage = (newarea / 43560.0);
    acreage = Math.abs(Math.floor(acreage*100)/100.0);
  }
  if (document.getElementById('measurePanelAcreageContainer')!=null)
    document.getElementById('measurePanelAcreageContainer').innerHTML = (acreage+' ac');
  return acreage;
};

MeasureControl.prototype.convertUnits = function(dist)
{
  if (this.distanceSourceUnits == this.distanceUnits)
    return(dist);
  return convertDistance(dist,this.distanceSourceUnits,this.distanceUnits);
};

MeasureControl.prototype.setDistanceUnits = function(newUnits)
{
  this.distanceUnits = newUnits;
  this.distanceCalculate();
  this.areaCalculate();
};
