var mapserver = {
    DPI: 72,
    INCHESPERMETER: 39.3701,
    PANACCURACY: 3,
    MODE_ZOOMIN: 0,
    MODE_RECENTRE: 1,
    MODE_QUERY: 2,
    MODE_DMT: 3,
    CURSORS_0: ['pointer', 'hand'],
    CURSORS_1: ['pointer', 'hand'],
    CURSORS_2: ['default'],
    CURSORS_3: ['pointer', 'hand'],
    MAPSERVER_PARAMS: ['map', 'mapsize', 'layers', 'mapxy', 'scale', 'searchstring', 'feature_na'],

    init: function()
    {
    	this.zoominimage = document.getElementById('zoominimage');
    	if (this.zoominimage)
    	{
    	    this.zoominimage.set = setButton;
    	    this.zoominimage.reset = resetButton;
    	}

    	this.getstatsimage = document.getElementById('getstatsimage');
		if (this.getstatsimage)
		{
    		this.getstatsimage.set = setButton;
    		this.getstatsimage.reset = resetButton;
            if (this.getstatsimage.addEventListener)
            {
                this.getstatsimage.addEventListener('mouseover', function () { popupcontroller.onmouseover(mapserver.getstatsimage, 'getstatspopup', 'below'); }, false);
                this.getstatsimage.addEventListener('mouseout', function () { popupcontroller.onmouseout(0); }, false);
            } else {
                this.getstatsimage.attachEvent('onmouseover', function () { popupcontroller.onmouseover(mapserver.getstatsimage, 'getstatspopup', 'below'); });
                this.getstatsimage.attachEvent('onmouseout', function () { popupcontroller.onmouseout(0); });
            }       
		}

		this.recentremapimage = document.getElementById('recentremapimage');
		if (this.recentremapimage)
		{
			this.recentremapimage.set = setButton;
			this.recentremapimage.reset = resetButton;
		}
		
		this.measuredistanceimage = document.getElementById('measuredistanceimage');
		if (this.measuredistanceimage)
		{
			this.measuredistanceimage.set = setButton;
			this.measuredistanceimage.reset = resetButton;
			if (this.measuredistanceimage.addEventListener)
			{
				this.measuredistanceimage.addEventListener('mouseover', function () { popupcontroller.onmouseover(mapserver.measuredistanceimage, 'dmtpopup', 'below'); }, false);
				this.measuredistanceimage.addEventListener('mouseout', function () { popupcontroller.onmouseout(0); }, false);
			} else {
				this.measuredistanceimage.attachEvent('onmouseover', function () { popupcontroller.onmouseover(mapserver.measuredistanceimage, 'dmtpopup', 'below'); });
				this.measuredistanceimage.attachEvent('onmouseout', function () { popupcontroller.onmouseout(0); });
			}			
		}

        this.params = {
            addLayers: function(layernames)
            {
                var layerlist = this.getLayerList();
                var layernames = layernames.split(' ');
                for (i=0; i < layernames.length; i++) {
                    if (! this.hasLayer(layernames[i]))
                        layerlist.push(layernames[i])
                }
                this.layers = layerlist.join(' ');
            },

            removeLayers: function(layernames)
            {
                var layerlist = this.getLayerList();
                var layernames = layernames.split(' ');
                for (i=0; i < layernames.length; i++) {
                    for (j=0; j < layerlist.length; j++) {
                        if (layerlist[j] == layernames[i])
                            layerlist.splice(j,1);
                    }
                }
                this.layers = layerlist.join(' ');
            },

            hasLayer: function(layername)
            {
                var layerlist = this.getLayerList();
                for (j=0; j < layerlist.length; j++) {
                    if (layerlist[j] == layername)
                        return true;
                }
                return false;
            },

            emptyLayerList: function()
            {
                delete this.layers;
            },

            hasParameter: function(paramname)
            {
                for (propname in this) {
                    if (propname == paramname)
                        return true;
                }
                return false;
            },

            toString: function(baseurl, appendurl)
            {
                var paramstrings = [];
                if (! baseurl)
                    baseurl = mapserver.mapserverurl + 'map=' + mapserver.mapfilepath + '&'
                var urlstring = baseurl;
                for (paramname in this) {
                    if (! (paramname == 'urlappend' || paramname == 'toString' || paramname == 'hasParameter' || paramname == 'addLayers' || paramname == 'removeLayers' || paramname == 'hasLayer' || paramname == 'emptyLayerList' || paramname == 'getLayerList'))
                        paramstrings.push(paramname + '=' + escape(this[paramname]));
                }
                if (paramstrings.length > 0)
                    urlstring += paramstrings.join('&');
                if (appendurl)
                	return urlstring + '&urlappend=' + escape(this.urlappend);
                else
                	return urlstring + this.urlappend;
            },
            
            getLayerList: function()
            {
                if (! this.layers)
                    return [];
                else
                    return this.layers.split(' ');
            }
        }

        var params = window.location.search.substring(1).split('&');
        this.params.urlappend = '';
        for (var i = 0; i < params.length; i++)
        {
            var pos = params[i].indexOf('=');
        	var paramname = params[i].substring(0,pos);
        	var paramvalue = unescape(params[i].substring(pos+1));
        	if (paramname == 'urlappend')
        		this.params.urlappend = paramvalue;
            if (pos > 0)
            {
            	for (index in this.MAPSERVER_PARAMS)
            	{
            	    if (paramname == this.MAPSERVER_PARAMS[index] || paramname.indexOf('map_') == 0)
            	    {
                		this.params[params[i].substring(0,pos)] = unescape(params[i].substring(pos+1).replace(/\+/, ' '));
                	}
                }
            }
        }

        if (this.defaultlayers)
            this.params.addLayers(this.defaultlayers);

        if (! this.params.mode)
            this.interfacemode = this.MODE_ZOOMIN;
        else {
            this.interfacemode = this.params.mode;
            delete this.params.mode;
        }

        if (! this.params.map_web)
            this.params.map_web = 'TEMPLATE ' + this.mapdatapath + 'ajax.html';

        this.iframe = this.getIFrame();

        this.previouscursor = '';

        //this.viewonly = false;
        this.maploading = document.getElementById('maploading');
        
        this.mapimage = document.getElementById('mapimg');
		this.mapclicksensor = this.mapimage;

		var jsgraphicscanvas = document.getElementById('jsgraphicscanvas');

		if (jsgraphicscanvas)
		{
			this.mapclicksensor = jsgraphicscanvas;
		    this.canvas = new jsGraphics(jsgraphicscanvas);
		    this.canvas.setColor('purple');
		    this.canvas.setStroke(2);
		    this.canvas.setPrintable(false);
		    this.canvas.distance = 0;
		    this.clearCanvas();
		}

		if (! this.viewonly)
			this.mapclicksensor.style.cursor = 'progress';
		
        this.refreshInterface();
    },
    
    refreshInterface: function()
    {
        if (! this.viewonly && this.mapclicksensor.style.cursor != 'progress')
            this.previouscursor = this.mapclicksensor.style.cursor;

        this.mapclicksensor.onclick == null;

        if (! this.viewonly) {
            try {
                this.mapclicksensor.style.cursor = 'progress';
            } catch(e) {
                void(0);
            }
        }

        this.maploading.style.visibility = 'visible';
        this.mapimage.style.visibility = 'hidden';
        
        if (this.spacerurl)
            this.mapimage.src = this.spacerurl;

		if (this.setnortharrow && this.params.hasParameter('scale') && this.params.hasParameter('mapxy'))
		{
		    var center = this.params['mapxy'].split(' ');
		    center[0] = parseFloat(center[0]);
		    center[1] = parseFloat(center[1]);
		    if (this.params.hasParameter('mapsize'))
		    	var mapsize = this.params.mapsize.split(' ');
		    else
			    var mapsize = this.kvp['mapsize'].split(' ');
		    var width = parseInt(mapsize[0]);
		    var height = parseInt(mapsize[1]);
		    var cellsize = (parseFloat(this.params['scale']) / this.DPI) / this.INCHESPERMETER;
		    var extminx = center[0] - cellsize * width/2;
		    var extminy = center[1] - cellsize * height/2;
		    var extmaxx = center[0] + cellsize * width/2;
		    var extmaxy = center[1] + cellsize * height/2;
		    var p = new Proj('EPSG:42304');
		    var extmingeo = p.Inverse([extminx, extminy]);
		    var extmaxgeo = p.Inverse([extmaxx, extmaxy]);
		    var miny = this.pixelToGeo(height/2-10, 0, height, extmingeo[1], extmaxgeo[1]);
		    var maxy = this.pixelToGeo(height/2+10, 0, height, extmingeo[1], extmaxgeo[1]);
		    var point1 = p.Forward([(extmaxgeo[0] - extmingeo[0])/2+extmingeo[0], maxy]);
		    var point2 = p.Forward([(extmaxgeo[0] - extmingeo[0])/2+extmingeo[0], miny]);
		    var topp = point1[1]-point2[1];
		    var deltax = point1[0]-point2[0];
		    var deltay = point1[1]-point2[1];
		    var bottom = Math.sqrt(deltax*deltax + deltay*deltay);
		    if (bottom == 0)
		        var deg = 90;
		    else
		        var deg = (Math.asin(topp/bottom)/(2*Math.PI))*360;

		    if (point1[0]-point2[0] < 0)
				deg = 90-deg;
		    else
				deg = -1*(90-deg);
			deg = -1*deg;
		
		    this.params['map_layer[northarrow]_class[0]_style[0]'] = 'ANGLE ' + deg;
		}
        
        url = this.params.toString();

        if (this.iframe.location && this.iframe.location.href)
            this.iframe.location.href = url;
        else
            this.iframe.src = url;
    },

    getIFrame: function()
    {
        if (frames)
            return frames['iframe'];
        else
            return document.getElementById('iframe');
    },

	getLegendBox: function()
	{
		var legendbox = document.getElementById('mytab_2');
		if (! legendbox)
			var legendbox = document.getElementById('legendBox');
		return legendbox;
	},
    
    parseMapServerResults: function()
    {
        iframedoc = this.getIFrameDocument();
        kvptable = iframedoc.getElementsByTagName('table')[0];
        kvptablerows = kvptable.getElementsByTagName('tr');
        this.kvp = new Object();
        for (index = 0; index < kvptablerows.length; index++)
        {
            cells = kvptablerows.item(index).getElementsByTagName('td');
            keyword = cells[0].firstChild.data;
            if (cells[1].firstChild)
                value = cells[1].firstChild.data;
            else
                value = null;
            this.kvp[keyword] = value;
        }

		var legendbox = this.getLegendBox();
		if (legendbox)
		{
			legendbox.innerHTML = iframedoc.getElementsByTagName('DIV')[0].innerHTML;
	        inputs = legendbox.getElementsByTagName('INPUT');
	        for (index = 0; index < inputs.length; index++)
	        {
	            input = inputs.item(index);
	            if (! this.viewonly)
	            {
	                input.onclick = onClickedLegendControl;
	            } else {
	                input.disabled = true;
	            }
	        }
		}

        if (this.kvp['layerlist'])
            this.params.layers = this.kvp['layerlist'];
        
        if (this.kvp['scale'])
            this.params.scale = this.kvp['scale'];

        if (this.kvp['mapxy'])
            this.params.mapxy = this.kvp['mapxy'];

        this.mapimage.src = this.kvp['image'];
        document.getElementById('scalebarimage').src = this.kvp['scalebar'];
        if (document.getElementById('referencemapimage'))
        	document.getElementById('referencemapimage').src = this.kvp['ref'];

		this.mapimage.style.visibility = 'visible';
        this.maploading.style.visibility = 'hidden';
        
        if (! this.viewonly)
        	this.mapclicksensor.onclick = onMapClick;

        this.setMapCursor();

		if (document.getElementById('scaledisplay'))
	        document.getElementById('scaledisplay').value = this.addCommas(Math.round(this.kvp['scale']));
        
        if (this.runafterloadfunc)
            this.runafterloadfunc();
    },

	addCommas: function(x1) {
		x1 = x1.toString();
		var rgx = /(\d+)(\d{3})/;
		while (rgx.test(x1))
			x1 = x1.replace(rgx, '$1' + ' ' + '$2');
		return x1;
	},

    getIFrameDocument: function()
    {
        if (this.iframe.contentDocument)
            return this.iframe.contentDocument;
        else
            return this.iframe.document;
    },
    
    getMapClickCoordinates: function(event)
    {
        imgx = (event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft) - (document.getElementById('contentContainer').offsetLeft + document.getElementById('mapContainer').offsetLeft + document.getElementById('mapFrame').offsetLeft + document.getElementById('map').offsetLeft + this.mapclicksensor.offsetLeft) - 2;
        imgy = (event.clientY + document.documentElement.scrollTop + document.body.scrollTop) - (document.getElementById('contentContainer').offsetTop + document.getElementById('mapContainer').offsetTop + document.getElementById('mapFrame').offsetTop + document.getElementById('map').offsetTop + this.mapclicksensor.offsetTop) - 3;
        return [imgx, imgy];
    },
    
    zoomIn: function(imgx, imgy)
    {
        mapxy = this.imgxyTomapxy(imgx, imgy);
        nextscaledown = this.getNextScales()[0];
        if (parseInt(nextscaledown) == parseInt(this.kvp['scale'])) {
            alert(this.maxzoommessage);
            return;
        }
        this.params.scale = nextscaledown;
        this.params.mapxy = mapxy[0].toString() + ' ' + mapxy[1].toString();
        this.refreshInterface();
    },

	zoomToPoint: function(mapx, mapy, zoomlevel)
	{
        this.params.scale = this.kvp['zoom_' + zoomlevel.toString()];
        this.params.mapxy = mapx.toString() + ' ' + mapy.toString();
        this.refreshInterface();
	},
    
    imgxyTomapxy: function(imgx, imgy)
    {
        extent = this.sanitizeExtent(this.kvp['mapext'])
        finalx = ((imgx+1) * (parseFloat(this.kvp['dx']) / parseFloat(this.kvp['mapwidth']))) + extent[0];
        finaly = extent[3] - ((imgy+1) * (parseFloat(this.kvp['dy']) / parseFloat(this.kvp['mapheight'])));
        return [finalx, finaly];
    },
    
    getNextScales: function()
    {
        nextscaledown = nextscaleup = null;
        currmapscale = parseInt(this.kvp['scale']);
        for ( count = 0; count < 10; count++ )
        {
            zoomstring = 'zoom_' + count.toString()
            if (parseInt(this.kvp[zoomstring]) == currmapscale) {
                if ( count != 9 ) {
                    if ( this.kvp['zoom_'+(count+1).toString()].charAt(0) == '[' )
                        nextscaledown = this.kvp['scale'];
                    else
                        nextscaledown = this.kvp['zoom_' + (count+1).toString()];
                } else {
                        nextscaledown = this.kvp[zoomstring];
                }
                if ( count == 9 )
                    nextscaledown = this.kvp['zoom_9']
                if ( count == 0 ) {
                    nextscaleup = this.kvp[zoomstring];
                } else {
                    nextscaleup = this.kvp['zoom_' + (count-1).toString()];
                }
            }
            if (nextscaleup && nextscaledown)
                return [nextscaledown, nextscaleup];
        }
        
        for ( count = 0; count < 10; count++ )
        {
            currzoomscale = parseInt(this.kvp['zoom_' + count.toString()]);
            if (count == 9 || this.kvp['zoom_'+ (count+1).toString()].charAt(0) == '[')
                return [currmapscale, currzoomscale];
            nextzoomscale  = parseInt(this.kvp['zoom_'+ (count+1).toString()]);
            if ( currmapscale < currzoomscale && currmapscale > nextzoomscale )
            {
                nextscaledown = nextzoomscale;
                nextscaleup = currzoomscale;
                return [nextscaledown, nextscaleup];
            }
        }
    },
    
    setMapCursor: function()
    {
        if (! this.viewonly)
        {
            if (this.previouscursor != '')
            {
                this.mapclicksensor.style.cursor = this.previouscursor;
                this.previouscursor = '';
            } else {
                cursors = this['CURSORS_' + this.interfacemode.toString()];
                for (i = 0; i < cursors.length; i++)
                {
                    try {
                        this.mapclicksensor.style.cursor = cursors[i];
                    } catch(e) {
                        void(0);
                    }
                }
            }
        }
    },
    
    sanitizeExtent: function(extent)
    {
        if (typeof extent == 'string')
            extent = extent.split(' ');
        minx = parseFloat(extent[0]);
        miny = parseFloat(extent[1]);
        maxx = parseFloat(extent[2]);
        maxy = parseFloat(extent[3]);
        return [minx, miny, maxx, maxy];
    },
    
    zoomOut: function()
    {
        mapxy = this.getMapCenterCoordinates();
        nextscaleup = this.getNextScales()[1];
        this.params.scale = nextscaleup;
        this.params.mapxy = mapxy[0].toString() + ' ' + mapxy[1].toString();
        this.refreshInterface();
    },
    
    getMapCenterCoordinates: function()
    {
        return this.imgxyTomapxy(parseFloat(this.kvp['center_x']), parseFloat(this.kvp['center_y']));
    },
    
    resetMapExtent: function()
    {
        this.params.scale = this.kvp['zoom_0'];
        delete this.params.mapxy;
        this.refreshInterface();
    },
    
    queryMapPoint: function(imgx, imgy)
    {
        mapxy = this.imgxyTomapxy(imgx, imgy);
        url = this.pointqueryurl + 'map=' + this.mapfilepath + '&mode=nquery&imgxy=' + imgx.toString() + '+' + imgy.toString() + '&imgext=' + escape(this.kvp['mapext']) + '&imgsize=' + this.kvp['mapwidth'] + '+' + this.kvp['mapheight'] + '&mapxy=' + mapxy[0].toString() + '+' + mapxy[1].toString();
        layerlist = this.params.getLayerList();
        if (layerlist.length > 0)
            url = url + '&layers=' + escape(layerlist.join(' '));
        window.open(url, 'query', 'height=360,width=500,location=no,menubar=no,resizable=yes,scrollbars=yes,status=yes,personal=no');
    },

    onZoomInClick: function()
    {
        this.zoominimage.set();
        this.getstatsimage.reset();
		if (this.recentremapimage)
	        this.recentremapimage.reset();
		if (this.measuredistanceimage)
	        this.measuredistanceimage.reset();
        this.clearCanvas();
        this.interfacemode = this.MODE_ZOOMIN;
        this.setMapCursor();
    },

    onGetStatsClick: function()
    {
        this.getstatsimage.set();
        this.zoominimage.reset();
        if (this.recentremapimage)
	        this.recentremapimage.reset();
		if (this.measuredistanceimage)
	        this.measuredistanceimage.reset();
        this.clearCanvas();
        this.interfacemode = this.MODE_QUERY;
        this.setMapCursor();
    },

    resizeMap: function(x, y)
    {
        this.params.mapsize = x + ' ' + y;
        delete this.params.map_web;
        this.refreshPage();
    },

    refreshPage: function(url)
    {
    	if (url)
    		finalurl = url + '?';
    	else
    		finalurl = this.pageurl + '?';
        url = this.params.toString(finalurl, true);
        window.location = url;
    },
    
    clickedPanArrow: function(dir)
    {
        // this.resetDMT();
        acc = this.PANACCURACY * 2;
        center_x = parseInt(this.kvp['center_x']);
        center_y = parseInt(this.kvp['center_y']);
        offset_x = parseInt(this.kvp['mapwidth'])/acc;
        offset_y = parseInt(this.kvp['mapheight'])/acc;
        switch (dir)
        {
            case 'up':
                imgx = center_x;
                imgy = center_y - offset_y;
                break;
            case 'down':
                imgx = center_x;
                imgy = center_y + offset_y;
                break;
        	case 'left':
                imgx = center_x - offset_x;
                imgy = center_y;
                break;
        	case 'right':
                imgx = center_x + offset_x;
                imgy = center_y;
                break;
            case 'upleft':
                imgx = center_x - offset_x;
                imgy = center_y - offset_y;
                break;
        	case 'upright':
                imgx = center_x + offset_x;
                imgy = center_y - offset_y;
                break;
        	case 'downleft':
                imgx = center_x - offset_x;
                imgy = center_y + offset_y;
                break;
            case 'downright':
                imgx = center_x + offset_x;
                imgy = center_y + offset_y;
                break;
        }
        this.recentreMap(imgx, imgy, this.kvp['mapwidth'], this.kvp['mapheight'], this.kvp['mapext'].split(' '));
    },

    recentreMap: function(imgx, imgy, width, height, extent) {
        extent = this.sanitizeExtent(extent);
        finalx = (imgx*((extent[2]-extent[0])/width))+minx;
        finaly = maxy-(imgy*((extent[3]-extent[1])/height));
        this.params['scale'] = this.kvp['scale'];
        this.params['mapxy'] = finalx.toString() + ' ' + finaly.toString();
        this.refreshInterface();
    },

    onRecentreClick: function()
    {
        this.recentremapimage.set();
        this.zoominimage.reset();
        this.measuredistanceimage.reset();
        this.getstatsimage.reset()
        this.clearCanvas();
        this.interfacemode = this.MODE_RECENTRE;
        this.setMapCursor();
    },
    
    onMeasureDistanceClick: function()
    {
        this.measuredistanceimage.set();
        this.zoominimage.reset();
        this.recentremapimage.reset();
        this.getstatsimage.reset()
        this.clearCanvas();
        this.interfacemode = this.MODE_DMT;
        this.setMapCursor();
    },
    
    clearCanvas: function()
    {
		if (this.canvas) {
		    this.canvas.Xpoints = new Array();
		    this.canvas.Ypoints = new Array();
		    this.canvas.clear();
		    this.canvas.distance = 0;
		    this.updateDistanceDisplay();
		}
    },

	updateDistanceDisplay: function()
	{
		display = document.getElementById('distanceboxinput').firstChild;
		if (this.canvas.distance < 1000)
		{
		    display.value = Math.round(this.canvas.distance).toString() + 'm';
		} else {
		    if (parseFloat(this.kvp['scale']) >= parseFloat(this.kvp['zoom_6']) && parseFloat(this.kvp['scale']) <= parseFloat(this.kvp['zoom_3']))
		        display.value = (Math.round(this.canvas.distance/10)/100).toString() + 'km';
		    else
		        display.value = Math.round(this.canvas.distance/1000).toString() + 'km';
		}
	},

    canvasDraw: function(imgx, imgy)
    {
		this.canvas.drawLine(imgx-5, imgy, imgx+5, imgy);
		this.canvas.drawLine(imgx, imgy+5, imgx, imgy-5);
		this.canvas.Xpoints.push(imgx);
		this.canvas.Ypoints.push(imgy);
		this.canvas.drawLine(this.canvas.Xpoints[this.canvas.Xpoints.length-2], this.canvas.Ypoints[this.canvas.Ypoints.length-2], this.canvas.Xpoints[this.canvas.Xpoints.length-1], this.canvas.Ypoints[this.canvas.Ypoints.length-1]);
		this.canvas.paint();
		if (this.canvas.Xpoints.length > 2) {
		    this.canvas.Xpoints.shift();
		    this.canvas.Ypoints.shift();
		} else {
	        document.getElementById('measuredistanceimage').reset();
		}
		if (this.canvas.Xpoints.length >= 2) {
		    latest = this.imgxyTomapxy(imgx, imgy);
		    previous = this.imgxyTomapxy(this.canvas.Xpoints[this.canvas.Xpoints.length-2], this.canvas.Ypoints[this.canvas.Ypoints.length-2]);
		    xdiff = latest[0] - previous[0];
		    ydiff = latest[1] - previous[1];
		    this.canvas.distance += Math.sqrt(xdiff*xdiff + ydiff*ydiff);
		    this.updateDistanceDisplay();
		}
	},

	zoomToScale: function(scale)
	{
		scale = scale.replace(/,/g,'');
		scale = scale.replace(/ /g,'');
		scale = scale.replace(/K/g,'000');
		scale = scale.replace(/k/g,'000');
		scale = scale.replace(/M/g,'000000');
		scale = scale.replace(/m/g,'000000');
		scale = parseInt(scale);
		minscale = 0;
		for (i=0; i<10; i++)
		{
		    zoomscale = this.kvp['zoom_'+ i.toString()];
		    if (zoomscale.toString().charAt(0) != '[' || i != 9) {
		        minscale = this.kvp['zoom_'+ i.toString()];
		    } else {
		        break;
		    }
		}
		if (scale <= parseFloat(this.kvp['zoom_0']) && scale >= minscale)
		{
		    mapxy = this.getMapCenterCoordinates();
	        this.params.scale = scale.toString();
    	    this.params.mapxy = mapxy[0].toString() + ' ' + mapxy[1].toString();
		    this.refreshInterface();
		} else {
		    alert(this.invalidscalemessage);
		}
	},

	pixelToGeo: function(pixpos, pixmin, pixmax, geomin, geomax)
	{
	    // calculate the geocoded & pixel width
	    widthgeo = geomax - geomin;
	    widthpix = pixmax - pixmin;
	
	    // get ratio
	    pixtogeo = widthgeo / widthpix;
	
	    // get difference
	    deltapix = pixpos - pixmin;
	
	    // calculate
	    deltageo = deltapix * pixtogeo;
	    posgeo = geomin + deltageo;
	
	    // return value
	    return posgeo;
	},
	
	zoomToExtent: function(minx, miny, maxx, maxy)
	{
		var finalscale = this.getBestScaleForExtent(minx, miny, maxx, maxy);
		var finalx = minx + ((maxx - minx)/2)
		var finaly = miny + ((maxy - miny)/2)
		this.params.scale = finalscale;
		this.params.mapxy =  finalx.toString() + ' ' + finaly.toString();
		this.refreshInterface();
	},

	getBestScaleForExtent: function(minx, miny, maxx, maxy)
	{
		reqscale = (maxx - minx) / (parseInt(this.kvp['mapwidth']) / (this.DPI * this.INCHESPERMETER));
		if (reqscale >= this.kvp['zoom_0'])
			index = 0;
		else if (reqscale <= this.kvp['zoom_9'])
			index = 9;
		else {
		    for (count = 1; count < 10; count ++)
		    {
		    	diffup = this.kvp['zoom_' + (count - 1)] - reqscale
		    	diffdown = reqscale - this.kvp['zoom_' + count]
		    	if (diffup > 0 && diffdown > 0)
		    	{
		        	if (diffup > diffdown)
		        		index = count;
		      		else
		        		index = count - 1;
		        }
			}
		}
		for (i=index; i >= 0; i--)
		{
			if (this.kvp['zoom_' + i.toString()].charAt(0) != '[')
		    	return this.kvp['zoom_' + i.toString()];
		}
	},

	printMap: function()
	{
		baseurl = this.pageurl;
		width = this.kvp['mapwidth'];
		height = this.kvp['mapheight'];
		if (width == '428' && height == '380')
		{
		    this.params['mapsize'] = '428 380';
		    baseurl += '/' + this.printtemplates['small'];
		}
		if (width == '525' && height == '466')
		{
			this.params['mapsize'] = '525 466';
		    baseurl += '/' + this.printtemplates['medium'];
		}
		if (width == '750' && height == '666')
		{
			this.params['mapsize'] = '750 666';
		    baseurl += '/' + this.printtemplates['large'];
		}
		if (width == '1150' && height == '1350')
		{
			this.params['mapsize'] = '1150 1350';
		    baseurl += '/' + this.printtemplates['xtralarge'];
		}
		this.refreshPage(baseurl);
	}
}

