var SITESELECTOR;

//Class representing a node on the tree.
function DataNode(nodeID, parentNode, treeElement, areaType, areaID, isOpen){
    this.nodes = [];
    this.nodeID = nodeID;
    this.eLabels= [];
    this.siteData = [];
    this.nodes = [];
    this.parentNode = parentNode;
    this.treeElement = treeElement;
    this.extent = null;
    this.childrenLoaded = false;
    this.areaType = areaType;
    this.areaID = areaID;
    this.isOpen = isOpen;
    this.contentActive = false;
    
    this.toggleSiblings = function(){
        if(!parentNode){return;}
        for(var j=0; j<this.parentNode.nodes.length; j++){
            var node = this.parentNode.nodes[j];
            if (node.isOpen && (node.nodeID != this.nodeID)){
                node.toggleState(true);
            }
        }
    }
    
    
    this.toggleState = function(toggleParent, forceOn){

            var isOpen = !this.isOpen;
            
            //may be forced to be switched on.
            if (forceOn){isOpen = true;}
            
            //let the node know it's state
            this.isOpen = isOpen;
            
            if (isOpen) {SITESELECTOR.activeNode = this;}

            //
            if (this.parentNode && toggleParent){
                //NOT recursive
                this.parentNode.toggleContentState(!isOpen, false);
                if (!isOpen) {SITESELECTOR.activeNode = this.parentNode;}
            }

            //show/hide the node and contents recursively 
            this.toggleContentState(isOpen, true);           

            if(isOpen){
                this.treeElement.className = 'redSideBarOpen';
            } else {
                this.treeElement.className = 'redSideBarClosed';
            }
            
            //activate/deactivate the li (for prettiness' sake)
            var li = this.treeElement.childNodes[0];
            var cn = li.className;
            var suffix = cn.slice(2);
            var prefix = cn.slice(0, 2);
            if (isOpen) {li.className = prefix+'active';}
            else {li.className = prefix+'inactive';}
            
            //set the internal state flag.
            this.isOpen = isOpen;  
 
      }
    
    //Will switch the parent data off and the child data on, or vice versa.
    //if recursive flag is true, all descendants will also be toggled.
    this.toggleContentState = function(active, recursive){
        
        if (active && !this.isOpen) {return;}
        
        this.showHideMapData(this.siteData, active);
        this.showHideMapData(this.eLabels, active);    
        
        if (this.parentNode){
            if (active && this.parentNode.isOpen){
                this.parentNode.toggleContentState(false, false)
            }
        }

        if(recursive){
           for (var i=0; i<this.nodes.length; i++){
              this.nodes[i].toggleContentState(active, recursive);
           }      
        }
    }

    //shows/hides map data held in an array
    this.showHideMapData = function(arr, active){

        for (var i=0; i<arr.length; i++){
            if(active){
                arr[i].show();
            } else {
                arr[i].hide();
            }
        }
    
    }
}

function init(){

SITESELECTOR = new SiteSelector(-5.2062,50, 2.5, 55.019)

//SITESELECTOR = new SiteSelector(-14,35,12,63)


}

