/***
MeasureControl.js
library for handling the map measure functions.

Dependencies:
MapLib/map.js
MapLib/mapImage.js
wz_jsgraphics

***/

MeasureControl = function (newId, mapObject, config, distanceDisplayElement, areaDisplayElement)
{
  var $_this = this;
  mapObject.measureControl = this;
  this.config=config;
  this.id = newId;
  this.canvasEnabled = false;
  this.liveUpdate = false;
  this.drawArea = false;
  this.prevMapX = 0;
  this.prevMapY = 0;
  this.eventNum = 0;
  this.distanceSourceUnits = document.applicationConfig.mapUnits;
  this.distanceUnits = config.distanceMeasureUnits;
  this.previousDistance = 0;
  var img = document.createElement("DIV");

  var mapImage = mapObject.mapImage;
  var points = new Array();
  var images = new Array();

  var gfx = null;
  var gfxContext = null;
  if (mapImage.measureCanvas)
  {
    gfxContext = mapImage.measureCanvas.getContext("2d");
    gfxContext.clearRect(0,0,mapImage.width(),mapImage.height());
    this.canvasEnabled = true;
  }
  else
  {
    gfx = new jsGraphics(mapImage.drawPlaneNode.id);
    gfxContext = null;
    gfx.setStroke(2);
    gfx.setColor(config.distanceColor);
    gfx.setStroke(config.distanceThickness);
  }

this.distanceReset = function()
{
  if (distanceDisplayElement!= null)
    distanceDisplayElement.innerHTML = '';
  if (areaDisplayElement!= null)
    areaDisplayElement.innerHTML = '';
  if (document.getElementById('measurePanelAcreageContainer')!=null)
    document.getElementById('measurePanelAcreageContainer').innerHTML = '';
  for (var lcv=0;lcv < images.length;lcv++)
  {
    mapImage.element.removeChild(images[lcv]);
    delete(images[lcv]);
  };
  delete(images);
  delete(points);
  points = new Array();
  images = new Array();
  if (gfxContext)
  {
    gfxContext.clearRect(0,0,mapImage.width(),mapImage.height());
    gfxContext.beginPath();
  }
  else
    gfx.clear();
};

this.distanceAddPoint = function(x,y){
  points.push({x: x,y: y});
};

this.distanceAddPointImage = function(measurePointX,measurePointY,Z){
  var dx = 29;
  var dy = 0;
  var pos = images.length;
  var img = document.createElement("DIV");
  
  sourceMarkerImage = document.createElement("IMG");
  sourceMarkerImage.style.top = -30;
  sourceMarkerImage.style.position = 'relative';
  sourceMarkerImage.src = './'+GuiWidget.THEME_PATH+'/'+GuiWidget.THEME+'/images/miniIcon.png';
  
  img.style.position = 'absolute';
  img.style.overflow = 'hidden';
  img.style.height = 10;
  img.appendChild(sourceMarkerImage);
  
  mapImage.element.appendChild(img);
  xZIndex(img,Z);

  var imgWidth = 10;  
  var imgHeight = 10;
  var centerX = measurePointX - imgWidth-dx;
  var centerY = measurePointY - imgHeight;
  xMoveTo(img,centerX,centerY);
  xShow(img);
  img.realX = measurePointX;
  img.realY = measurePointY;
  images[pos] = img;
  this.draw();
};

this.draw = function(){
  var dx = 29;
  var dy = 0;
  var pos = images.length-1;
  if (pos > 0)
  {
    var lastPt = images[pos-1];
    if (gfxContext)
    {
      var color="rgba(255,255,255";
      var cfgcolor=config.distanceColor;
      if(cfgcolor[0]=='#'){
          cfgcolor=cfgcolor.slice(1);
          color='rgba('+parseInt('0x'+cfgcolor.substr(0,2))+','+parseInt('0x'+cfgcolor.substr(2,2))+','+parseInt('0x'+cfgcolor.substr(4,2));
      }
      else{
        switch(cfgcolor.toLowerCase()){
          case 'red':color="rgba(255,0,0";break;
          case 'green':color="rgba(0,255,0";break;
          case 'blue':color="rgba(0,0,255";break;
        }
      }
      gfxContext.strokeStyle = color+',1.0)';
      gfxContext.fillStyle=color+',0.25)';
      gfxContext.lineWidth = config.distanceThickness;
      gfxContext.clearRect(0,0,mapImage.width(),mapImage.height());
      gfxContext.beginPath();
      gfxContext.moveTo(images[0].realX-dx,images[0].realY-dy);
      for (var currentPoint=0;currentPoint<points.length;currentPoint++)
      {
        gfxContext.lineTo(images[currentPoint].realX-dx,images[currentPoint].realY-dy);
      };
      gfxContext.stroke();  //note - IE and Safari implicitly close the path here.
      gfxContext.closePath();  //bring firefox into sync
      if (this.drawArea)
      {
        gfxContext.beginPath();
        gfxContext.moveTo(images[0].realX-dx,images[0].realY-dy);
        for (var currentPoint=0;currentPoint<points.length;currentPoint++)
        {
          gfxContext.lineTo(images[currentPoint].realX-dx,images[currentPoint].realY-dy);
        };
        gfxContext.fill();
      }
    }
    else
    {
      gfx.drawLine(lastPt.realX-dx,lastPt.realY-dy,images[pos].realX-dx,images[pos].realY-dy);
      gfx.paint();
    }
  }
};

this.distanceCalculate = function(){
	var pts = cloneObject(points);
	if (this.liveUpdate&&(arguments.length>0)&&(points.length>0))
		pts.push(arguments[0]);

  freeance_request($_this.distanceCalculateCallback,'UnitConv.CalculateDistance',convertUnitToID(this.distanceSourceUnits),convertUnitToID(this.distanceUnits),pts);
};

this.distanceCalculateCallback = function(resp){
	if(resp.XMLRPC_FAULT){
		alert('Fault '+resp.XMLRPC_FAULT_CODE+': '+resp.XMLRPC_FAULT_MESSAGE);
		return;
	}
	var dist = resp.data;
	var distStr = Math.floor(dist[0]*100)/100+' '+$_this.distanceUnits.toLowerCase();
	
	var distance = 0;
	if(images.length > 0){
		images[0].setAttribute('title','Measure Point # 1, Distance = 0, Segment = 0');
		for(var i = 0; i < dist[1].length && i < images.length-1; i++){
			distance += dist[1][i];
			images[i+1].setAttribute('title','Measure Point #'+(i+2)+', Distance = '+distance+', '+'Segment = '+dist[1][i]);
		}
	}

	if (distanceDisplayElement != null)
		distanceDisplayElement.innerHTML = distStr;

	return dist[0];
}

this.areaCalculate = function(){
	if(this.distanceSourceUnits=='LL')
		return 0;

	var pts = cloneObject(points);
	if (this.liveUpdate&&(arguments.length>0))
		pts.push(arguments[0]);

	freeance_request($_this.areaCalculateCallback,'UnitConv.CalculateArea',convertUnitToID(this.distanceSourceUnits),convertUnitToID(this.distanceUnits),pts);
};

this.areaCalculateCallback = function(resp){
	if(resp.XMLRPC_FAULT){
		alert('Fault '+resp.XMLRPC_FAULT_CODE+': '+resp.XMLRPC_FAULT_MESSAGE);
		return;
	}
	
	var area = resp.data;
	if (areaDisplayElement != null)
		areaDisplayElement.innerHTML = area+' sq. '+$_this.distanceUnits.toLowerCase();
	var acreage = $_this.acreageCalculate(area,$_this.distanceUnits); 

	return area;
};

this.acreageCalculate = function(area,units)
{
  var acreage = 0;
  if (area > 0)
  {
    var newArea = 0;
    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;
};

this.convertUnits = function(dist){
  return convertDistance(dist,(this.distanceSourceUnits=="LL")?"km":this.distanceSourceUnits,this.distanceUnits);
};

this.setDistanceUnits = function(newUnits)
{
  this.distanceUnits = newUnits;
  this.distanceCalculate();
  this.areaCalculate();
};

mapObject.addCursorEventHandler('click','MeasureDistance',function(xPos,yPos,width,height,XPercent,YPercent,clickMode){
	var mapimg = mapObject.mapImage;
	var mapImageX = mapimg.left();
	var mapImageY = mapimg.top();
	var extent = mapObject.extent;
	var miny=extent[0];
	var minx=extent[2];
	$_this.eventNum++;
	$_this.distanceAddPoint(XPercent*(extent[3]-minx)+minx,YPercent*(extent[1]-miny)+miny);
	$_this.distanceAddPointImage(mapImageX+xPos,mapImageY+yPos,xZIndex(mapimg.eventHandlerNode)+1);
	$_this.distanceCalculate();
	$_this.areaCalculate();
});

mapObject.addCursorEventHandler('move','MeasureDistance',function(xPos,yPos,width,height,XPercent,YPercent,clickMode){
	$_this.prevMapY = yPos;
	$_this.prevMapX = xPos;
	$_this.eventNum++;
	window.setTimeout(function(){$_this.mouseMove(xPos,yPos,width,height,XPercent,YPercent,clickMode,$_this.eventNum);},75);
});

this.mouseMove = function(xPos,yPos,width,height,XPercent,YPercent,clickMode,num)
{
	if($_this.liveUpdate && $_this.prevMapY == yPos && $_this.prevMapX == xPos && num == $_this.eventNum){
		var extent = mapObject.extent;
		var coord={x:(XPercent * (extent[3]-extent[2])) + extent[2],y:(YPercent * (extent[1]-extent[0])) + extent[0]};
		$_this.distanceCalculate(coord,num);
		$_this.areaCalculate(coord,num);
	}
};
};

FreeanceXMLParser.prototype.getMeasureConfig = function()
{
  var configNodes = this.xmlDoc.getElementsByTagName('measureConfig');
  if (configNodes.item(0))
  {
    configNode = configNodes.item(0);
    return {
      distanceMeasureUnits: this.decodeSTRING(configNode.getElementsByTagName('distanceMeasureUnits')[0]),
      distanceColor: this.decodeSTRING(configNode.getElementsByTagName('distanceColor')[0]),
      distanceThickness: this.decodeSTRING(configNode.getElementsByTagName('distanceThickness')[0])
    }
  }
  else
    return null;
};  

if (Freeance_Extension_Manager)
  Freeance_Extension_Manager.register('measure',function(){
    document.measureControl = new MeasureControl('map0MeasureControl', document.mapObject,document.freeance_config_parser.getMeasureConfig('measureConfig'),$('measurePanelDistanceContainer'),$('measurePanelAreaContainer'));
    
    //disable area fill for unsupported browsers
    if (!document.measureControl.canvasEnabled)
      $('measureControlAreaDrawContainer').style.display = 'none';
    //set appropriate default units
    $('mapToolMeasureDistanceUnitSelector').value = document.measureControl.config.distanceMeasureUnits;
    
    //set up the toolbar button
    var measureButton = (document.mapToolbar.showButton('measureButton'))?document.mapToolbar.getButton('measureButton'):document.mapToolbar.addButton('measureButton',ToolBar.BUTTON_RADIO,ToolBar.ADD_BUTTON_LAST,null,25,25,25,true,'toolBar.png','Measure',document.mapToolbar.mapCursorRadioButtonGroup,'');
    measureButton.clickEvent = function (e) 
    {
      document.mapObject.mapImage.setMouseMode('MeasureDistance');
      setActiveMapTool('MeasureDistance');
      $('mapToolPanelNameField').innerHTML = 'Measure Distance';
    };
    measureButton.setInactiveEvent = function()
    {
      document.measureControl.distanceReset();
    };
    return true;
});

