﻿Ext.namespace('Mapping.Ext.Esri');


Mapping.Ext.Esri.MeasureTool = function() {

  var initialized = false;
  var serviceUrl, map, geometryService, drawingTools, onDrawEndHandle, projectDeferral;

  var measureToolBar = new Ext.Toolbar({
    items: [
      {
        icon: 'images/icons/small/i_draw_line.png',
        cls: 'x-btn-icon',
        tooltip: 'Measure line',
        handler: function() { 
          navToolbar.deactivate();
          hoverOff();
          activateTool(esri.toolbars.Draw.LINE);  
          Mapping.Ext.Esri.CursorManager.setCursor('mouseCrossHair');
          Ext.get('selectedToolText').update('Measure line tool active');          
        }
      }, {
        icon: 'images/icons/small/i_draw_freeline.png',
        cls: 'x-btn-icon',
        tooltip: 'Measure free line',
        handler: function() { 
          navToolbar.deactivate();
          hoverOff();
          activateTool(esri.toolbars.Draw.FREEHAND_POLYLINE);  
          Mapping.Ext.Esri.CursorManager.setCursor('mouseCrossHair');
          Ext.get('selectedToolText').update('Measure polyline tool active');  
        }
      }, '-', {
        icon: 'images/icons/small/i_draw_poly.png',
        cls: 'x-btn-icon',
        tooltip: 'Measure polygon',
        handler: function() { 
          navToolbar.deactivate();
          hoverOff();
          activateTool(esri.toolbars.Draw.POLYGON);  
          Mapping.Ext.Esri.CursorManager.setCursor('mouseCrossHair');
          Ext.get('selectedToolText').update('Measure polygon tool active');  
        }
      }, {
        icon: 'images/icons/small/i_draw_freepoly.png',
        cls: 'x-btn-icon',
        tooltip: 'Measure free polygon',
        handler: function() { 
          navToolbar.deactivate();
          hoverOff();
          activateTool(esri.toolbars.Draw.FREEHAND_POLYGON);  
          Mapping.Ext.Esri.CursorManager.setCursor('mouseCrossHair');
          Ext.get('selectedToolText').update('Measure freehand polygon tool active');  
        }
      }, '->', {
        icon: 'images/icons/small/i_clear.png',
        cls: 'x-btn-icon',
        tooltip: 'Clear',
        handler: function() { 
          Ext.get('measures').update(''); 
          map.graphics.clear(); 
          Mapping.Ext.Esri.CursorManager.setCursor('mouseCrossHair');
        }
      }
    ]
  });

  var measureWindow = new Ext.Window({
    title: 'Measure Tool',
    visible: true,
    items: [
      measureToolBar,
      { html: '<div id="measures"></div>', width: 244, height: 70 }
    ],
    resizable: false,
    collapsible: true,
    closable: true,
    closeAction: 'hide',
    height: 130,
    width: 260,
    x: 530,
    y: 125
  });

  // After the user draws a line for measuring, project to the proper spatial reference
  /// @params {esri.geometry.Geometry} geometry The geometry drawn by the user
  function handleLineDrawing(geometry) {
    measureWindow.el.mask('Calculating...');
    map.graphics.clear();
    var graphic = map.graphics.add(new esri.Graphic(geometry, new esri.symbol.SimpleLineSymbol()));
    if (graphic.geometry.spatialReference != baseDataSpatialReference) {
      projectDeferral = geometryService.project([graphic], baseDataSpatialReference, calculateLineLength);
      projectDeferral.addErrback(projectionError);
    } else {
      calculateLineLength(graphic);
    }
    return geometry;
  }

  /// After user draws polygon, simplify it
  /// @params {esri.geometry.Geometry} geometry The geometry drawn by the user
  function handlePolygonDrawing(geometry) {
    measureWindow.el.mask('Calculating...');
    map.graphics.clear();
    var graphic = map.graphics.add(new esri.Graphic(geometry, new esri.symbol.SimpleFillSymbol()));
    // reproject the geometry, then simplify
    if (graphic.geometry.spatialReference != baseDataSpatialReference) {
      projectDeferral = geometryService.project([graphic], baseDataSpatialReference, simplifyPolygonGeometry);
      projectDeferral.addErrback(projectionError);
    } else {
      calculatePolygonAreaLength(graphic);
    }
    return geometry;
  }

  /// Project the simplified geometry, if necessary
  /// @params {esri.geometry.Graphic[]} graphics The projected graphics from the server
  function simplifyPolygonGeometry(projectedGraphics) {
    geometryService.simplify(projectedGraphics, calculatePolygonAreaLength);
    projectDeferral.addErrback(projectionError);
    return projectedGraphics
  }
  /// Calculate the length of a line
  /// @params {esri.geometry.Graphic[]} graphics The propertly projected graphics from the server
  function calculateLineLength(graphics) {
    calculateDef = geometryService.lengths(graphics, displayResults);
    projectDeferral.addErrback(projectionError);
    return graphics;
  }
  /// Calculate the area and outside length of a polygon
  function calculatePolygonAreaLength(graphics) {
    calculateDef = geometryService.areasAndLengths(graphics, displayResults);
    projectDeferral.addErrback(projectionError);
    return graphics;
  }
  function displayResults(measurements) {
    if (measurements.areas != null) {
      var newArea = measurements.areas[0];
      var newLength = measurements.lengths[0];

      var newString = Ext.util.Format.number(newArea, '0,000.00') + " square feet<br/>";
      if (newArea > 43560) {
        newString += Ext.util.Format.number(newArea / 43560, '0,000.00') + " acres<br/>";
      }
      if (newArea > 27878400) {
        newString += Ext.util.Format.number(newArea / 27878400, '0,000.00') + " square miles<br/>";
      }
      if (newLength > 5280) {
        newString += Ext.util.Format.number(newArea / 5280, '0,000.00') + " miles around perimeter<br/>";
      } else {
        newString += Ext.util.Format.number(newLength, '0,000.00') + " feet around perimeter<br/>";
      }
      Ext.get('measures').update(newString);
    } else {
      var newLength = measurements.lengths[0];
      var newString = Ext.util.Format.number(newLength, '0,000.00') + " feet<br/>";
      if (newLength > 5280) {
        newString += Ext.util.Format.number(newLength / 5280, '0,000.00') + " miles<br/>"
      }
      Ext.get('measures').update(newString);
    }
    measureWindow.el.unmask();
    return measurements;
  }
  /// Handle a geometryServer projection error
  function projectionError(err) {
    console.error('projectionError: ' + err);
    Mapping.Ext.Esri.ErrorManager.esriError(err);

    return err;
  }

  /// @params {string} geometryType A constant from esr.toolbars.Draw
  function activateTool(geometryType) {
    drawingTools.activate(geometryType);
    activeTool = geometryType;

    // remove existing listener
    dojo.disconnect(onDrawEndHandle);

    // Setup new listener based on type
    if (geometryType == esri.toolbars.Draw.LINE ||
      geometryType == esri.toolbars.Draw.FREEHAND_POLYLINE ||
      geometryType == esri.toolbars.Draw.POLYLINE) {

      onDrawEndHandle = dojo.connect(drawingTools, "onDrawEnd", handleLineDrawing);
    } else if (activeTool == esri.toolbars.Draw.FREEHAND_POLYGON ||
      activeTool == esri.toolbars.Draw.POLYGON ||
      activeTool == esri.toolbars.Draw.EXTENT) {

      onDrawEndHandle = dojo.connect(drawingTools, "onDrawEnd", handlePolygonDrawing);
    }
  }

  /// Displays the window
  function setup() {
    geometryService = new esri.tasks.GeometryService(serviceUrl);
    drawingTools = new esri.toolbars.Draw(map);

    measureWindow.show();
  }

  return Ext.apply(new Ext.util.Observable(), {

    disable: function() {
      if (initialized) {
        drawingTools.deactivate();
      }
    },

    /// Initialize the component
    /// @param {esri.Map} mapObj The map to which this identify tool is bound
    /// @param {string} geometryServiceUrl The url to the geometry service
    init: function(mapObj, geometryServiceUrl) {
      if (!initialized) {
        map = mapObj;
        serviceUrl = geometryServiceUrl;
        initialized = true;

        setup();
      } else {
        measureWindow.show();
      }
    }
  });
  // end of return
} ();

//Mapping.Ext.Esri.MeasureTool.init(map, geometryService);
