function IdentifyOption(id, image, altImage)
{
    this.id = id;
	this.image = $get(image);
	if (altImage) this.altImage = $get(altImage);
	//alert(this.image.id);
	this.mapTool;
	this.bufferUnits = "pixels";
};

IdentifyTool = function(map, floatingPanelId, ddlLayersId, hdnEventArgsId, btnSubmitId, progressControlId, hasDefaultClickSubscriber)
{
    this.map = map;
	this.floatingPanelId = floatingPanelId;
	this.floatingPanel = $find(floatingPanelId);
	this.floatingPanel.add_close(Function.createDelegate(this, this._onClosePanel));
	this.ddlLayersId = ddlLayersId;
	this.ddlLayers = $get(ddlLayersId);	
	this.hdnEventArgsId = hdnEventArgsId;
	this.btnSubmitId = btnSubmitId;
	this.progressControlId = progressControlId;
	this.hasDefaultClickSubscriber = hasDefaultClickSubscriber;
	this.eventNumber = 0;
    this.tools = new Array();
	
	this._clickDelegate = Function.createDelegate(this, this._onPointClick);
	this._dblClickDelegate = Function.createDelegate(this, this._onPolygonCreated);	

	this.defaultMapTool = $create(MapsDirect.WebControls.Tools.Point, {map: this.map}, null, null, null);
	this.defaultMapTool.add_click(Function.createDelegate(this, this._onDefaultToolPointClick));
	this.defaultMapTool.graphic.visible = false;
	
	this.inputBufferSize = $get("inputBufferSize");
	this.optionBufferUnits = $get("optionBufferUnits");
	this.pixelToleranceOptionsContainer = $get("pixelToleranceOptionsContainer");
	this.optionPixelTolerance = $get("optionPixelTolerance");
    this.bufferUnits = "Pixels";
    this.isValid = true;
    
    // shortcut to the graphicslayer object
	this.graphicsLayer = this.map.graphicsLayers["tools"];
	
	//point												
	this.tools["point"] = new IdentifyOption("point", "identifyPointImage", "identifyCircleImage");	
	this.tools["point"].mapTool = $create(MapsDirect.WebControls.Tools.Point, {map: this.map}, null, null, null);
	this.tools["point"].mapTool.add_click(this._clickDelegate);
	this.tools["point"].mapTool.graphic.visible = false; 	
	
	//this syncs the default pixel tolerance with the value in the dropdown list
	//as the user modifies the dropdown in the floating panel, those changes with take effect for the default ID as well
	this.tools["point"].mapTool.pixelTolerance = this.optionPixelTolerance.options[this.optionPixelTolerance.selectedIndex].value;
	
	//polygon
	this.tools["polygon"] = new IdentifyOption("polygon", "identifyPolygonImage");
	this.tools["polygon"].mapTool = $create(MapsDirect.WebControls.Tools.Polygon, {map: this.map}, null, null, null);
	this.tools["polygon"].mapTool.add_dblClick(this._dblClickDelegate);
	
	//help
    this.pointHelpString = "Click on the map to identify features at that location.<br /><br />  All features that fall within a pixels range (\"Tolerance\") will be returned.<br /><br />  You may adjust the Tolerance value in the dropdown box above.";
    this.bufferHelpString = "Click on the map to identify features that fall within the specified radius.";
    this.polyHelpString = "This tool identifies features that intersect a user defined shape.<br /><br />Click on the map to add points to your shape.<br /><br />Press the 'DELETE' key to undo your last click.<br /><br />Double-click to complete the shape and submit the identify request.<br /><br />Points in an completed shape can be moved by dragging the associated vertex to the desired location (This will re-submit the identify request).<br /><br />Points can be removed from a completed shape by mousing over the vertex and pressing the 'DELETE' key (This will re-submit the identify request).";
    
    this.defaultTool = "point";
	this.activeTool = this.tools[this.defaultTool];
	// Closing the panel will reset varialbes used in the default click tool
	//this._onClosePanel();
};