var SiteSelector = Class.create({
    
    initialize: function(minX, minY, maxX, maxY) {
        //Range checking for input 
        
        if ((minX>=maxX) || (minY>=maxY)){
            alert("Invalid extent.");
            return;
        }

       
        this.geocoder = new GClientGeocoder();
       
        var mapDiv = $('redMap');
        //create the basic legend elements
        var legendTbody = $('redLegendTbody');
        var infoDiv = $('infoDiv');
      
        this.infoDiv = infoDiv;
        
        this.geocodeInput = $('redGeocodeInput');
        this.countrySelect = $('redCountrySelect');
                    
        Event.observe($('redGetAddresses'), "click", this.getAddresses.bindAsEventListener(this));

        //this.map = new GMap2(mapDiv);
        
        //set the legend member variable
        this.legendTbody = legendTbody;
        
        
        this.geocodeTbody = $('redGeocodeResponseTbody');
        
        //initialise map
        this.map = new GMap2(mapDiv);
        //get the bounds from constructor

        this.zoomToBounds(minX, minY, maxX, maxY);

        //add the small pan zoom control
        this.map.addControl(new GSmallMapControl());
        this.map.parentObject = this;
        //create icons
        this.iconArray = new Hash();
        //holds service types
        this.serviceTypes = new Hash();
        
        this.serviceTypeNames = new Hash();
        //Add listenter to get POIs on MOVEEND event
        //GEvent.addListener(this.map, "moveend", function(){this.yourMum.getPOI();});
         
        //need to use a hash object to keep all unique values in key
        this.legendData = new Hash();
        this.treeData = new Hash();

        
        this.currentRequests = new Hash();
        this.sidebar = $('redMapSidebar');
        this.requestCount = 0;
        this.nodeCount = 0;
        this.getIcons();
        this.getCountries();
        this.treeData = new DataNode(0, null, this.sidebar, 'continent', null, true);

        //make initial query. Always look in Europe.
        this.queryMap(this.treeData);

},
    
    //get country data
    getCountries: function(){
        new Ajax.Request('ajax/getCountries.php', {
        method: 'get',
        onSuccess: this.displayCountries.bindAsEventListener(this)
        });
    },

    displayCountries: function(responseObj){
        var countries = responseObj.responseText.evalJSON();
        for (var i=0; i<countries.length; i++){
            var opt = new Element('option').update(countries[i].countryname);
            this.countrySelect.appendChild(opt);
        }
    },

    
    zoomToBounds: function(minX, minY, maxX, maxY){
        //alert("minX: "+minX+" minY: "+minY+" maxX: "+maxX+" maxY: "+maxY);
        var bounds = new GLatLngBounds(new GLatLng(parseFloat(minY), parseFloat(minX)),new GLatLng(parseFloat(maxY), parseFloat(maxX)));
        //get the lowest zoom level at which the bounds fit in the map.
        var startZoom = this.map.getBoundsZoomLevel(bounds);
        //centre the map on the centre of the passed bounds
        var c = bounds.getCenter();
        if (!this.activeNode){startZoom++}
        this.map.setCenter(bounds.getCenter(), startZoom);
    },

    zoomToBoundsObj: function(bounds){

        this.zoomToBounds(bounds.minx, bounds.miny, bounds.maxx, bounds.maxy);
        
    },
    
    debug: function(arr){
        var t = $('debug1');
        var tr = t.insertRow(t.rows.length);
        for (var i=0; i<arr.length; i++){
            var td = tr.insertCell(tr.cells.length);
            td.innerHTML = arr[i];
        }
    },
    
    //Takes a data node and queries the DB for it's child nodes. regionID and noZoom are optional, for when geocoding.
    queryMap: function(dataNode, regionID, noZoom){
       

	//alert("queryMap" + "__" + dataNode + "__" + regionID + "__" + noZoom)

	 var url = "./ajax/getMapData.php";
        //Very important! set the request id.
        reqID = 'req'+this.requestCount++;
        this.currentRequests.set(reqID, {'dataNode':dataNode, 'regionID':regionID, 'noZoom': noZoom});
        //TODO remove this later to avoid memory leak.
        


	//alert("areatype/id = " + dataNode.areaType + "," + dataNode.areaID)
	//alert(dataNode.areaID)
	//alert(globalServiceTypes.join(','))


        new Ajax.Request(url, {
        method: 'get',
        parameters: {'st':globalServiceTypes.join(','),
                     'areatype':dataNode.areaType,
                     'areaid':dataNode.areaID,
                     'reqid':reqID
                    },
        onSuccess: this.queryMapResults.bindAsEventListener(this)
        });
    },
    
    //Takes ajax results. Decides where to send the data for display.  Also does the zooming.
    queryMapResults: function(responseObj){

      var response = responseObj.responseText.evalJSON();


      returnType = response.returnType;
      reqID = response.reqID;
      
	  //alert(returnType + "__" + reqID)

      //get the request object
      var req = this.currentRequests.get(reqID);
            
      if (response.returnType == 'sitedata'){
        this.displaySiteData(response.data, req.dataNode);
      } else {

	//alert(response.data.length)

	//for(c=0;c < response.data.length;c++){
//
//		alert(response.data[c].sitecount)
//	}

//	alert(req.dataNode + "__" + response.returnType)


        this.displayAreaData(response.data, req.dataNode, response.returnType);
      }
      
      //set the extent
      var ext = Object.clone(response.extent);
      	  //alert(ext)

      req.dataNode.extent = ext;
      
      if (!req.noZoom){this.zoomToBoundsObj(ext)};

       
      req.dataNode.childrenLoaded = true;
    
      //if a callback is set, we need to do another query for a region.
      if (req.regionID){
        var dataNode = this.findDataNode(this.treeData, 'areaID', req.regionID);
        this.queryMap(dataNode, false, true);
      }
    
    },

    //find a datanode in the tree according to its ID.
    findDataNode: function(treeNode, attributeName, attribute){
        if (treeNode[attributeName]==attribute){return treeNode;}
        var node;
        var nodes = treeNode.nodes;
        for (var i=0; i<nodes.length; i++){
            node = nodes[i];
            if(node[attributeName]){
                if (node[attributeName]==attribute){return node;}
                node = this.findDataNode(node, attributeName, attribute);
                if (node){return node;}
            }
        }
        
    },
 
    //displays lables on the map. May be regions or countries.
    displayAreaData: function(areas, parentNode, areaType){
        
        var treeElement = parentNode.treeElement;
        var treeLevel = Math.abs(treeElement.getAttribute('treeLevel'));
        var newTreeLevel = treeLevel + 1;
        var liClass = 'l'+ newTreeLevel +'inactive';
        
        //DISPLAY THE AREAS.
        for (var i=0; i<areas.length; i++){
            //check we have sites!
            if (areas[i].sitecount == 0){continue;}
            
            //create a new nodeID
            var nodeID = ++this.nodeCount;
            
            var x = areas[i].x;
            var y = areas[i].y;
            
            var html = "<table onclick='SITESELECTOR.displayNodeDataByNodeID("+nodeID+")' class='region'><tr><td>"+areas[i].areaname + "</td></tr><tr><td>"+areas[i].sitecount  + " Sites</td></tr></table>";
            var label = this.createRegionLabel(new GLatLng(y, x), html, new GSize(-40,0))
            this.map.addOverlay(label);
            //this.mapareas[i] = label;
            
            var ul = new Element('ul', {'class':'redSidbarClosed','treeLevel':newTreeLevel, 'nodeID':nodeID});
            treeElement.appendChild(ul);
            var li = new Element('li', {'class':liClass, 'nodeID':nodeID});
            ul.appendChild(li);
            var a = new Element('a', {'href':'#'}).update(areas[i].areaname);
            li.appendChild(a);
            
            Event.observe(li, 'click', this.handleSideBarClick.bindAsEventListener(this));
        
            //create a new data node with the node id
            var newNode = new DataNode(nodeID, parentNode, ul, areaType, areas[i].areaid);
            
            //add the new node to the parent node
            parentNode.nodes.push(newNode);
            //add the label to the parent
            parentNode.eLabels.push(label);
            
        }
        
    },

    //displays sites.
    displaySiteData: function(siteData, dataNode){
          
        var prevST = "";
        var st, theServiceType, theIcon, markerTypeActive, markerData;
         
        for (var i=0; i<siteData.length; i++){
            if (siteData[i].st != prevST){
                st = "st"+siteData[i].st;
                theServiceType = this.serviceTypes.get(st);
                theIcon = theServiceType.icon;
                markerTypeActive = theServiceType.isActive;
            }
            prevST= siteData[i].st;
            //create a marker
            var marker = this.CreateMarker(new GLatLng(siteData[i].y, siteData[i].x), theIcon, siteData[i].id, st);


            //add the marker to the map
            this.map.addOverlay(marker);
            dataNode.siteData.push(marker);
            
            //hide the marker if layer is not active
            if (!markerTypeActive) {marker.hide();}            
        } 

	//---NE Update 19/09/08 (Need to show the region nodes if necessary - were not shown on intial search and thus info bubble did not have data to show)
        //if(getRegion){
        	//dataNode = this.findDataNode(this.treeData, 'areaID', areaID);
		//alert(dataNode.nodeID)
		if(dataNode.nodeID != 0){
			dataNode.toggleState(true, true);
       			var nodes = dataNode.parentNode.nodes;
        		//need to hide all nodes at this level
        		for (var i=0; i<nodes.length; i++) {
            			//hide all open nodes
            			if (nodes[i].isOpen && (nodes[i].nodeID != dataNode.nodeID)){
                			nodes[i].toggleState(false);
				}
        		}
		}
	//
 
 	for (c=0; c<globalServiceTypes.length; c++) {
		serviceTypeID = "st" + globalServiceTypes[c];
		var theCheckBox = $(serviceTypeID);
		if(theCheckBox.checked){
			var isActive = true;

		}else{
			var isActive = false;
		}

		var siteData = dataNode.siteData
		var theMarker;
        	for (var i=0; i<siteData.length; i++) {
            		theMarker = siteData[i];
            		if (theMarker.st == serviceTypeID){
                		if (isActive){
                    			theMarker.show();
                		} else {
                    			theMarker.hide();
                		}             
            		}
		}

        }  
	//---End of update


        //Activenode may not be datanode in this function.
        //if (!noZoom){this.zoomToBoundsObj(Object.clone(this.activeNode.extent));

        
    },

    
    handleSideBarClick: function(evt){
        //get the element, making sure it's an LI
        var elem = evt.element();
        if (elem.tagName != 'LI'){
            if (elem.tagName == 'A'){
                var li = elem.parentNode;
            }
        }
        
        var treeNode = li.parentNode;
        //if(treeNode.tagName != 'UL'){alert('treenode is a '+treeNode.tagName)}
        
        var nodeID = li.getAttribute('nodeid');
        
        this.displayNodeDataByNodeID(nodeID);
     },
     
     displayNodeDataByNodeID: function(nodeID){
        //find the datanode associated with this node ID.
        var dataNode = this.findDataNode(this.treeData, 'nodeID', nodeID);
        this.displayNodeData(dataNode);
     },
     
     //separated from handlesidebarclick to allow it to be called by querymap if doing recursive ajax.
     displayNodeData: function(dataNode, areaID, noZoom, forceOn){    
        
	var getRegion = false;
        //3 possibilities - not loaded yet, loaded and opening, loaded and closing
        if (!dataNode.childrenLoaded){//not loaded
            //areaID and noZoom are optional arguments, passed through for use by the geocode function.
		getRegion = true;            
		this.queryMap(dataNode, areaID, noZoom);  
        } 
        
        dataNode.toggleState(true, forceOn);
        var nodes = dataNode.parentNode.nodes;

        //need to hide all nodes at this level
        for (var i=0; i<nodes.length; i++) {
            //hide all open nodes
            if (nodes[i].isOpen && (nodes[i].nodeID != dataNode.nodeID)){
                nodes[i].toggleState(false);
            }
        }
        

	//---NE Update 19/09/08 (Need to show the region nodes if necessary - were not shown on intial search and thus info bubble did not have data to show)
        if(getRegion){
        	dataNode = this.findDataNode(this.treeData, 'areaID', areaID);
		if(dataNode.nodeID != 0){
			dataNode.toggleState(true, forceOn);
       			var nodes = dataNode.parentNode.nodes;
        		//need to hide all nodes at this level
        		for (var i=0; i<nodes.length; i++) {
            			//hide all open nodes
            			if (nodes[i].isOpen && (nodes[i].nodeID != dataNode.nodeID)){
                			nodes[i].toggleState(false);
            			}
        		}
		}
	}

 	for (c=0; c<globalServiceTypes.length; c++) {
		serviceTypeID = "st" + globalServiceTypes[c];
		var theCheckBox = $(serviceTypeID);
		if(theCheckBox.checked){
			var isActive = true;

		}else{
			var isActive = false;
		}

		var siteData = dataNode.siteData
		var theMarker;
        	for (var i=0; i<siteData.length; i++) {
            		theMarker = siteData[i];
            		if (theMarker.st == serviceTypeID){
                		if (isActive){
                    			theMarker.show();
                		} else {
                    			theMarker.hide();
                		}             
            		}
		}

        }  

	//---End of update


        //Activenode may not be datanode in this function.
        //if (!noZoom){this.zoomToBoundsObj(Object.clone(this.activeNode.extent));}

    },

     createRegionLabel: function (point,html, offset) {
        var label = new ELabel(point, html, "regionLabel", offset, 80, true);
        return label;
      },
  
    getIcons: function(){
      var url = "./ajax/getIcons.php";
      
      new Ajax.Request(url, {
        method: 'get',
        onSuccess: this.setIcons.bindAsEventListener(this)
      });
    },
   
    //Creates an array of gmap icons that can be used DIRECTLY in markers
    setIcons: function(responseObj){

        var theIcons = responseObj.responseText.evalJSON();        
        var theIcon;
        var imgWidth, imgHeight;
        var theServiceType;
        
        //retreive the icon
        for (var i=0; i<theIcons.length; i++) {
            
            //create the icon
            theIcon = new GIcon();
            theIcon.image = theIcons[i].imageURL;
            theIcon.iconSize = new GSize(theIcons[i].width, theIcons[i].height);
            theIcon.iconAnchor = new GPoint((theIcons[i].width/2), theIcons[i].height);
            theIcon.infoWindowAnchor = new GPoint((theIcons[i].width/2), theIcons[i].height);
            //create a servicetype object.
            theServiceType = new Object();
            theServiceType.serviceDescription = theIcons[i].serviceDescription;
            theServiceType.icon = {icon:theIcon};
            theServiceType.markerData = new Array();
            theServiceType.isActive = true;
            
            this.serviceTypes.set(("st" + theIcons[i].serviceType), theServiceType);
            
        }
        this.drawLegend();
    },
    
    
    //draws legend.
    //Legend data is a 2d array, 3 items wide holding layername, markertype and typeid
    drawLegend: function() {
    
    //table row var
    var tr;
    var serviceTypeID, icon, descr;
    var theServiceType;
    //Add all items to legend table
    for (i=0; i<globalServiceTypes.length; i++) {
        
        //FOUR CELLS MAKE UP AN ITEM IN THE LEGEND
        //Insert layer name and checkbox switcher
        
        //make a row for the legend entry
        tr = this.legendTbody.insertRow(this.legendTbody.rows.length);
        td = tr.insertCell(tr.cells.length);

        //get the icon for the service type
        serviceTypeID = "st" + globalServiceTypes[i];
        theServiceType = this.serviceTypes.get(serviceTypeID);
        icon = theServiceType.icon;
        descr = theServiceType.serviceDescription;
        
        //create a checkbox
        var legendChk = document.createElement("INPUT");
        legendChk.setAttribute("type","checkbox");
	legendChk.setAttribute("id", serviceTypeID);   //NE - Updated
        legendChk.serviceTypeID = serviceTypeID;

        td.appendChild(legendChk);

        //attach an event handler to checkbox. Using prototype to maintain scope to this instance.
        //passes arguments retrieved using $A(arguments) in event listener
        Event.observe(legendChk, "click", this.handleToggleServiceType.bindAsEventListener(this));


        td = tr.insertCell(tr.cells.length);
        td.innerHTML = descr;
        legendChk.checked = true;

        //insert marker icon image
        td = tr.insertCell(tr.cells.length);
        
        //Avoid problems with ie png deficiencies.  Set the background url and size of the table cell to match the image.
        if (td.addEventListener) {
            td.setStyle({width: icon.icon.iconSize.width + 'px'});
            td.style.backgroundImage = 'url('+icon.icon.image+')';
            td.style.backgroundRepeat = 'no-repeat';
            
        } else { //need to tell directX to transform the image.
            td.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+icon.icon.image+"', sizingMethod='image')";
        }

    }
    
    legendDiv = $('redLegend');
    geocodeDiv = $('redGeocodeHeader');
    
    var max = Math.max(legendDiv.getHeight(), geocodeDiv.getHeight());
    
    legendDiv.setStyle({height: (max+'px')})
    geocodeDiv.setStyle({height: (max+'px')})
    
    },
    
    
    clearLegend: function() {
        
        //remove any rows currently in table
        rowCount = this.legendTbody.rows.length;
       //delete rows in table
        for (var j=(rowCount-1); j>-1; j--) {
          this.legendTbody.deleteRow(j);
        } 
    },

    //creates a legend markertype entry
    addLegendServiceType: function (td, serviceTypeDescription, serviceTypeID, visible) {
        
        //create a checkbox
        var legendChk = document.createElement("INPUT");
        legendChk.setAttribute("type","checkbox");
        legendChk.serviceTypeID = serviceTypeID;

        //attach an event handler to checkbox. Using prototype to maintain scope to this instance.
        //passes arguments retrieved using $A(arguments) in event listener
        Event.observe(legendChk, "click", this.handleToggleServiceType.bindAsEventListener(this));

        var label1 = document.createElement("LABEL");
        label1.innerHTML = serviceTypeDescription;
        label1.className = "redLegendLabel";
        //append the child elements
        legendChk = td.appendChild(legendChk);
        legendChk.checked = visible;
        td.appendChild(label1);
    },
    

    //toggles a serviceType. Avoids turning on layers in group layers that are not active.
    handleToggleServiceType: function(evt) {

        //get the servicetype from the legend checkbox
        var serviceTypeID = evt.target.serviceTypeID;
        
        //get layer
        var theServiceType = this.serviceTypes.get(serviceTypeID);
        
        //get serviceType
        theServiceType.isActive = evt.target.checked;
        var active = evt.target.checked;        
        var theMarker;
        
        var siteData = this.activeNode.siteData;
        
        for (var i=0; i<siteData.length; i++) {
            theMarker = siteData[i];
            
            if (theMarker.st == serviceTypeID){
                if (active) {
                    theMarker.show();
                } else {
                    theMarker.hide();
                }             
            }

        }      
    },

    CreateMarker: function(point, icon, id, st) {
        


	//alert(id + "__" + st)


 	   //var marker = createMarker(new GLatLng(y,x), icons[markerData.acc])



        var marker = new GMarker(point, icon);
        //attibute the marker with it's layerName, markertype and lable
        //marker.markerType = markerType;
        marker.uid = id;
        marker.st = st;
        marker.widget = this;
        //marker.markerLable = markerLable;
        //marker.zoomLevel = zoomLevel;

        //add the info window listener.
        GEvent.addListener(marker, "click", function() {
           this.widget.getMarkerInfo(this.uid, this.st);
        });
        return marker;

    },
    
    getMarkerInfo: function(uid, serviceTypeID) {
        
        var url="ajax/getMarkerInfo.php";
        
        new Ajax.Request(url, {
            method: 'get',
            parameters: {'uid':uid, 'st':serviceTypeID},
            onSuccess: this.openMarkerWindow.bindAsEventListener(this)
        });
        //alert("here")
    }, 

     openMarkerWindow: function(responseObj) {  
         
        var response = responseObj.responseText.evalJSON();
        var markup = response.markup;
        var uid = response.uid;
        var st = response.st;
	
	if (markup.Services == null) markup.Services = "";
	if (markup.Phone == null) markup.Phone = "";
	if (markup.Directions == null) markup.Directions = "";

            var infoTabs = [];
            infoTabs.push(new GInfoWindowTab("Site",markup.Address + markup.Phone));
	if ((markup.Phone !="") || (markup.Directions != "")) {
            infoTabs.push(new GInfoWindowTab("Info", markup.Services + markup.Directions));  
	}          
   
       var siteData = this.activeNode.siteData;
       for (var i=0; i<siteData.length; i++) {
          if (siteData[i].uid == uid) {
            var theMarker = siteData[i];    

			//alert(theMarker.getLatLng().lat())
			//alert(theMarker.getLatLng().lng())


            //theMarker.openInfoWindowTabsHtml(infoTabs); //,{suppressMapPan:true});


 	    //theMarker.openInfoWindow("hello");


			//infowindowopen() 

			//map.getInfoWindow().getContentContainers()[0].style.height
			//map.getInfoWindow().getContentContainers()[0].style.width 


		theLat = theMarker.getLatLng().lat(); //this.map.getCenter().lat() + 3
		theLong = theMarker.getLatLng().lng();  //this.map.getCenter().lng()
		testPoint = new GLatLng(theLat , theLong)

		//this.map.openInfoWindow(this.map.getCenter(),document.createTextNode("Hello, world"));
		//this.map.openInfoWindow(testPoint,document.createTextNode("Hello, world!!!!!"));


		this.map.openInfoWindowTabsHtml(testPoint,infoTabs)


            this.activeMarker = theMarker;
            return;
        }
       }

     },
     
     getAddresses: function() {
        if (this.geocodeInput.value == "") return;
        var opt = this.countrySelect.options[this.countrySelect.selectedIndex];
        var fromAddress = this.geocodeInput.value + "," + opt.text;
        this.geocoder.getLocations(fromAddress, function(response){SITESELECTOR.displayGeocodeResponse(response)})
    },


    displayGeocodeResponse: function(response)  {

       //get associated text input
       var addressTd = $('redGeocodeAddress');
       addressTd.innerHTML= '';

        //if no places returned, exit.
        if (!response.Placemark) {
            addressTd.innerHTML= 'Address not found.';
            return;
        }

       //get table body
       var tbody = this.geocodeTbody;

       var responseDiv = $('redGeocodeResponse');
       responseDiv.style.display = 'block';
       responseDiv.style.zIndex = 6;
       
       
       //remove any rows currently in table
        row_count = tbody.rows.length
       //delete rows in table
        var j = 0;
        for (j=(row_count-1); j>-1; j--)
        {
        tbody.deleteRow(j);
        }



        //if length is 1 then do not bother with little popup div.
        if (response.Placemark.length == 1) {
          addressTd.innerHTML = response.Placemark[0].address;
          var thePt = new GLatLng(response.Placemark[0].Point.coordinates[1], response.Placemark[0].Point.coordinates[0]);
          SITESELECTOR.getAreaOnGeocode(thePt);
          return;
        }

        var i = 0;
        for (i=0; i<response.Placemark.length; i++) {
          //create table of data retrived.
          tr = tbody.insertRow(tbody.rows.length);
          td = tr.insertCell(tr.cells.length);
          td.className = "redGeocodeResponse";
          td.innerHTML = response.Placemark[i].address;

          tr.lat = response.Placemark[i].Point.coordinates[1];
          tr.lng = response.Placemark[i].Point.coordinates[0];
          //alert(tr.lat + "  " + tr.lng)

          if (tr.addEventListener) {
              tr.addEventListener("click", function(){
                                           addressTd.innerHTML = this.cells[0].innerHTML;
                                           var pt = new GLatLng(this.lat, this.lng);
                                           SITESELECTOR.getAreaOnGeocode(pt);
                                           }
                                           , false);
              tr.addEventListener("mouseover", function() {this.cells[0].style.backgroundColor='#ff0000';}, false);
              tr.addEventListener("mouseout", function() {this.cells[0].style.backgroundColor='transparent';}, false);

            } else {
              tr.attachEvent("onclick", function(evt){
                                        var srcElem = evt["srcElement"];
                                        addressTd.innerHTML = srcElem.innerHTML;
                                        var pt = new GLatLng(srcElem.parentNode.lat, srcElem.parentNode.lng);
                                        SITESELECTOR.getAreaOnGeocode(pt);
                                        }
                                        );
              tr.attachEvent("onmouseover", function(evt){evt["srcElement"].parentNode.style.backgroundColor='#ff0000';})
              tr.attachEvent("onmouseout", function(evt){evt["srcElement"].parentNode.style.backgroundColor='transparent';})
            }
        }
    },
    
    getAreaOnGeocode: function(pt){
        
        this.map.setCenter(pt, 10);
        
        $('redGeocodeResponse').style.display = 'none';
        
        var url = "ajax/getAreaByPoint.php?&x="+pt.x+"&y="+pt.y;
        new Ajax.Request(url, {
        method: 'get',
        onSuccess: this.displayAreaOnGeocode.bindAsEventListener(this)
        });
    },
    
    displayAreaOnGeocode: function(transport) {
	//alert(transport.responseText)
        var response = transport.responseText.evalJSON();
        var regionID = response.regionID;
        var countryID = response.countryID;


	if(response.areaType == "region"){
		var countryID = "GB";
		var regionID = response.areaID;
	}else{
		var countryID = response.areaID;
	}

        var dataNode;
        var callback = true;
        
        //two possibilities. Country has regions or not.
        //country has no regions
        if (countryID && !regionID){
            dataNode = this.findDataNode(this.treeData, 'areaID', countryID);
        } else if (countryID && regionID){ //country has regions
            //try and find the region.
            dataNode = this.findDataNode(this.treeData, 'areaID', regionID);
            //region may not be loaded. need to load it.
            if (!dataNode) {
                dataNode = this.findDataNode(this.treeData, 'areaID', countryID);
            }
        } else {
            return;
        }
        this.displayNodeData(dataNode, regionID, true, true);
    }
    

});