function setButton()
{
	this.onmouseover = null;
	this.onmouseout = null;
	this.src = mapserver.buttondata[this.id]['pressed'];
}

function resetButton()
{
	this.src = mapserver.buttondata[this.id]['depressed'];
	this.onmouseover = function() { MM_swapImage(this.id, '', mapserver.buttondata[this.id]['hover'], 1); }
	this.onmouseout = function() { MM_swapImgRestore(); }
}

function onMapClick(event)
{
    if (window.event)
        event = window.event
    click = mapserver.getMapClickCoordinates(event);
    imgx = click[0];
    imgy = click[1];

	switch (mapserver.interfacemode)
	{
		case mapserver.MODE_ZOOMIN:
			mapserver.zoomIn(imgx, imgy);
			break;
		case mapserver.MODE_QUERY:
			mapserver.queryMapPoint(imgx, imgy);
			break;
		case mapserver.MODE_RECENTRE:
			mapserver.recentreMap(imgx, imgy, mapserver.kvp['mapwidth'], mapserver.kvp['mapheight'], mapserver.kvp['mapext'].split(' '));
			break;
		case mapserver.MODE_DMT:
			mapserver.canvasDraw(imgx, imgy);
			break;
	}
}

function onClickedLegendControl(event) {
    if (window.event)
        event = window.event;
    layerlist = mapserver.params;
    if (event.target)
        control = event.target;
    else if (event.srcElement)
        control = event.srcElement;
    exclusive = control.getAttribute('exclusive');
    inputs = mapserver.getLegendBox().getElementsByTagName('input');
    if (control.type == 'checkbox') {
        if (control.checked) {
            if (exclusive != null) {
                if (layerlist.hasLayer('fapfeature'))
                    preservefapfeature = true;
                else
                    preservefapfeature = false;
                layerlist.emptyLayerList();
                if (preservefapfeature)
                    layerlist.addLayers('fapfeature');
            }
            layerlist.addLayers(control.value);
        } else {
            layerlist.removeLayers(control.value);
            if (exclusive != null)
                layerlist.addLayers(mapserver.defaultlayers);
        }
    } else if (control.type == 'radio') { 
        for (index = 0; index < inputs.length; index++) {
            if (inputs.item(index).type == 'radio') {
                if (inputs.item(index).checked)
                    layerlist.addLayers(inputs.item(index).value);
                else
                    layerlist.removeLayers(inputs.item(index).value);
            }
        }
    }
    mapserver.refreshInterface();
}

