/*
 COPYRIGHT 2009 ESRI

 TRADE SECRETS: ESRI PROPRIETARY AND CONFIDENTIAL
 Unpublished material - all rights reserved under the
 Copyright Laws of the United States and applicable international
 laws, treaties, and conventions.

 For additional information, contact:
 Environmental Systems Research Institute, Inc.
 Attn: Contracts and Legal Services Department
 380 New York Street
 Redlands, California, 92373
 USA

 email: contracts@esri.com
 */

if(!dojo._hasResource["esri.SnappingManager"]){dojo._hasResource["esri.SnappingManager"]=true;dojo.provide("esri.SnappingManager");dojo.require("esri.tasks.query");dojo.declare("esri.SnappingManager",null,{constructor:function(_1){_1=_1||{};if(!_1.map){console.error("map is not specified for SnappingManager");}this.map=_1.map;this.tolerance=_1.tolerance||15;this.layerInfos=[];if(_1.layerInfos){this.layerInfos=_1.layerInfos;}else{var i;for(i=0;i<this.map.graphicsLayerIds.length;i++){var _2=this.map.getLayer(this.map.graphicsLayerIds[i]);this.layerInfos.push({"layer":_2});}this.layerInfos.push({"layer":this.map.graphics});}if(_1.snapPointSymbol){this.snapPointSymbol=_1.snapPointSymbol;}else{this.snapPointSymbol=new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_CROSS,15,new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID,new dojo.Color([0,255,255]),1),new dojo.Color([0,255,0,0]));}if(_1.alwaysSnap){this.alwaysSnap=_1.alwaysSnap;}else{this.alwaysSnap=false;}if(_1.snapKey){this.snapKey=_1.snapKey;}else{this.snapKey=dojo.keys.copyKey;}this._SelectionLyrQuery=new esri.tasks.Query();this._SelectionLyrQuery.spatialRelationship=esri.tasks.Query.SPATIAL_REL_INTERSECTS;this._snappingGraphic=new esri.Graphic();this.setLayerInfos(this.layerInfos);this._currentGraphicOption={snapToPoint:true,snapToVertex:true,snapToEdge:true};this._snappingCallback=dojo.hitch(this,this._snappingCallback);},getSnappingPoint:function(_3){var _4=this.layers,_5=this.tolerance,_6=this.map,_7=this.layerOptions,_8=_6.toMap(_3.offset(-_5,_5)),_9=_6.toMap(_3.offset(_5,-_5)),_a=new esri.geometry.Extent(_8.x,_8.y,_9.x,_9.y,_6.spatialReference),_b=new esri.tasks.Query();_b.geometry=_a;_b.spatialRelationship=esri.tasks.Query.SPATIAL_REL_INTERSECTS;var _c=[],_d=[],_e,_f=this._extractPointsAndLines,_10=new dojo.Deferred(),_11=this._nonSelectionLayerCount,_12,_13=_a.xmin,_14=_a.xmax;if(_6.spatialReference._isWrappable()){_13=esri.geometry.Extent.prototype._normalizeX(_a.xmin,_6.spatialReference._getInfo()).x;_14=esri.geometry.Extent.prototype._normalizeX(_a.xmax,_6.spatialReference._getInfo()).x;}var _15=new esri.geometry.Extent(_13,_a.ymin,_14,_a.ymax,_6.spatialReference);dojo.forEach(_4,function(_16,idx){if(_16.declaredClass==="esri.layers.GraphicsLayer"&&_16.visible){var _17=[];dojo.forEach(_16.graphics,function(_18){if(_18){if(_18.visible&&_15.intersects(_18.geometry)){_17.push(_18);}}});var _19=_f(_17,_7[idx]);_c=_c.concat(_19[0]);_d=_d.concat(_19[1]);}});var _1a=dojo.hitch(this,function(_1b){_11--;if(_1b instanceof Error){var msg="getSnappingPoint: query features failed";console.log(msg);}else{var _1c=_f(_1b.features,_7[_12]);_c=_c.concat(_1c[0]);_d=_d.concat(_1c[1]);}if(!_11){_e=this._getSnappingPoint(_c,_d,_3);_10.callback(_e);}});var _1d=false;dojo.forEach(_4,function(_1e,idx){if(_1e.visible&&_1e.loaded){_12=idx;if((_1e.declaredClass==="esri.layers.FeatureLayer")&&_1e.mode!==esri.layers.FeatureLayer.MODE_SELECTION){_1d=true;_1e.queryFeatures(_b,_1a,_1a);}}});if(!_1d){_e=this._getSnappingPoint(_c,_d,_3);_10.callback(_e);}return _10;},setLayerInfos:function(_1f){this.layers=[];this.layerOptions=[];var i;for(i=0;i<_1f.length;i++){this.layers.push(_1f[i].layer);this.layerOptions.push({snapToPoint:true,snapToVertex:true,snapToEdge:true});if(_1f[i].snapToPoint===false){this.layerOptions[i].snapToPoint=_1f[i].snapToPoint;}if(_1f[i].snapToVertex===false){this.layerOptions[i].snapToVertex=_1f[i].snapToVertex;}if(_1f[i].snapToEdge===false){this.layerOptions[i].snapToEdge=_1f[i].snapToEdge;}}this._nonSelectionLayerCount=0;this._featurePtsFromSelectionLayer=[];this._featureLinesFromSelectionLayer=[];this._selectionLayers=[];this._selectionLayerOptions=[];dojo.forEach(this.layers,function(_20,idx){if(_20.declaredClass==="esri.layers.FeatureLayer"){if(_20.mode===esri.layers.FeatureLayer.MODE_SELECTION){this._selectionLayers.push(_20);this._selectionLayerOptions.push(this.layerOptions[idx]);}else{this._nonSelectionLayerCount++;}}},this);this.layerInfos=_1f;},destroy:function(){dojo.disconnect(this._onExtentChangeConnect);this._killOffSnapping();this._featurePtsFromSelectionLayer=this._featureLinesFromSelectionLayer=this._currentFeaturePts=this._currentFeatureLines=this.layers=this.map=null;},_startSelectionLayerQuery:function(){dojo.disconnect(this._onExtentChangeConnect);this._mapExtentChangeHandler(this._selectionLayers,this._selectionLayerOptions,this.map.extent);this._onExtentChangeConnect=dojo.connect(this.map,"onExtentChange",dojo.hitch(this,"_mapExtentChangeHandler",this._selectionLayers,this._selectionLayerOptions));},_stopSelectionLayerQuery:function(){dojo.disconnect(this._onExtentChangeConnect);},_mapExtentChangeHandler:function(_21,_22,_23){this._featurePtsFromSelectionLayer=[];this._featureLinesFromSelectionLayer=[];var _24;this._SelectionLyrQuery.geometry=_23;var _25=dojo.hitch(this,function(_26){if(_26 instanceof Error){var msg="getSnappingPoint: query features failed";console.log(msg);}else{var _27=this._extractPointsAndLines(_26.features,_22[_24]);this._featurePtsFromSelectionLayer=this._featurePtsFromSelectionLayer.concat(_27[0]);this._featureLinesFromSelectionLayer=this._featureLinesFromSelectionLayer.concat(_27[1]);}});dojo.forEach(_21,function(_28,idx){if(_28.visible&&_28.loaded){_24=idx;_28.queryFeatures(this._SelectionLyrQuery,_25,_25);}},this);},_extractPointsAndLines:function(_29,_2a){var _2b=[],_2c=[];var i,j;dojo.forEach(_29,function(_2d,idx){if(_2d.visible&&_2d.geometry){if(_2d.geometry.type==="point"&&_2a.snapToPoint){_2b.push(_2d.geometry);}else{if(_2d.geometry.type==="polyline"){for(i=0;i<_2d.geometry.paths.length;i++){_2c.push("lineStart");for(j=0;j<_2d.geometry.paths[i].length;j++){var _2e=_2d.geometry.getPoint(i,j);if(_2a.snapToVertex){_2b.push(_2e);}if(_2a.snapToEdge){_2c.push(_2e);}}_2c.push("lineEnd");}}else{if(_2d.geometry.type==="polygon"){for(i=0;i<_2d.geometry.rings.length;i++){_2c.push("lineStart");for(j=0;j<_2d.geometry.rings[i].length;j++){var _2f=_2d.geometry.getPoint(i,j);if(_2a.snapToVertex){_2b.push(_2f);}if(_2a.snapToEdge){_2c.push(_2f);}}_2c.push("lineEnd");}}}}}});return [_2b,_2c];},_getSnappingPoint:function(_30,_31,_32){var _33,_34,_35=this.tolerance;var map=this.map;var _36=this.map._getFrameWidth();_30=_30.concat(this._featurePtsFromSelectionLayer);_31=_31.concat(this._featureLinesFromSelectionLayer);if(this._currentGraphic){var _37=this._extractPointsAndLines([this._currentGraphic],this._currentGraphicOption);_30=_30.concat(_37[0]);_31=_31.concat(_37[1]);}var _38,_39;dojo.forEach(_30,function(pt,idx){var _3a=map.toScreen(pt,true);if(_36!==-1){_3a.x=_3a.x%_36;if(_3a.x<0){_3a.x+=_36;}if(map.width>_36){var _3b=(map.width-_36)/2;while(_3a.x<_3b){_3a.x+=_36;}}}_33=Math.sqrt((_3a.x-_32.x)*(_3a.x-_32.x)+(_3a.y-_32.y)*(_3a.y-_32.y));if(_33<=_35){_35=_33;_38=_3a.x;_39=_3a.y;}});if(_38){var _3c=new esri.geometry.Point(_38,_39);_3c=map.toMap(_3c);_34=_3c;}else{var _3d,_3e,i,j;_35=this.tolerance;for(i=0;i<_31.length;i++){if(_31[i]==="lineStart"){for(j=i+1;j<_31.length;j++){if(_31[j+1]!=="lineEnd"&&_31[j+1]!=="lineStart"&&_31[j]!=="lineEnd"&&_31[j]!=="lineStart"){var _3f=map.toScreen(_31[j],true),_40=map.toScreen(_31[j+1],true),_41=(_3f.x>=_40.x)?_3f:_40,_42=(_3f.x>=_40.x)?_40:_3f;if(_36!==-1){_41.x=_41.x%_36;if(_41.x<0){_41.x+=_36;}_42.x=_42.x%_36;if(_42.x<0){_42.x+=_36;}if(_42.x>_41.x){_42.x-=_36;}}var x1=_41.x,y1=_41.y,x2=_42.x,y2=_42.y;var _43,_44,_45,_46,_47,_48;if(x1===x2){_43=x1;_44=_32.y;_45=_46=x1;_47=(y1<=y2)?y1:y2;_48=(y1<=y2)?y2:y1;}else{if(y1===y2){_43=_32.x;_44=y1;_45=(x1<=x2)?x1:x2;_46=(x1<=x2)?x2:x1;_47=_48=y1;}else{var a=(y2-y1)/(x2-x1),b=(y1*x2-x1*y2)/(x2-x1),_49=(x1-x2)/(y2-y1),_4a=(_32.y*y2-_32.y*y1-_32.x*x1+_32.x*x2)/(y2-y1);_43=(b-_4a)/(_49-a);_44=a*_43+b;_45=(x1<=x2)?x1:x2;_46=(x1<=x2)?x2:x1;_47=(y1<=y2)?y1:y2;_48=(y1<=y2)?y2:y1;}}if(_43>=_45&&_43<=_46&&_44>=_47&&_44<=_48){var _4b=Math.sqrt((_32.x-_43)*(_32.x-_43)+(_32.y-_44)*(_32.y-_44));if(_4b<=_35){_35=_4b;_3d=_43;_3e=_44;}}else{var _4c=Math.sqrt((x1-_32.x)*(x1-_32.x)+(y1-_32.y)*(y1-_32.y));var _4d=Math.sqrt((x2-_32.x)*(x2-_32.x)+(y2-_32.y)*(y2-_32.y));var _4e;if(_4c<=_4d){_4e=_4c;_43=x1;_44=y1;}else{_4e=_4d;_43=x2;_44=y2;}if(_4e<=_35){_35=_4e;_3d=_43;_3e=_44;}}}if(_31[j]==="lineEnd"){i=j;break;}}}}if(_3d){var _4f=new esri.geometry.Point(_3d,_3e);_4f=map.toMap(_4f);_34=_4f;}}return _34;},_setGraphic:function(_50){this._currentGraphic=_50;},_addSnappingPointGraphic:function(){var map=this.map;var _51=this.snapPointSymbol;this._snappingGraphic.setSymbol(_51);map.graphics.add(this._snappingGraphic);},_setUpSnapping:function(){var map=this.map;this._onSnapKeyDown_connect=dojo.connect(map,"onKeyDown",this,"_onSnapKeyDownHandler");this._onSnapKeyUp_connect=dojo.connect(map,"onKeyUp",this,"_onSnapKeyUpHandler");this._onSnappingMouseMove_connect=dojo.connect(map,"onMouseMove",this,"_onSnappingMouseMoveHandler");this._onSnappingMouseDrag_connect=dojo.connect(map,"onMouseDrag",this,"_onSnappingMouseMoveHandler");if(this.alwaysSnap){this._activateSnapping();}},_killOffSnapping:function(){dojo.disconnect(this._onSnapKeyDown_connect);dojo.disconnect(this._onSnapKeyUp_connect);dojo.disconnect(this._onSnappingMouseMove_connect);dojo.disconnect(this._onSnappingMouseDrag_connect);this._deactivateSnapping();},_onSnapKeyDownHandler:function(evt){if(evt.keyCode===this.snapKey){dojo.disconnect(this._onSnapKeyDown_connect);if(this.alwaysSnap){this._deactivateSnapping();}else{this._activateSnapping();}}},_activateSnapping:function(){this._snappingActive=true;this._addSnappingPointGraphic();if(this._currentLocation){this._onSnappingMouseMoveHandler(this._currentLocation);}},_onSnapKeyUpHandler:function(evt){if(evt.keyCode===this.snapKey){this._onSnapKeyDown_connect=dojo.connect(this.map,"onKeyDown",this,"_onSnapKeyDownHandler");if(this.alwaysSnap){this._activateSnapping();}else{this._deactivateSnapping();}}},_deactivateSnapping:function(){this._snappingActive=false;this._snappingPoint=null;this.map.graphics.remove(this._snappingGraphic);this._snappingGraphic.setGeometry(null);},_onSnappingMouseMoveHandler:function(evt){this._currentLocation=evt;this._snappingPoint=null;if(this._snappingActive){this._snappingGraphic.hide();var _52=this.getSnappingPoint(evt.screenPoint);_52.addCallback(this._snappingCallback);}},_snappingCallback:function(_53){this._snappingPoint=_53;if(_53){this._snappingGraphic.show();this._snappingGraphic.setGeometry(_53);}}});}