function WsNav(){
    this.mapInstanceKey = null;
    this.zoom = 0;
    this.mapBounds = null;
    this.xmin = 0;
    this.xmax = 0;
    this.ymin = 0;
    this.ymax = 0;
    this.xminInitial = 0;
    this.xmaxInitial = 0;
    this.yminInitial = 0;
    this.ymaxInitial = 0;
    this.initialized = false;
    this.workspaceKey = null;
    this.baseHREF = null;
    this.baseHREFpns = null;
    this.tools = new Object();
    this.eventListeners = new Array();
    this.distanceUnit = "";
    this.oppositeDistanceUnit = "";
    this.srs = "";
    this.nn6=document.getElementById&&!document.all;
    this.mapWidth = 640;
    this.mapHeight = 480;
    this.isLoading = false;
    this.imgseq = 0;
    this.imageMimeType = "image/gif";
    this.previousTool = "";
    this.hasAnnotations = false;
}

function getScrollX() {
  var scrOfX = 0;
  if( typeof( window.pageYOffset ) == 'number' ) {
    //Netscape compliant
    scrOfX = window.pageXOffset;
  } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
    //DOM compliant
    scrOfX = document.body.scrollLeft;
  } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
    //IE6 standards compliant mode
    scrOfX = document.documentElement.scrollLeft;
  }
  return scrOfX;
}

function getScrollY() {
  var scrOfY = 0;
  if( typeof( window.pageYOffset ) == 'number' ) {
    //Netscape compliant
    scrOfY = window.pageYOffset;
  } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
    //DOM compliant
    scrOfY = document.body.scrollTop;
  } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
    //IE6 standards compliant mode
    scrOfY = document.documentElement.scrollTop;
  }
  return scrOfY;
}

WsNav.prototype.getGlobalImgX=function(){
    var xscroll = getScrollX(); 
    return findPosX(this.getImg())+(this.nn6?0:2) - xscroll;
}

WsNav.prototype.getGlobalImgY=function(){
    var verticalScroll = getScrollY();  
    return findPosY(this.getImg())+(this.nn6?0:2) - verticalScroll;
}

WsNav.prototype.getImg=function(){
    return document.getElementById("imgMap"+this.imgseq);
}

WsNav.prototype.switchImg=function(){
    if(this.imgseq==1)
        this.imgseq = 0;
    else
        this.imgseq = 1;
}

WsNav.prototype.getImgAlt=function(){
    var temp = 0;
    if(this.imgseq==0)
        temp=1;
    return document.getElementById("imgMap"+temp);
}

WsNav.prototype.modifyImage=function(x,y,w,h){
    this.getImg().width = w;
    this.getImg().height = h;
    this.getImg().style.left = x + "px";
    this.getImg().style.top = y + "px";
}

WsNav.prototype.init=function(){
    this.dispatch("map_init_start");
    
    this.getImg().width = this.mapWidth;
    this.getImg().height = this.mapHeight;
    
    this.getImgAlt().width = this.mapWidth;
    this.getImgAlt().height = this.mapHeight;
    
    document.getElementById("divDraw").style.width = this.mapWidth + "px";//resout bug firefox, agilbert
    document.getElementById("divDraw").style.height = this.mapHeight + "px";//resout bug firefox, agilbert
    document.getElementById("divMap").style.width = this.mapWidth + "px";
    document.getElementById("divMap").style.height = this.mapHeight + "px";
    this.loadingAction(true);
    if(this.mapInstanceKey==null)
        this.createMapInstanceKey();
    if(this.distanceUnit!="")
        this.setDistanceUnit(this.distanceUnit);
    if(this.srs!="")
        this.setSRS(this.srs);
    var temp = this;
    document.getElementById("divMap").onmousedown = function(e){ 
        if (!e) var e = window.event;
        if(!temp.isLoading&&((!temp.nn6&&e.button==1)||(temp.nn6&&e.which==1))){
            for(id in temp.tools){      
                if(temp.tools[id].toggle&&temp.tools[id].selected){
                    if(temp.tools[id].maponmousedown){
                        //temp.dispatch("toggletoolstart");
                        temp.tools[id].maponmousedown(e);
                    }
                }
            }
        }
        return false;
    } 
    document.getElementById("divMap").onmouseup = function(e){ 
        if (!e) var e = window.event;
        if(!temp.isLoading&&((!temp.nn6&&e.button==1)||(temp.nn6&&e.which==1))){
            for(id in temp.tools){      
                if(temp.tools[id].toggle&&temp.tools[id].selected){
                    if(temp.tools[id].maponmouseup){
                        temp.tools[id].maponmouseup(e);
                        //temp.dispatch("toggletoolend");
                    }
                }
            }
        }
        return false;
    }
    document.getElementById("divMap").ondblclick = function(e){ 
        if (!e) var e = window.event;
        if(!temp.isLoading&&((!temp.nn6&&e.button==0)||(temp.nn6&&e.which==1))){
            for(id in temp.tools){      
                if(temp.tools[id].toggle&&temp.tools[id].selected){
                    if(temp.tools[id].mapondblclick){
                        temp.tools[id].mapondblclick(e);
                    }
                }
            }
        }
        return false;
    } 
    document.getElementById("divMap").onmousemove = function(e){
        if(!temp.isLoading){
            for(id in temp.tools){      
                if(temp.tools[id].toggle&&temp.tools[id].selected){
                    if(temp.tools[id].maponmousemove){
                        if(temp.tools[id].drawing){
                            temp.dispatch("map_drawing");
                        }
                        temp.tools[id].maponmousemove(e);
                    }
                }
            }
        }
        return false;
    }
    document.getElementById("divMap").onmouseout = function(e){ 
        if(!temp.isLoading){
            for(id in temp.tools){      
                if(temp.tools[id].toggle&&temp.tools[id].selected){
                    if(temp.tools[id].maponmouseout){
                        temp.tools[id].maponmouseout(e);
                    }
                }
            }
        }
        return false;
    }
    this.dispatch("map_init_end");
    this.initialized = true;
}