IdentifyTool.prototype =
{
    setDefaultTool: function() {
        this.map.set_defaultClickTool(this.defaultMapTool);
    },

    setTool: function(tool, bufferUnits) {
        // map.clear_tool() removes the graphics from the map. So add it back in
        this.map.graphicsLayers["tools"].erase(this.activeTool.graphic);

        this.map.clear_tool();

        this.bufferUnits = bufferUnits;
        if(!this.bufferUnits) this.bufferUnits = "pixels";

        for(var key in this.tools) {
            this.tools[key].image.style.border = "1px solid #FFFFFF";
            if(this.tools[key].altImage) this.tools[key].altImage.style.border = "1px solid #FFFFFF";
            this.tools[key].mapTool.graphic.geometry.clear();
            this.tools[key].mapTool.graphic.geometry.showVertices = false;
        }

        this.activeTool = this.tools[tool];


        if(!this.bufferOptionsContainer) this.bufferOptionsContainer = $get("bufferOptionsContainer");

        if(tool == "point") {
            this.tools["point"].mapTool.add_click(this._clickDelegate);

            if(this.bufferUnits == "pixels") {
                this.floatingPanel.get_helpPanel().innerHTML = this.pointHelpString;
                this.tools["point"].autoCalculateMapUnitRadius = true;
                this.activeTool.image.style.border = "1px solid #919B9C";
                if(this.bufferOptionsContainer) this.bufferOptionsContainer.style.display = "none";
                if(this.pixelToleranceOptionsContainer) this.pixelToleranceOptionsContainer.style.display = "";
            } else {
                this.floatingPanel.get_helpPanel().innerHTML = this.bufferHelpString;
                this.tools["point"].autoCalculateMapUnitRadius = false;
                this.activeTool.altImage.style.border = "1px solid #919B9C";
                if(this.bufferOptionsContainer) this.bufferOptionsContainer.style.display = "";
                if(this.pixelToleranceOptionsContainer) this.pixelToleranceOptionsContainer.style.display = "none";
            }
            this.setRadius();
            this.tools["point"].mapTool.graphic.visible = true;
        } else {
            this.floatingPanel.get_helpPanel().innerHTML = this.polyHelpString;
            this.activeTool.image.style.border = "1px solid #919B9C";
            this.tools["polygon"].mapTool.add_dblClick(this._dblClickDelegate);
            if(this.bufferOptionsContainer) this.bufferOptionsContainer.style.display = "none";
            if(this.pixelToleranceOptionsContainer) this.pixelToleranceOptionsContainer.style.display = "none";
        }
        this.map.set_tool(this.activeTool.mapTool);
    },

    setPixelTolerance: function(value) {
        this.tools["point"].mapTool.pixelTolerance = value;
    },

    setUnits: function(value) {
        this.bufferUnits = value;
        Sys.Debug.trace("units are " + this.bufferUnits);
    },

    setRadius: function() {
        //	    switch(this.bufferUnits)
        //	    {
        //			case "pixels":
        //                this.tools["point"].mapTool.mapUnitRadius = this.pixelTolerance * this.map.get_mapUnitsPerPixelX();
        //                this.isValid=true;
        //				return;
        //		}

        Sys.Debug.trace("setRadius()");
        if(!this.optionBufferUnits) this.optionBufferUnits = $get("optionBufferUnits");

        this.bufferUnits = this.optionBufferUnits.options[this.optionBufferUnits.selectedIndex].value;

        //alert(this.bufferUnits);

        var the_length = this.inputBufferSize.value.length;
        var last_char = this.inputBufferSize.value.charAt(the_length - 1);

        var cleanValue;


        if(last_char == '.') {
            cleanValue = this.inputBufferSize.value;
        } else {
            cleanValue = "" + parseFloat(this.inputBufferSize.value);
        }

        if(cleanValue != "NaN") {
            this.isValid = true;
            this.inputBufferSize.style.backgroundColor = "";
            this.inputBufferSize.value = cleanValue;
        } else {
            this.isValid = false;
            this.inputBufferSize.style.backgroundColor = "#FF5555";
            this.inputBufferSize.value = "";
            return;
        }

        Sys.Debug.trace("this.bufferUnits=" + this.bufferUnits);
        switch(this.bufferUnits) {
            case "Pixels":

                this.tools["point"].mapTool.mapUnitRadius = cleanValue * this.map.get_mapUnitsPerPixelX();
                break;
            default:
                this.tools["point"].mapTool.mapUnitRadius = this.getMapUnitDistance(cleanValue, this.bufferUnits);
                break;
        }

        //alert('this.bufferUnits='+this.bufferUnits+'\nthis.tools["point"].mapTool.mapUnitRadius = ' + this.tools["point"].mapTool.mapUnitRadius);		
        //this.tools["point"].mapTool.mapUnitRadius = inputValue;
        //this.radiusInMapUnits = this.tools["point"].mapTool.mapUnitRadius * this.map.get_mapUnitsPerPixelX();
    },

    getMapUnitDistance: function(inputDistance, inUnits) {
        //Sys.Debug.trace("getMapUnitDistance(), map units are " + this.map._mapUnits);
        //Sys.Debug.trace("getMapUnitDistance(), scale is " + this.map.get_scale());

        var outValue = null;
        var inputUnits = inUnits.toLowerCase();

        //switch on the map units
        //THESE ARE THE UNITS TO BE RETURNED
        switch(this.map.get_mapUnits().toLowerCase()) {
            case "meters":
                if(inputUnits == "feet") outValue = inputDistance * METERS_PER_FEET;
                if(inputUnits == "meters") outValue = inputDistance;
                if(inputUnits == "miles") outValue = inputDistance * METERS_PER_MILE;
                break;
            case "feet":
                if(inputUnits == "feet") outValue = inputDistance;
                if(inputUnits == "meters") outValue = inputDistance * FEET_PER_METER;
                if(inputUnits == "miles") outValue = inputDistance * FEET_PER_MILE;
                break; //
            case "decimaldegrees":
                if(inputUnits == "feet") outValue = inputDistance * 1 / FEET_PER_DEGREE_LAT;
                if(inputUnits == "meters") outValue = inputDistance * 1 / METERS_PER_DEGREE_LAT;
                if(inputUnits == "miles") outValue = inputDistance * 1 / MILES_PER_DEGREE_LAT;
                break;

            default: alert("Map units '" + this.map.get_mapUnits() + "' are not currently supported");
        }
        Sys.Debug.trace("getMapUnitDistance(" + inputDistance + "," + inputUnits + ") = " + outValue);
        return outValue;
    },

    show: function() {
        this.optionsOpen = true;

        floatingPanelManager.closeAll();
        floatingPanelManager.open(this.floatingPanelId);
        this.setTool(this.activeTool.id);


        this.setRadius();
        this.tools["point"].mapTool.graphic.visible = true;
    },

    _onClosePanel: function() {
        this.optionsOpen = false;

        //restore default behavior

        // this.map.set_tool(this.tools["point"].mapTool);

        //this.map.clear_tool();

        this.setTool('point', 'pixels');
        this.tools["point"].mapTool.autoCalculateMapUnitRadius = true;
        this.tools["point"].mapTool.graphic.visible = false;
        //this.tools["point"].mapTool.mapUnitRadius = null;
        //this.bufferUnits = "pixels";

        this.map.clear_tool();
    },

    _onDefaultToolPointClick: function(sender, e) {
        //this.tools["point"].mapTool.pixelTolerance = this.optionPixelTolerance.options[this.optionPixelTolerance.selectedIndex].value;

        // use pixel tolerance value set in hidden option control
        var buffer = this.tools["point"].mapTool.pixelTolerance * this.map.get_mapUnitsPerPixelX();

        // get the point
        var point = sender.get_point().x + "," + sender.get_point().y + ";";

        //submit
        this.submit(point, "point", buffer, true);

    },

    _onPointClick: function(sender, e) {
        if(this.tools["point"].autoCalculateMapUnitRadius == false) {
            this.setRadius();
            if(!this.isValid) return;
        }

        var point = sender.get_point().x + "," + sender.get_point().y + ";";

        //submit
        this.submit(point, "point", this.tools["point"].mapTool.mapUnitRadius, false);

        //update vector object
        if(this.tools["point"].mapTool.graphic.visible) {
            this.tools["point"].mapTool.graphic.geometry.defineGeometry(this.tools["point"].mapTool.get_point(), this.tools["point"].mapTool.mapUnitRadius);

            this.graphicsLayer.draw(this.activeTool.mapTool.graphic);

            //            //TEST CODE
            //            if (this.testGraphic != null) {
            //                this.graphicsLayer.removeItem(this.testGraphic);
            //            }
            //            this.testGraphic = new MapsDirect.Vector.Graphic("polygon");
            //            
            //            var startPoint = new MapsDirect.Geometry.Point();
            //            var newPoint;
            //            var lastPoint = new MapsDirect.Geometry.Point();
            //            var firstRun = true;
            //            
            //            var numPoints = 180;
            //            var incrementBy = Math.round(360/numPoints);
            //            var flippedTheLon = 0;
            //            var skippedLastSegment = false;
            //            
            //            for (var bearing=0; bearing<360; bearing+=incrementBy) {
            //                if (this.testGraphic.geometry.segments.length < 1) {
            //                    this.testGraphic.geometry.segments.push();
            //                }
            //                
            //                newPoint = calcDestinationDDPointByBearingAndDistance_Km(this.tools["point"].mapTool.get_point(), 2000, bearing);
            //                
            //                if (!firstRun) {
            //                    var theNewSegment = new MapsDirect.Geometry.Line({x: lastPoint.x, y: lastPoint.y}, newPoint);
            //	                theNewSegment.skip = false;
            //	                
            //	                if (newPoint.flippedTheLon!=0) {
            //                        if (flippedTheLon==0 || flippedTheLon+newPoint.flippedTheLon==0) {
            //                            flippedTheLon = newPoint.flippedTheLon;
            //                            theNewSegment.skip=true;
            //                        }
            //                    }
            //                    //if we skipped the last segment, this one marks a new ring
            //                    if (skippedLastSegment) {
            //                        theNewSegment.startsNewPathSection=true;
            //                    }
            //                    
            //                    if (!theNewSegment.skip) {
            //                        this.testGraphic.geometry.addSegment(theNewSegment);
            //                        skippedLastSegment=false;
            //	                } else {
            //	                    skippedLastSegment=true;
            //	                }
            //	                
            //	                //Sys.Debug.trace("Test Graphic segment: " + theNewSegment.toString());
            //	            } else {
            //	                startPoint.x = newPoint.x;
            //	                startPoint.y = newPoint.y;
            //	            }
            //                lastPoint.x = newPoint.x;
            //                lastPoint.y = newPoint.y;
            //                firstRun=false;
            //            } 
            //            //close the shape
            //            if (flippedTheLon==0) {
            //                var theNewSegment = new MapsDirect.Geometry.Line({x: lastPoint.x, y: lastPoint.y}, startPoint);
            //	            this.testGraphic.geometry.addSegment(theNewSegment);
            //	        }
            //            
            //            this.testGraphic.style = new MapsDirect.Vector.Style("solid", "red", 2, 1, "yellow", 0.3);
            //            this.graphicsLayer.addItem(this.testGraphic, true);
            //            //END OF TEST CODE
        }
    },

    _onPolygonCreated: function(sender, e) {
        var segments = sender.get_segments();
        if(segments.length > 2) {
            var points;

            // get starting point
            points = segments[0].fromPoint.x + "," + segments[0].fromPoint.y + ";";

            // get all end points
            for(var i = 0; i < segments.length; i++) {
                points += segments[i].toPoint.x + "," + segments[i].toPoint.y + ";";
            }

            this.submit(points, "polygon");
        }
    },

    submit: function(points, mode, buffer, defaultTool) {
        //alert("Identify.js : submit(" + points + " " + mode + ", " + buffer + ")");
        if(!defaultTool || !this.hasDefaultClickSubscriber) {
            SwitchTab("results");
            $get(this.progressControlId).style.display = "block";
        } else {
            this.map.get_element().style.cursor = "wait";
        }

        var idLayer = this.ddlLayers.options[this.ddlLayers.selectedIndex].value;

        var eventArgs;

        if(buffer) {
            eventArgs = "EventArg=" + mode + "&layerid=" + idLayer + "&coords=" + points + "&buffer=" + buffer;
        } else {
            Sys.Debug.trace("submitting shape without buffer...");
            eventArgs = "EventArg=" + mode + "&layerid=" + idLayer + "&coords=" + points;
        }
        eventArgs += "&defaultClick=";
        eventArgs += this.map.get_tool() == null ? "true" : "false";
        $get(this.hdnEventArgsId).value = eventArgs;
        $get(this.btnSubmitId).click();
    }
}
if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();