function resizeContentContainer() {
//set contentContainer height according to legend height
	if (document.getElementById('legendBox')) {
	  var d = document.getElementById('contentContainer'); // Get div element
      var dh = d.offsetHeight;
	  var l = document.getElementById('legendBox'); // Get div element
      var lh = l.offsetHeight;
      if ((dh-45) < lh)
		d.style.height = (lh + 10) + 'px'; // Set div height to legend height only if div height is less than legend height;
	}
}

function zoomToLatLong(westletter)
{
	var zoomlevel = 4;
	var latdeg = document.getElementById('tbxlatdeg').value;
	var latmin = document.getElementById('tbxlatmin').value;
	var latsec = document.getElementById('tbxlatsec').value;
	var londeg = document.getElementById('tbxlongdeg').value;
	var lonmin = document.getElementById('tbxlongmin').value;
	var lonsec = document.getElementById('tbxlongsec').value;
	ddregex = /^\d+\.\d+$/;
	if (! (ddregex.test(latdeg) || ddregex.test(londeg)))
	{
		latdeg = parseInt(latdeg, 10);
		latmin = parseInt(latmin, 10);
		latsec = parseInt(latsec, 10);
		londeg = parseInt(londeg, 10);
		lonmin = parseInt(lonmin, 10);
		lonsec = parseInt(lonsec, 10);
		if (isNaN(latdeg) || isNaN(londeg) || latdeg < 0 || latdeg > 90 || londeg < 0 || londeg > 180)
		{
			alert('Invalid degrees input.');
			return;
		}
		if (isNaN(latmin))
		{
			latmin = 0;
		} else if (latmin < 0 || latmin > 60) {
			alert('Invalid latitude minutes.');
			return;
		}
		if (isNaN(lonmin))
		{
			lonmin = 0;
		} else if (lonmin < 0 || lonmin > 60) {
			alert('Invalid longitude minutes.');
			return;
		}
		if (isNaN(latsec))
		{
			latsec = 0;
		} else if (latsec < 0 || latsec > 60) {
			alert('Invalid latitude seconds.');
			return;
		}
		if (isNaN(lonsec))
		{
			lonsec = 0;
		} else if ( lonsec < 0 || lonsec > 60 ) {
			alert('Invalid longitude seconds.');
			return;
		}
		lat = convertDMSToDD(latdeg, latmin, latsec);
		lon = convertDMSToDD(londeg, lonmin, lonsec) * -1;
		mapstring = latdeg + '° ' + latmin + '\' ' + latsec + '\'\' N' + ' ' + londeg + '° ' + lonmin + '\' ' + lonsec + '\'\' ' + westletter;
	} else {
		lat = parseFloat(latdeg);
		lon = parseFloat(londeg) * -1;
		mapstring = latdeg + '° N' + ' ' + londeg + '° ' + westletter;
	}
	p = new Proj('EPSG:42304');
	center = p.Forward([lon, lat]);
	mapserver.params.addLayers('fapfeature');
	mapserver.params.removeLayers('million_grid t50k_grid grid_50k_3 grid_50k');
	mapserver.params['map_layer[arrowlatlongall]'] = 'FEATURE POINTS ' + center[0].toString() + ' ' + center[1].toString() + ' END TEXT "' + mapstring + '" END END';
	mapserver.params['map_layer[arrowlatlongallarrow]'] = 'FEATURE POINTS ' + center[0].toString() + ' ' + center[1].toString() + ' END END';
	mapserver.params['mapxy'] = center[0].toString() + ' ' + center[1].toString();
	mapserver.params['scale'] = mapserver.kvp['zoom_' + zoomlevel.toString()];
	mapserver.refreshInterface();
}