WsNav.prototype.click=function(id){    
    if(this.tools[id].toggle){
        if(this.tools[id].selected){
            this.unselect(id);
        }else{
            this.select(id);
        }
    }
    if(this.tools[id].click){
        this.tools[id].click();
    }
}

WsNav.prototype.select=function(id){
    if(id != "ruler" && id != "pointOverlay"){this.previousTool = id;}    //To select the previous tool once the ruler has been used

    this.clearselect();
    this.tools[id].selected = true;
    if(this.tools[id].select != null) 
        this.tools[id].select();
    var img = document.getElementById("tool_"+id+"_img");
    if(img!=null){
        document.getElementById("tool_"+id+"_img").className = "tool_"+id+"_selected";
    }
}

WsNav.prototype.unselect=function(id){
    this.clearselect();
    if(this.tools[id].unselect){
        this.tools[id].unselect();
    }
}

WsNav.prototype.clearselect=function(){
    for(z in this.tools){      
        if(this.tools[z].selected){
            if(this.tools[z].toggle){     
                if(this.tools[z].unselect != null) 
                    this.tools[z].unselect();
                this.tools[z].selected=false;
                var img = document.getElementById("tool_"+z+"_img");
                if(img!=null){
                    document.getElementById("tool_"+z+"_img").className = "tool_"+z;
                }
            }
        }
    }
}

WsNav.prototype.loadingAction=function(response){
    this.isLoading = response;
    document.getElementById("divLoading").style.left = (this.mapWidth/2)-(document.getElementById("imgLoading").width/2) + "px";
    document.getElementById("divLoading").style.top =  (this.mapHeight/2)-(document.getElementById("imgLoading").height/2) + "px";	
    if (response==true)
        document.getElementById("divLoading").style.display =  'block';
    else
        document.getElementById("divLoading").style.display =  'none';	
}

WsNav.prototype.mapLoaded=function(){
    if(this.initialized){
        this.getImg().style.left=0;
        this.getImg().style.top=0;
        this.getImg().width = this.mapWidth;
        this.getImg().height = this.mapHeight;
        this.getImg().style.visibility = 'visible';
        this.getImgAlt().style.visibility = 'hidden';
        
        this.updateZoom();
        this.updateBounds();
        this.loadingAction(false);
        this.dispatch("map_loaded");
    }
}

WsNav.prototype.isMapInstanceKeyValid=function(){
    var isValid = true;
    if ( this.mapInstanceKey.indexOf("<html>") != -1 )
        isValid = false;   
    return isValid;
}

WsNav.prototype.createMapInstanceKey=function(){
    var url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MappingSessionService&method=createMapInstanceKey&mapKey="+this.workspaceKey+"&refresh="+Math.random(); 
    
    //    document.location=url;
    var x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
    this.mapInstanceKey =  x.responseText.replace(/^\s*|\s*$/g,"");
    if(this.isMapInstanceKeyValid() == false){
        alert("Unable to create mapInstanceKey.");
        alert(x.responseText);
    }
}

WsNav.prototype.updateZoom=function(){
    this.zoom =  this.getZoom();
}

