//
// File : rtwgmap-filtering.js
//
// Description : Core Javascript functions for advanced Filtering on an RTWGMap implementation. 
//
// Contents    : 
//               
//                                       
//
//

var filters = [];
var filterMsgConnector = " and ";
var filterMsgSuffix = "";

var selectedFilters = [];
  
      
    //
	// get all the filters for the map
	//    
    function getFilters(){
    	eval(getDataProviderClassName()).getFilters(returnFilters);
	}
		
 	//
    // Callback for getFilters()
    //
    var returnFilters = function(data){
        if(data != null)   {
	        selectBoxes = [];
	        filterMsgConnector = " and ";
	        filterMsgSuffix = "";
	        
        	var container = document.getElementById("advFilterContainer");
        
        	var filterBySelectBox = document.createElement("select");
        	filterBySelectBox.id = "filterBy";
        	filterBySelectBox.onchange=filterChanged;
        	container.appendChild( filterBySelectBox );
        	if(data.length == 1) {
        		// no need to show this select box
        		filterBySelectBox.className = 'hidden';	
        	} else {        	
				// add a divider under the "filterby" select box
				container.appendChild( document.createElement("br") );        		
        	}
        			
            for(var i = 0; i < data.length; i++)   {                        
                filters[i] = data[i]; 
                                
                // create the filter by <blat> option
				filterBySelectBox.appendChild( createSelectOption(filters[i]) );
				
				// create the a select box for each child of 'Filter'
				if(filters[i].children) {
					filters[i].selectBoxes = new Array();
					
					for(var c=0;c<filters[i].children.length; c++) {
						var filter = filters[i].children[c];
						var filterId = filter.id;
						if(!filterId) {
						  filterId = c;
						  filters[i].id = filterId;
						}
						  
						//create a select box for this filter
						var selectBox = createSelectBox(filter);
			        	selectBox.onchange=filterChanged;
			        	selectBox.setAttribute("style","width: 175px");
						if(selectBox.width) 
						   selectBox.width = 125;
						   			        			        	
			        	//create the container/panel for the select box with it's label
			       		var selContainer = document.createElement("div");
						//filters[i].selectBoxes[c] = selContainer;	
						filters[i].selectBoxes[c] = selectBox;						
			       		container.appendChild(selContainer); 
			       		selContainer.className = 'hidden';			        	
        				
        				//add filter/selectbox label
        				//selContainer.appendChild( document.createTextNode(filter.label + ':' ) );
        				selContainer.appendChild( selectBox );
        			}
				}
			}    
			setDefaultFilter();
        }
    }

    var isFiltering = function () {
      return selectedFilters.length > 0;
    }
    
	//
	// returns true if the markerObj passes ALL the selected filters (AND logic)
	//
	function matchesAllSelectedFilters(markerObj) {
		var match = true;
		
		for(var i=0; i< selectedFilters.length; i++) {
		  var filter = selectedFilters[i];
		  
		  if(!filter.propertyMap)
		     continue;
		     
		  var filterPropertyName = filter.propertyMap.key;
          var filterPropertyValue = filter.propertyMap.value;
     
          if(!markerObj.additionalInfo)
              return false;
              
          var value = eval ("markerObj." + filterPropertyName);
           
          if( value == null || value != filterPropertyValue) 
              return false; //has to match all filters!?
		}
      
        	  
		return match;
	}
	
	
	   //
    // Returns a natural language message (string) that
    // represents the selected filters with a count of the
    // number of listings that matched
    //    
    function getFilterMsg(filteredMarkers, noun) {
        if(selectedFilters.length == 0)
           return "";
           
        // get the visible markers' bounds
        var bounds = getVisibleMarkersBounds();
        var panZoomUrl = null;
        if( bounds && !map.getBounds().containsBounds( bounds ) ) {
        	 // let the user pan/zoom to the visible markers 
        	 // if they aren't (all) visible
	         panZoomUrl = "<a alt='Zoom to visible " + noun + "s' href='javascript:panZoomToVisibleMarkers();'>";
	    }
	    
  		var indicative  = "";
        var verbIndex;
        if( filteredMarkers.length == 0)  {
        	indicative  += "are no " + noun + " ";
        	verbIndex = 1;
        } else {
        	if( filteredMarkers.length == 1) {
        		indicative  += " is only ";
        		if(panZoomUrl) 
        		  indicative += panZoomUrl;
        		
        		if(noun.match(/s$/))  {
          			// strip off the "s"    		
	        		indicative += "one " + noun.substring(0, noun.length-1) ; 
        		} else 
	        		indicative += "one " + noun ; 
	        	verbIndex = 0;
    	    } else if( filteredMarkers.length > 1) {
        		indicative  += " are ";
        		if(panZoomUrl)
        		  indicative += panZoomUrl;
        		indicative += filteredMarkers.length +" " + noun;
        		verbIndex = 1;
	        }
	        if(panZoomUrl)
	          indicative += "</a>";
	        indicative += " ";
	    }
        	
       	// get a list of the components of the natural language string
        var nlComponents = new Array();   
        var verbs = new Array();     
        for(var i = 0; i< selectedFilters.length; i++) {        
           var currentVerb = selectedFilters[i].nlVerbs[verbIndex];
           var label = selectedFilters[i].label;
           if(selectedFilters[i].propertyMap != null) {
		   	   verbs[currentVerb] = label;   
			   nlComponents[nlComponents.length] = { verb:currentVerb, type:label };   	              		   
		   }
        }
        
		// get the number of verbs
		var numOfVerbs = 0;
		for (var k in verbs) {
			numOfVerbs++;
		}
                   
        var msg = new Array();
        
        msg.push("<span>There " + indicative);
        msg.push("that ");
        var currentVerb = nlComponents[0].verb;
		msg.push( currentVerb + " ");      

        for(var i = 0; i< nlComponents.length; i++) {        
	        if( nlComponents[i].verb != currentVerb){
	          // verbage changed
	          currentVerb = nlComponents[i].verb;
			  msg.pop(); // get rid of the comma
			  
	          if(numOfVerbs <= 2 || i>0 && i+1 >= nlComponents.length)
		          msg.push(filterMsgConnector); //" and ");
		      else 
		          msg.push(", ");
		      msg.push(currentVerb + " ");
		      
	        } else if(i>0 && i+1 >= nlComponents.length) {
	        	//only one more nlcomponent left
          	    msg.pop(); 
        	   	msg.push(filterMsgConnector);//" and ");	        	      
        	}
	        
			msg.push( nlComponents[i].type );	              	  	            

    	    msg.push(", ");  
	    }
        
        msg.pop(); // get rid of the comma
	    msg.push("</span>");
	    
	    var str = "";
	    for(var i=0;i<msg.length; i++) 
	    	str += msg[i];
	    	
	    if(filterMsgSuffix && filterMsgSuffix.length > 0)
	      str += filterMsgSuffix;
	      
	    return str;    
    
    }
	
  
  
     //
    // shows only the Markers that match a filter
    //
    // Uses the function 'matchesAllSelectedFilters(markerObj) to determine
    // if the marker should be visible.
    //
    // Implementors should override matchesAllSelectedFilters or carefully
    // maintain the list of selected filters in the selectedFilters[] array
    //
    function applySelectedFilters(){
        var filteredMarkers = [];
        var gmarker = 0;
        
        if(directions != null)
           directions.clear();        
        
        //hide all the markers
		for(m in gmarkers)  {
       		gmarkers[m].hide();
		}	
			
        var j=0;
		// 
		// show or hide each marker as required
		//
        for(var m = 0; m < markerObjs.length; m++)
        {
            //
            // Filter by selected nodes
            //
            if( matchesAllSelectedFilters(markerObjs[m]) ) {
             
               // (re)set the marker's color to the current filter if specified
               //if(selectedFilters[0].color) {
               //	  setGMarkerColor(markerObjs[m], selectedFilters[0].color);
               //}
               
               var info = markerObjs[m].infoHtml;
               info +=  "<p/>";        
               info += "<span class=\"smallTextCenter\"><a href=\"javascript:zoomIn('" + markerObjs[m].id + "');\">Zoom In</a>" + "</span>&nbsp;&nbsp;";

               show( markerObjs[m] );
               
				// add it to the resultset for display on the sidelisting
               filteredMarkers[j++] = markerObjs[m];
            } 
        }
		
	    var filter = {label:getSideListingsLabel()};
        globalRegion = filter;
		// display on the sidelisting
        returnFilteredMarkers(filteredMarkers);
       
        //
        //update the msg string
        //      
        var noun = markerInfo.markerTypeLabel;
        updateFilterResultMsg(filteredMarkers, noun);
    }

	//
	// overrideable function for updating the filtered results msg(s)
	//    
    function updateFilterResultMsg(filteredMarkers, noun) {
        if( !loading ) {
           document.getElementById("filters").innerHTML = getFilterMsg(filteredMarkers, noun);           
        }
    }
    
    function createSelectBox(filter) {
     	var selectBox = document.createElement("select");
        selectBox.id = "select" + filter.id;            
				
        if(filter.children) {
        	for(var cc=0;cc<filter.children.length; cc++) {					
				selectBox.appendChild( createSelectOption(filter.children[cc]) );
			}
        }
        
        return selectBox;
    }
    
    function createSelectOption(filter) {
    	var _option=document.createElement("OPTION");
		_option.value=filter;
		_option.innerHTML=filter.label;
		
		return _option;
    }
 
 
 	function filterByChanged() { 				
		var filterBy = filters[document.getElementById("filterBy").selectedIndex];
		if(filterBy.label.indexOf("Equipment" == -1))
			filterMsgSuffix = " Equipment";
		
		filterChanged();
	}

	var filterChanged = function() {	
		map.closeInfoWindow();
			
		//hide all the select boxes
		for(var i=0; i< filters.length; i++) {
			filter = filters[i];
			for(s=0;s<filters[i].selectBoxes.length; s++) {
				filters[i].selectBoxes[s].parentNode.className = 'hidden';
				filters[i].selectBoxes[s].className = 'hidden';
			}
		}
	
		if( isFiltering() ) {
			// only show the select boxes for the current filterby selection
			var index = document.getElementById("filterBy").selectedIndex;
			var filterBy = filters[index];
			for(s=0;s<filterBy.selectBoxes.length; s++) {
				filterBy.selectBoxes[s].parentNode.className = 'visible';
				filterBy.selectBoxes[s].className = 'visible';
			}
				
    	 	selectedFilters = [];
     
			if(	filterBy.children ) {	
     			for(var c=0;c<filterBy.children.length; c++) {
     				//set the selected filters
     				var filter = filterBy.children[c];
	     			var selectBox = filterBy.selectBoxes[c];
    	 			selectBox.className = 'visible';
     				index = selectBox.selectedIndex; //selectBox.value doesn't work !?
					var filter = filter.children[index];
					selectedFilters[selectedFilters.length] = filter;
				}				
    	 	}
     	}
     	
     	if( isFiltering() )  {     	
 	    	applySelectedFilters();
 	    } else {
 	    	document.getElementById("filters").innerHTML = "";
 	    	manageMarkers(null, null);
 	    }
 	    
 	    //
        // Zoom out on the map until at least one marker
        // is visiable
        //     
        panZoomToAtLeastOneVisibleMarker();
	}
    
    //
    // pause for x milliseconds
    //
    function pausefor(millis) {
		var date = new Date();
		var curDate = null;

		do { curDate = new Date(); }
		while(curDate-date < millis);
	} 

  
    function setDefaultFilter() {    
    	if(!isFiltering() || gmarkers.length == 0)
    		return;
    
         //
         // wait for the filters to be loaded - this
         // can be tough to sync with different load times
         // for the markers, filters, etc (diff on each browser)
         //
         var filterBy = document.getElementById("filterBy");           
         if(!filterBy) {            
    	        return;
         }
         
			// only show the select boxes for the current filterby selection
			var index = filterBy.selectedIndex;
			var filterBy = filters[index];
			for(s=0;s<filterBy.selectBoxes.length; s++) {
				filterBy.selectBoxes[s].parentNode.className = 'visible';
				filterBy.selectBoxes[s].className = 'visible';
			}
				
    	 	selectedFilters = [];
     
			if(	filterBy.children ) {	
     			for(var c=0;c<filterBy.children.length; c++) {
     				//set the selected filters
     				var filter = filterBy.children[c];
	     			var selectBox = filterBy.selectBoxes[c];
    	 			selectBox.className = 'visible';
     				index = selectBox.selectedIndex; //selectBox.value doesn't work !?
					var filter = filter.children[index];
					selectedFilters[selectedFilters.length] = filter;
				}				
    	 	}
     	
	    	applySelectedFilters();
    }
    