//
// File : rtwgmap-core.js
//
// Description : Core Javascript functions for an RTWGMap implementation. 
//
// Contents    : 
//               getFilters - 
//                                       
//
//


    var gmarkers = [];
    var markerObjs= [];
    var bounds = [];
    var markerMgr;
    //var listings = [];
    var regions= [];
    var map = null;
    var globalRegion = new Object();
    var directionsPanel;
    var directions;
    var showDirections = true;
    var startAddress = getCookie("startAddress");
    var startCity = getCookie("startCity");
    var PROV = "AB";
    var zoomToId = "";
    var markerInfo = {markerTypeLabel:""};
    var printableMarkers = [];
    var loading = 0;
   
     
    
    //
    // initialize the map and other required objects
    //
	function initMap() {
	    //DWRUtil.useLoadingMessage();
	    loading = 1;
		getMarkerInfo();
		
    	getMarkers();
		createMap();
		getRegions();
		getFilters();
		
		var mapDiv = document.getElementById("map");
		recenterMap();
		addOverlays();
		loading = 0;
	};
	
	function addOverlays() { 
	
    }
    
    
	//
	// get the marker info (or metadata)
	//
	function getMarkerInfo() {
    	eval(getDataProviderClassName()).getMarkerInfo(returnMarkerInfo);
	}
	
	//
	// get all the gmarkers for the map
	//
	function getMarkers() {
    	eval(getDataProviderClassName()).getMarkers(returnMarkers);
	}
	
	//
	// get all the regions for the map
	//
   	function getRegions(){
    	eval(getDataProviderClassName()).getRegions(returnRegions);
	}


	//
	// get all the gmarkers for the specified region
	//
	function getMarkersForRegion(regionId){
    	currentRegionId = regionId;
	    map.closeInfoWindow();    
    	closeDirections();
    	
	    for(var i = 0; i < regions.length; i++)
    	{
        	if(regions[i].id == regionId) {
	            globalRegion = regions[i];

    	        map.setCenter(new GLatLng(regions[i].latitude, regions[i].longitude), regions[i].zoomLevel);
        	    break;
	        }
    	}
	}

    
    //
    // set a cookie
    //
    function setCookie(name,value) {
        var today = new Date();
        var cookie_expire_date = new Date(today.getTime() + (30 * 7 * 86400000)); 
    
        var cookieString = name + "=" +escape(value) +";expires=" + cookie_expire_date.toGMTString() ;
        document.cookie = cookieString;
    } 
        
    //
    // get a cookie
    //
    function getCookie(name) {
       var start = document.cookie.indexOf(name+"=");
       var len = start+name.length+1;
       if ((!start) && (name != document.cookie.substring(0,name.length))) return null;
       if (start == -1) return null;
       var end = document.cookie.indexOf(";",len);
       if (end == -1) end = document.cookie.length;
       var value = unescape(document.cookie.substring(len,end));
       if(value == null || value == "null") value = "";
       return value;
    }
    
    //
    // Delete a cookie
    //
    function Delete_Cookie(name,path,domain) {
       if (Get_Cookie(name)) document.cookie = name + "=" +
          ( (path) ? ";path=" + path : "") +
          ( (domain) ? ";domain=" + domain : "") +
          ";expires=Thu, 01-Jan-70 00:00:01 GMT";
    } 

    //
    // Unapply any filters being applied
    function unapplyFilter() {
       if(isFiltering()) {
          //map.clearOverlays();
          clearInnerHTML(document.getElementById("sideListing"));
          showAllMarkers();
          recenterMap();
          selectedFilters = [];
        }
    }
    
    //
    // Show (unhide) all the known markers
    //
    function showAllMarkers() {
    	for(var m = 0; m < markerObjs.length; m++)  {
    	   gmarkers[markerObjs[m].id].show();
    	}
    	initSideListing();
    }
    
    //
    // shows only the Markers that match a filter
    //
    function applyFilter(filterName){    
//TESTING
//alert('applyFilter called');
//TESTING
        var filteredMarkers = [];
        var gmarker = 0;
        
        //map.clearOverlays();  // don't clear, just hide the markers
        if(directions != null)
           directions.clear();
        
        var j=0;
        var filter =null;
        
        // get a reference to the filter
        for(var i=0; i< filters.length; i++) {
          if(filters[i].label == filterName) {
            filter = filters[i];
            //alert("Filter : "+ filter);
            break;
          }
        }
        
        if(filter == null)
          alert('no filter found for ' + filterName);
        
        // special case - if the filter doesn't have a property map, show all
        if(!filter.propertyMap) {
          unapplyFilter();
          initSideListing();
          return;
        }
        
        var filterPropertyName = filter.propertyMap.key;
        var filterPropertyValue = filter.propertyMap.value;
     
        for(var m = 0; m < markerObjs.length; m++)
        {
            if(!markerObjs[m].additionalInfo)
              continue;
              
	        var value = eval ("markerObjs[m]." + filterPropertyName);
           
            if( value == filterPropertyValue) {
               // include this gmarker in the resultset
               var info = markerObjs[m].infoHtml;
               info +=  "<p/>";        
               info += "<span class=\"smallTextCenter\"><a href=\"javascript:zoomIn('" + markerObjs[m].id + "');\">Zoom In</a>" + "</span>&nbsp;&nbsp;";

               //gmarker = createGMarker(markerObjs[m]);
               //gmarkers[markerObjs[m].id] = gmarker;
               gmarkers[markerObjs[m].id].show();
               
               //map.addOverlay(gmarker); 
               filteredMarkers[j++] = markerObjs[m];
            } else {
               if(gmarkers[markerObjs[m].id])
               		gmarkers[markerObjs[m].id].hide();
            }
        }
        globalRegion = filter;
//        returnFilteredMarkers(filteredMarkers);

        recenterMap();
    }

 
    //
    // Recenter the map
    //
    function recenterMap() {
      map.setCenter(new GLatLng(54.6, -113.0), 5);
    }
    
    //
    // Get all the gmarkers
    //    
    function getAllMarkers(){
    
        var gmarker = 0;
        map.clearOverlays(); 
        for(var i = 0; i < markerObjs.length; i++)
        {
            gmarker = createGMarker(markerObjs[i]);
            map.addOverlay(gmarker);
        }
        //recenterMap();
    }
    
    //
    // callback for getMarkerInfo()
    //
    var returnMarkerInfo = function(data){
        if(data != null) {
            markerInfo = data;
        }
    }
    
  
  
    //
    // callback for getMarkers()
    //
    var returnMarkers = function(data){
        if(data != null)  {
            var gmarker = 0;
            var count = 0;
            for(var i = 0; i < data.length; i++)  {                
            	if(data[i].latitude != null) {   
            		var markerObj = data[i];            		
                	markerObjs[count] = markerObj;
                 
                    gmarker = createGMarker(markerObj);
                    gmarkers[markerObj.id] = gmarker;

					markerObj.isAddedToMap = false;
                    count++;
                }
            }
             
        }
            
        if(zoomToId != null && zoomToId != "")
               zoomIn(zoomToId);
        zoomToId = null;
            
        loading = 0;				
		setDefaultFilter();
				
        manageMarkers(null, null);
    }

    //
    // Provided for implementors to utilize 
    // - called from returnMarkers at the point where the
    // available markers have been added to the map (and should
    // be filtered by the default filter as needed on startup)
    //
    function setDefaultFilter()  {
    
    }
    
    
    //
    // callback for getRegions()
    //
    var returnRegions = function(data){
        if(data != null)
        {
            var htmlList = '<span class="smallText" ><b>Choose Region:</b></span>';
            for (var i in data) 
            {
                regions[i] = data[i];
                htmlList = htmlList + renderRegion( regions[i] );
var sw = new GLatLng(regions[i].envelope.x + regions[i].envelope.height, regions[i].envelope.y);
var ne = new GLatLng(regions[i].envelope.x , regions[i].envelope.y + regions[i].envelope.width);

//console.debug("region : " + regions[i].name + " x=" + regions[i].envelope.x + " y=" +regions[i].envelope.y + " w="+regions[i].envelope.width + " h=" +regions[i].envelope.height);                
//console.debug("  sw="+sw);
//console.debug("  ne="+ne);

bounds[regions[i].id] = new GLatLngBounds(sw, ne);

            }
            
            htmlList = htmlList + '<br/>';
            document.getElementById("regions").innerHTML = htmlList;
            
            initSideListing();
        }
    }
        
    //
    // 
    // Loads the rendered markers that match the filter
    // into the "sideListing' element
    //
    // See also 
    //   renderMarkerForSideListing(marker)
    //   applySelectedFilter()
    //
    var returnFilteredMarkers = function(data){    	          		        
        var htmlList = '<div class="smallTextCenter">';   
         
		var label = getSideListingsLabel();        
        if(document.getElementById('sideListingHeader')) {	        
    	    document.getElementById('sideListingHeader').innerHTML = label;
        }

        htmlList += getPrintUrl(label) ;
       
 		printableMarkers = data;
        if(data != null)
        {
            htmlList = htmlList + '<br/>';
            for(var i = 0; i < data.length; i++)
            {
                htmlList = htmlList + renderMarkerForSideListing ( data[i] );                
            }
            
            htmlList = htmlList + '</div>';
            
            document.getElementById("sideListing").innerHTML = htmlList;
        }
    }
    

    //
    // Clear the html for an obj/div/other
    // 
    function clearInnerHTML(obj) {
        // remove child objects
        while(obj.firstChild) obj.removeChild(obj.firstChild);
    }
    
    //
    // Get the url to print the current markers/listings
    //
    function getPrintUrl(label) {
      //print link
        var printIcon = "/app21/rtw/icons/maps/printer2.gif";
        return "<center><a href='javascript:printCurrentListings(\"" + label + "\");'><img src='" + printIcon + "' border='0'/></a></center>";
    }
    
    
     
    //
    // print the current listings
    // see printableMarkers, returnFilteredMarkers
    //
    function printCurrentListings(title) {
	    top.consoleRef=window.open('','myconsole',
									  'width=600,height=400'
									 +',menubar=0'
									 +',toolbar=1'
									 +',status=0'
								     +',scrollbars=1'
									 +',resizable=1');
   
	   	var content = "<h1>" + title + "</h1>";
	   	for(var i=0;i<printableMarkers.length; i++) {
    		content += "<br/>" + printableMarkers[i].infoHtml;
    		//content += printableMarkers[i].equipHtml;
		}
   
		top.consoleRef.document.writeln('<html><head><title>' + title + '</title></head>'
									+'<body style="font-size: 0.86em;" bgcolor=white onLoad="self.focus(); window.print();">'
								    +content
								    +'</body></html>');
   
	 	top.consoleRef.document.close();    
    }
 
     
    
    //
    // Initialization for the Map
    //
    function createMap(){
        if (GBrowserIsCompatible()) {
			var mapDiv = document.getElementById("map");
	
            map = new GMap2(mapDiv);

	        GEvent.addListener(map, "zoomend",function(oldLevel, newLevel){ manageMarkers(oldLevel, newLevel); });
    	    GEvent.addListener(map, "moveend",function(){ manageMarkers(null, null); });
        	GEvent.addListener(map, "dragend",function(){ globalRegion = null; }); // user moved the map, there is no region now

			map.enableContinuousZoom();

            //Initialize directions
            //directionsPanel = document.getElementById("sideListing");//directions_div");
            directions = new GDirections(map);//, directionsPanel);
            directions.isVisible = false;
            GEvent.addListener(directions, "error", handleErrors);

      		GEvent.addListener(directions,"load", function() {
        		setTimeout('renderDirections(map,"map",directions,document.getElementById("sideListing"))', 1);
      		});
      
            var mt = map.getMapTypes();
            //Overwrite min and max resolution parameters
            for(var i = 0; i < mt.length; i++)
            {
                mt[i].getMinimumResolution = function () {return 5;}
                mt[i].getMaximumResolution = function () {return 17;}
            }

            map.addControl(new GLargeMapControl());
            
            recenterMap;

//               map.getPane(G_MAP_FLOAT_SHADOW_PANE).style.visibility="hidden"; 

            GEvent.addListener(map, "move",function(){checkBounds();});                    
       
            var allowedBounds = new GLatLngBounds(new GLatLng(48.5,-120.0), new GLatLng(60.9,-109.0));
            
            function checkBounds(){
                  if(allowedBounds.contains(map.getCenter())){
                return;
                  }
              var c = map.getCenter();
              var xcoord = c.lng();
              var ycoord = c.lat();

              var aMaxX = allowedBounds.getNorthEast().lng();
              var aMaxY = allowedBounds.getNorthEast().lat();
              var aMinX = allowedBounds.getSouthWest().lng();
              var aMinY = allowedBounds.getSouthWest().lat();

              if(xcoord < aMinX){xcoord = aMinX;}
              if(xcoord > aMaxX){xcoord = aMaxX;}
              if(ycoord < aMinY){ycoord = aMinY;}
              if(ycoord > aMaxY){ycoord = aMaxY;}
              map.setCenter(new GLatLng(ycoord,xcoord));

            }
        }    
    }

    //
    // show the markerObj's info window/balloon
    //
    function myclick(id){
        GEvent.trigger(gmarkers[id],"click");
    }


    //
    // Zoom in to a gmarker
    //
    function zoomIn(id) {      
    	gmarkers[id].show();
        map.setCenter(new GLatLng(gmarkers[id].getPoint().lat(), gmarkers[id].getPoint().lng()), 14);
        GEvent.trigger(gmarkers[id],"click");
    }
    
    function closeDirections() {
    	if(directions != null && directions.isVisible == true) { 
    		directions.isVisible = false;
    		directions.clear();
    		manageMarkers(null, null);
    	}
    }
    
    //
    // Get the directions to a marker using the start address provided
    // Utilizes DOM to get values from the ui form elements : 'startAddressTxt' & 'startCityTxt'
    //
    // Called when the user presses the "Get Directions" Button on the gmarker's Direction tab
    //
    function getDirections(id)  {
        directions.isVisible = true;
        map.getInfoWindow().hide();
		
        var currentmarker = gmarkers[id];
        var currentListing = getMarkerObj(id);

        //alert("get directions to " +currentmarker.getPoint().lat() + " " + currentmarker.getPoint().lng() );
        var lat = currentmarker.getPoint().lat();
        var lng = currentmarker.getPoint().lng();
        var endlatlng = lat + "," + lng;

        //get the start address & town entered
        startAddress = document.getElementById("startAddressTxt").value;
        startCity = document.getElementById("startCityTxt").value;

        // save start address in cookies for the next session
        setCookie("startAddress",startAddress);
        setCookie("startCity",startCity);

        //build the url to the printer friendly page
        var prstart = encodeURIComponent(startAddress) + "," + encodeURIComponent(startCity)+"," + PROV;
        var prend = encodeURIComponent(currentListing.address)+","+ encodeURIComponent(currentListing.town)+"," + PROV+"&sll=" + endlatlng;   
        var printurl = "http://maps.google.com/maps?f=d&hl=en&geocode=&saddr=" + prstart + "&daddr=" + prend + "&sspn=4.301366,10.283203&ie=UTF8&z=13&om=1&pw=2";    

        var start = startAddress + " " + startCity + " " + PROV;
        var end = currentListing.address + "@" + endlatlng;

        //clear the previous directions and set the header for the sideListings 
        //space before GDirections will output/append to it
        directions.clear();
        clearInnerHTML(document.getElementById("sideListing"));
        var htmlList = '<div class="textBoldGrey">Directions to ' + currentListing.name + '</div><div class="smallTextCenter"><br/>';            
	
		//close directions link
		htmlList = htmlList + '<div style="align: right"><a href="javascript:closeDirections();">Close Directions</a></div><br/>';		

		//print link
        htmlList = htmlList + '<a target="_blank" href="' + printurl + '"><img border="0" src="/app68/listings/icons/maps/printer.gif"/></a><br/>';

        document.getElementById("sideListing").innerHTML = htmlList;


        //load the directions ! This will do the callback to rtwgmap-ui#renderDirections() that was setup earlier
        directions.load("from: " + start + " to: " + end , {getSteps:true});       
    }

    //
    // handle any/all errors returned from google
    //
    function handleErrors(){
       if (directions.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
         alert("No corresponding geographic location could be found for one of the specified addresses. This may be due to the fact that the address is relatively new, or it may be incorrect.\nError code: " + directions.getStatus().code);
       else if (directions.getStatus().code == G_GEO_SERVER_ERROR)
         alert("A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.\n Error code: " + directions.getStatus().code);
       
       else if (directions.getStatus().code == G_GEO_MISSING_QUERY)
         alert("The HTTP q parameter was either missing or had no value. For geocoder requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input.\n Error code: " + directions.getStatus().code);

       else if (directions.getStatus().code == G_GEO_BAD_KEY)
         alert("The given key is either invalid or does not match the domain for which it was given. \n Error code: " + directions.getStatus().code);

       else if (directions.getStatus().code == G_GEO_BAD_REQUEST)
         alert("A directions request could not be successfully parsed.\n Error code: " + directions.getStatus().code);
        
       else alert("An unknown error occurred.");
       
       //reload the current map's region
       if(globalRegion != null) {
         getMarkersForRegion(globalRegion.id);
       } else {
         getAllMarkers();
       }
    }

	// 
	// Show a marker
	//
    function show(markerObj) {
        var gmarker = gmarkers[markerObj.id];
         
    	if(!markerObj.isAddedToMap) 
			map.addOverlay(gmarker);
		markerObj.isAddedToMap = true;
        gmarker.show();
    }

	//
	// Hide a marker
	//
    function hide(markerObj) {
        var gmarker = gmarkers[markerObj.id];
        if(gmarker)
	        gmarker.hide();
    }
    
    //
    // Get a marker obj using it's unique id
    //
    function getMarkerObj(id) {
        for(var m = 0; m < markerObjs.length; m++)  {
	       if( markerObjs[m].id == id) 
	         return markerObjs[m];
		}	         
	    return null;
    }
    
    //
    // move end occurred (drag, pan, programatic zoom, etc
    // 
    function manageMarkers(oldLevel, newLevel) {    
       var gmarker = null;              
          
       if(isFiltering() && !directions.isVisible)    {             
       	  	applySelectedFilters();
       } else if( (newLevel == null || oldLevel == null ) || oldLevel != newLevel ) {
       		//no real region now - just use the marker type label
 	        globalRegion = new Object();
 	        globalRegion.label = markerInfo.markerTypeLabel;
 	        globalRegion.id = -1;
 	        
          	//show all the markers
			for(m in gmarkers)  {
    	   		gmarkers[m].show();
			}			
			
			if(newLevel == null) {
			  newLevel = map.getZoom();
			}
			
            //
       		// manage which markers are viewable
	        //            
	       for(var m = 0; m < markerObjs.length; m++)  {
	       	   var markerObj = markerObjs[m];
	           gmarker = gmarkers[markerObj.id];   
	           
	           //
	           // Show the marker if the marker is in the current viewport 
	           // and the map's zoom level is within it's viewable range, 
	           // 
	           if( map.getBounds().contains( gmarker.getPoint() ) ) {
	           	   if(markerObj.visibleRange[0] <= newLevel && 
	           	       markerObj.visibleRange[1] >= newLevel) {
	           	      show(markerObj);   
	           	   } else 
	           	      hide(markerObj);
	            } 
	       }       
	       
	       // update the side listing for the markers shown
	       //
	       // (the code in applySelectedFilters() will update the list
	       // with markers that match in alberta - not just in the current
	       // view)
	       if(directions==null || directions.isVisible == false)
		       updateSideListingForCurrentView(); 
       } 
    }  
  	
	//
	// Returns all the marker objs (not gmarkers) in the current view
	//
	function getMarkersInCurrentView() {
	 	var markersInView = [];
        var gmarker = 0;
        var j =0;  
        
        // 
        // build a resultset of all
        // the markers in the current view
        //
        for(var m = 0; m < markerObjs.length; m++)  {
            gmarker = gmarkers[markerObjs[m].id];           
            if( !gmarker.isHidden() && map.getBounds().contains( gmarker.getPoint() ) ) {
               markersInView[j++] = markerObjs[m];
            } 
        }
        
        return markersInView;
	}
	
	
	//
	// update the side listing for all the gmarkers for the current view
	//
	function updateSideListingForCurrentView(){    	
        // list all the markers in the current view in the side listings    
        var markers =     getMarkersInCurrentView();
        returnFilteredMarkers( markers );
        
        if(markers == null || markers.length == 0) 
            initSideListing();
	}
  
  