WsNav.prototype.updateBounds=function(){
    var url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=getBounds&mapInstanceKey="+this.mapInstanceKey+"&contentType=text/xml&refresh="+Math.random(); 
    var x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
    this.bounds = x.responseText;
    try{
        this.srs = x.responseXML.getElementsByTagName("Box").item(0).attributes.item(0).value;
    }catch(exception){
        alert("Unable to get srs info");
    }
    this.xmin = Number(x.responseXML.getElementsByTagName("X").item(0).firstChild.nodeValue);
    this.xmax = Number(x.responseXML.getElementsByTagName("X").item(1).firstChild.nodeValue);
    this.ymin = Number(x.responseXML.getElementsByTagName("Y").item(0).firstChild.nodeValue);
    this.ymax = Number(x.responseXML.getElementsByTagName("Y").item(1).firstChild.nodeValue);
    if(this.xminInitial==0&&this.xmaxInitial==0&&this.yminInitial==0&&this.ymaxInitial==0){
        this.xminInitial = this.xmin;
        this.xmaxInitial = this.xmax;
        this.yminInitial = this.ymin;
        this.ymaxInitial = this.ymax;
    }
}

WsNav.prototype.getBounds=function(){
    var url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=getBounds&mapInstanceKey="+this.mapInstanceKey+"&contentType=text/xml&refresh="+Math.random(); 
    var x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
    this.bounds = x.responseText;
    return this.bounds;
}

WsNav.prototype.getBoundsExt=function(srsName){
    var url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=getBounds&mapInstanceKey="+this.mapInstanceKey+"&contentType=text/xml&srsName="+srsName+"&refresh="+Math.random(); 
    var x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
    return x.responseText;
}

WsNav.prototype.getZoom=function(){
    var url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=getZoom&mapInstanceKey="+this.mapInstanceKey+"&refresh="+Math.random(); 
    var x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
    return x.responseText;
}

WsNav.prototype.getZoomExt=function(unit){
    var url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=getZoom&mapInstanceKey="+this.mapInstanceKey+"&unit="+unit+"&refresh="+Math.random(); 
    var x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
    return Number(x.responseText);
}

WsNav.prototype.setZoom=function(zoom){
    url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=setZoom&mapInstanceKey="+this.mapInstanceKey+"&zoom="+zoom+"&refresh="+Math.random(); 
    x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}

WsNav.prototype.setZoomExt=function(zoom, unit){
    url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=setZoom&mapInstanceKey="+this.mapInstanceKey+"&zoom="+zoom+"&unit="+unit+"&refresh="+Math.random(); 
    x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}

WsNav.prototype.setDistanceUnit=function(unit){
    url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=setDistanceUnits&mapInstanceKey="+this.mapInstanceKey+"&unit="+unit+"&refresh="+Math.random(); 
    x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}

WsNav.prototype.setSRS=function(srs){
    url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=setNumericCoordSys&p.1.string="+this.mapInstanceKey+"&p.2.string="+srs+"&refresh="+Math.random(); 
    x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}

WsNav.prototype.setCenter=function(x,y){
    var url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=setCenter&mapInstanceKey="+this.mapInstanceKey+"&centerx="+x+"&centery="+y+"&refresh="+Math.random(); 
    var x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}

WsNav.prototype.setCenterExt=function(x,y,srsName){
    var url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=setCenter&mapInstanceKey="+this.mapInstanceKey+"&centerx="+x+"&centery="+y+"&srsName="+srsName+"&refresh="+Math.random(); 
    var x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}

WsNav.prototype.setZoomAndCenter=function(zoom,x,y){
    var url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=setZoomAndCenter&mapInstanceKey="+this.mapInstanceKey+"&zoom="+zoom+"&centerx="+x+"&centery="+y+"&refresh="+Math.random(); 
    var x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}

WsNav.prototype.setZoomAndCenterExt=function(zoom,x,y,srsName,unit){
    var url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=setZoomAndCenter&mapInstanceKey="+this.mapInstanceKey+"&zoom="+zoom+"&centerx="+x+"&centery="+y+"&srsName="+srsName+"&unit="+unit+"&refresh="+Math.random(); 
    var x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}

WsNav.prototype.setBounds=function(x1,y1,x2,y2){
    url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=setBounds&mapInstanceKey="+this.mapInstanceKey+"&xmin="+x1+"&ymin="+y1+"&xmax="+x2+"&ymax="+y2+"&refresh="+Math.random(); 
    x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}

WsNav.prototype.setBoundsExt=function(x1,y1,x2,y2, srsName){
    url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=setBounds&mapInstanceKey="+this.mapInstanceKey+"&xmin="+x1+"&ymin="+y1+"&xmax="+x2+"&ymax="+y2+"&srsName="+srsName+"&refresh="+Math.random(); 
    x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}

WsNav.prototype.setLayerVisibility=function(layerID, visible){
    url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=setLayerVisibility&mapInstanceKey="+this.mapInstanceKey+"&layerID="+layerID+"&visible="+visible+"&refresh="+Math.random(); 
    x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}

WsNav.prototype.stretchFromBounds=function(x1,y1,x2,y2){
    var r = (this.xmax-this.xmin)/(x2-x1);
    var w = r*this.mapWidth;
    var h = r*this.mapHeight;
    var x = (x1-this.xmin)/(this.xmax-this.xmin)*w*-1;
    var y = (this.ymax-y2)/(this.ymax-this.ymin)*h*-1;
    this.modifyImage(x,y,w,h);
}

WsNav.prototype.setInitialBounds=function(){
    this.stretchFromBounds(this.xminInitial, this.yminInitial, this.xmaxInitial, this.ymaxInitial);
    this.setBounds(this.xminInitial, this.yminInitial, this.xmaxInitial, this.ymaxInitial);
}

WsNav.prototype.refreshMap=function(){    
    if(divDraw.innerHTML != ""){divDraw.innerHTML = ""}    //To remove the ruler information once the map changes

    if (this.mapInstanceKey!=null){
        this.dispatch("map_refresh");
        this.loadingAction(true);
        this.dispatch("mappreload");
        var url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=MapService&method=getImage&mapInstanceKey="+this.mapInstanceKey+"&mapWidth="+this.mapWidth+"&mapHeight="+this.mapHeight+"&contentType="+this.imageMimeType+"&refresh="+Math.random(); 
        this.switchImg();
        this.getImg().src = url;	
    }
}

WsNav.prototype.addEventListener=function(listener){
    this.eventListeners[this.eventListeners.length]=listener;
}

WsNav.prototype.dispatch=function(name){
    for(var i=0;i<this.eventListeners.length;i++){
        if(this.eventListeners.length){
            if(this.eventListeners[i].mapevent){
                this.eventListeners[i].mapevent(name);
            }
        }
    }
}

WsNav.prototype.getDistanceFromScreen=function(px1,py1,px2,py2){
    url = this.baseHREF+"/wsnav/WebServiceCaller.do?service=CommonService&method=getDistanceFromScreen&mapInstanceKey="+this.mapInstanceKey+
    "&xmin="+this.xmin+
    "&ymin="+this.ymin+
    "&xmax="+this.xmax+
    "&ymax="+this.ymax+
    "&px1="+px1+
    "&py1="+py1+
    "&px2="+px2+
    "&py2="+py2+
    "&srs="+this.srs+
    "&unit="+this.distanceUnit+
    "&mapWidth="+this.mapWidth+
    "&mapHeight="+this.mapHeight+
    "&refresh="+Math.random(); 
    x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
    return Number(x.responseText);
}

WsNav.prototype.getPointFromLongLat=function(longitude, latitude, poiImgId) {
    var pointOnMap = new Array();
    var rangeX = this.xmax - this.xmin;
    var rangeY = this.ymax - this.ymin;
    var pointX = (longitude - this.xmin) * ( this.mapWidth / rangeX );
    var pointY = (this.ymax - latitude) * ( this.mapHeight / rangeY );
    
    if (poiImgId && document.getElementById(poiImgId)) {
        var poiImg = document.getElementById(poiImgId);
        pointX = pointX  - ( poiImg.height / 2 );
        pointY = pointY - ( poiImg.width / 2);  
    }
    pointOnMap[0] = pointX;
    pointOnMap[1] = pointY;
    if (!this.isValidPoint(pointOnMap)) {
        alert('Point is outside map boundaries.');
    }
    //alert(pointOnMap);
    return pointOnMap;
}

WsNav.prototype.isValidPoint=function(pointOnMap) {
    if (pointOnMap[0] && pointOnMap[0] < this.mapWidth) {
        return true;
    }
    if (pointOnMap[1] && pointOnMap[1] < this.mapHeight) {
        return true;
    }
}

WsNav.prototype.addPoint=function(layername, id, x, y, rendition, srsName){
    var url = this.baseHREF+"/wsnav/WebServiceCaller.do?pnsURL="+this.baseHREFpns+"&service=AnnotationService&method=addPoint&p.1.string="+this.mapInstanceKey+"&p.2.string="+layername+"&p.3.string="+id+"&p.4.double="+x+"&p.5.double="+y+"&p.6.string="+rendition+"&p.7.string=&p.8.string=&p.9.string="+srsName+"&refresh="+Math.random(); 
    var x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}

WsNav.prototype.removePoint=function(layername, id){
    var url = this.baseHREF+"/wsnav/WebServiceCaller.do?pnsURL="+this.baseHREFpns+"&service=AnnotationService&method=removeFeature&p.1.string="+this.mapInstanceKey+"&p.2.string="+layername+"&p.3.string="+id+"&refresh="+Math.random(); 
    var x = createXmlHttpRequest();
    x.open("GET",url,false);
    x.send(null);
}