/**
 *	Global Logic for Google Maps API, Boydgroup Website
 *  Copyright 2011, Adnet Communications, unless otherwise noted
 *	Author: James Clarke
 *	
 *	Rev 1.2
 *	
  *	Requires:
 *	Locations.js
 *	_"companyname"_Params.js 	<- target ids in here
 *	Utils.js
 *	Polys.js or PrecomputedPolys.js
 *	
 *	To initialize:	
 *		window.onload=function(){
 *					GMapLarge.init();
 *		}
 */



// GMapLarge() METHODS:
// .init <-- handles set up of google map, polygons, plots locations and calls setup of event handlers for html elements
// .moveMyLocationToPoint <-- repositions map and marker
// .getZoomLevel <-- returns zoom (superfluous)
// .setZoomLevel <-- set zoom to a value or default
// .showAllLocations <-- prints all locations below map 								
// .dim  <-- locks the map from use, hides/shows an html element
// .showAddress <-- geocodes address from find us box
// .findNearest <-- calculates distance and lists 5 nearest locations
// .printLocations <-- lists locations below map
// .getDirections <-- gets directions and writes directions to page
// .handleErrors <-- handles directions errs in case google can't find that address.
// .plotLocations <-- plots locations to the map and determines location types (Brand). if not Lat/Long set, this fails over to Geolocation (SLOW)



var map; 			// map - global
var myLocationMarker; //refernce to location marker
var mgr; 			// marker manager - global 
var directions;		// holder for Google Directions Object
var sortLoc; 		// object, used in Utils - sortLocation()
var address;		// hold user address
var myMarkers = [];	// container for markers






function GMapLarge(){
	return this;	
}


GMapLarge.prototype.init = function(){	

	if(document.getElementById(mapEl) != undefined){ //mapEl set in params
		
		UTILS.sortLocation(); //check for sorting
			
		map = new GMap2(document.getElementById(mapEl));

	    G_NORMAL_MAP.getMaximumResolution = function () { return 16 }; 
     
	 	map.setMapType(G_NORMAL_MAP);
		map.enableScrollWheelZoom();
		map.addControl(new GLargeMapControl3D());
		map.addControl (new GScaleControl());
		map.setCenter(myCenterPoint, GMapLarge.getZoomLevel());	
		
		//this block probably does nothing
		var lat = myPoint.lat();
		var lon = myPoint.lng();
		var latOffset = 0.01;
		var lonOffset = 0.01;
		// 'til here
	
	
		//POLYLINE STUFF
		
		//draws states to map
		Polys.init(map);
		


		//MARKER STUFF
		//add origin marker - (attempt geolocation?)
		myLocationMarker = new GMarker(myPoint, markerOptions);
		GEvent.addListener(myLocationMarker, "click", function() {
			this.openInfoWindowHtml('You Are Here<br>'+ myPoint);
		});

		GEvent.addListener(myLocationMarker, "dragend", function(){											 
			myPoint = myLocationMarker.getLatLng();
			myCenterPoint = myPoint;
		});
		map.addOverlay(myLocationMarker);	
 	   
	   
		directions = new GDirections(map,document.getElementById(routeEl));
	    GEvent.addListener(directions, "error", GMapLarge.handleErrors); 
		
		//plots locations, generates 'myMarkers' used below.
		GMapLarge.plotLocations(map,PARAMS); 
		
		mgr = new MarkerManager(map);
		mgr.addMarkers(myMarkers,6);
		mgr.refresh();


		//Interface Stuff (forms et al)
		PARAMS.setupLocalFunctions();
		
	}
}

GMapLarge.prototype.moveMyLocationToPoint = function(point){
		map.setCenter(point, GMapLarge.getZoomLevel());	
		myLocationMarker.setLatLng(point); 
}

//getter for global zoom variable
GMapLarge.prototype.getZoomLevel = function(){
		return zoom;
	}
	
//setter for global zoom variable
GMapLarge.prototype.setZoomLevel = function(num){
		if(num){
			zoom = num;
		}else{
			zoom = 8;
		}
	}

var sortedLocations = new Array();

//Break out of sorting to view all locations. 
GMapLarge.prototype.showUnsortedLocations = function(){
	
	//short circuits sorting to allow all locations to be shown without refresh.
	
	//remove sorting flag
	sortLoc.by = '';
	sortedLocations = locations;
	GMapLarge.showAllLocations();
	
	//clear map of overlays
	Polys.clearPolys();
	map.clearOverlays()
	
	///redraw overlays
	Polys.init(map);
	GMapLarge.plotLocations(map);
	
	//resent marker manager
	mgr = new MarkerManager(map);
	mgr.addMarkers(myMarkers,6);
	mgr.refresh();
}

// interface function for printing all locations.
GMapLarge.prototype.showAllLocations = function(p){
	
	if(sortedLocations.length < 1){
		for(i=0;i<locations.length;i++){
			if(sortLoc.by == 'province'){
				if( locations[i].State.toLowerCase() == sortLoc.val){
					sortedLocations.push(locations[i]);
					Polys.hideAllPolysExcept(sortLoc.val.toUpperCase());
				}else{
					continue;
				}
			}else if(sortLoc.by == 'city'){
				if( locations[i].City.toLowerCase() == sortLoc.val){
					sortedLocations.push(locations[i]);
					Polys.hideAllPolysExcept(sortLoc.val.toUpperCase());
					
					//set focus of city on sort by city. maybe a bit kludgy code
					map.setCenter(new GLatLng(sortedLocations[0].Lat,sortedLocations[0].Long));
					map.setZoom(6);
					
				}else{
					continue;	
				}
			}
		}				
	}
	if(sortedLocations.length < 1){
		sortedLocations = locations;
	}
	
	var myPage;		
	
	if(p){
		myPage = p
	}else{
		myPage = 0	
	}

	var numResults = 10;
	var myIndex = myPage*numResults
	var myLimit = myIndex+numResults;
		if(myLimit > sortedLocations.length)myLimit = sortedLocations.length;
		 
	var pages = Math.ceil(sortedLocations.length/numResults);
	
	var textOut = '<h2>'+UTILS.sortName()+'Locations:</h2>';
	
	var pageNav =  '<b>Page:</b> ';	
	
		for (i=0;i<pages;i++){
			if(i == myPage){
				pageNav += ' <a href="javascript:void(0)" onclick="GMapLarge.showAllLocations('+(i)+')" class="pagination"><b>'+ (i+1) +'</b></a>';
			}else{
				pageNav += ' <a href="javascript:void(0)" onclick="GMapLarge.showAllLocations('+(i)+')" class="pagination">'+ (i+1) +'</a>';
			}
		}	
	
		textOut += pageNav;	
		textOut += '<br>';
		for (i=myIndex; i < myLimit; i++){
			textOut += PARAMS.locationListing(sortedLocations[i]);
		}
		
		textOut += pageNav;	
		
		document.getElementById(locationsEl).innerHTML = textOut;

}

// dims page by toggling visibility of dimming element
GMapLarge.prototype.dim = function(opacity){
	if(document.getElementById(dimEl)){
		var dimmer = document.getElementById(dimEl); //Params - dimEl
		if(opacity){
			dimmer.style.display = 'block';
		}else{
			dimmer.style.display = 'none';
		}
	}
}

GMapLarge.prototype.showAddress = function() { //lookup of address for Find Us functionality
	
	// get element for route description
	var route = document.getElementById(routeEl);
		route.innerHTML = '';
	
	// dim the map while looking up address
	  GMapLarge.dim(1);	//blocking
	  
	  geocoder = new GClientGeocoder();
	  if (geocoder) {
		  geocoder.getLatLng(address,function(point){
			if (!point) {
			  alert("Could not find address: " + address);
			  GMapLarge.dim(0); // remove dimming
			} else {
			  myPoint = point;

			  // eliminate sorting;
			  sortLoc.by = '';
			  sortedLocations = locations;
		
			  //replot markers???
			  GMapLarge.plotLocations(map);
			  
			  //fix manager issue on replot???
			  	mgr = new MarkerManager(map);
				mgr.addMarkers(myMarkers,6);
				mgr.refresh();
			
			  GMapLarge.findNearest(point);
			  GMapLarge.moveMyLocationToPoint(point); // moves map and marker - no bounds calculations yet.
			  
			  UTILS.setLocation(point);//sets point as cookie
			}
			});
	  }
	  
}


	
	//timing function - used for testing
	var timeDiff  =  {
		setStartTime:function (){
			d = new Date();
			time  = d.getTime();
		},
	
		getDiff:function (){
			d = new Date();
			return (d.getTime()-time);
		}
	}
	

//calculate nearest location as the crow flies.
GMapLarge.prototype.findNearest = function(point){
		//loop through locations, calculate hypoteneus(^2), determine closest
		
		var py, px, lt, lng, nearest, hypSq;
		
			py = point.y;
			px = point.x;
			
		var shuffledLocations = locations.slice();	
		//loop and calculate hypoteneus(^2) for each. no Math.sqrt for speed
		for (i=0;i<shuffledLocations.length; i++){
			
			lt = py-shuffledLocations[i].Lat;
			lng = px-shuffledLocations[i].Long;
			hypSq = (lt*lt + lng*lng);
			shuffledLocations[i].hypSq = hypSq; 
									
		}
		
		//sort based on hypotenus
		shuffledLocations.sort(UTILS.sortMe);	
		
		var bounds = new GLatLngBounds; 
			bounds.extend(new GLatLng(py, px)); 
			bounds.extend(new GLatLng(shuffledLocations[0].Lat, shuffledLocations[0].Long)); 		
			bounds.extend(new GLatLng(shuffledLocations[0].Lat, shuffledLocations[0].Long)); 		
			map.setCenter(bounds.getCenter(),  GMapLarge.setZoomLevel( map.getBoundsZoomLevel(bounds)-1 )); 
			myCenterPoint = bounds.getCenter();
		
		//remove blocking
		GMapLarge.dim(0);		
		
		GMapLarge.printLocations(shuffledLocations);
		
	}
	
GMapLarge.prototype.printLocationsPage = function(p){
	this.printLocations(this.shuffledLocations,p);
}
GMapLarge.prototype.printLocations = function(shuffledLocations,p){
	
		this.shuffledLocations = shuffledLocations;
	
		for (var i=0, len=this.shuffledLocations.length; i<len; i++){
				
				//Sorting		
				if(sortLoc.by == 'province'){
					if(this.shuffledLocations[i].State.toUpperCase() == sortLoc.val){
					
					//turned off sorting	
					//	sortedLocations.push(this.shuffledLocations[i]);

					}else{
						continue;
					}
				}
		
		}
		
		//turned off sorting
		//if(sortedLocations.length>0){
		//	this.shuffledLocations = sortedLocations;
		//}
		/////////////////////////////////////////////////////////////
		
			var myPage;		
	
			if(p){
				myPage = p
			}else{
				myPage = 0	
			}
		
			var numResults = 10;
			var myIndex = myPage*numResults
			var myLimit = myIndex+numResults;
				if(myLimit > this.shuffledLocations.length)myLimit = this.shuffledLocations.length;
				 
			var pages = Math.ceil(this.shuffledLocations.length/numResults);
			
			var textOut = '<h2>Nearest Locations:</h2>';
			
			var pageNav =  '<b>Page:</b> ';	
			
				for (i=0;i<pages;i++){
					if(i == myPage){
						pageNav += ' <a href="javascript:void(0)" onclick="GMapLarge.printLocationsPage('+(i)+')" class="pagination"><b>'+ (i+1) +'</b></a>';
					}else{
						pageNav += ' <a href="javascript:void(0)" onclick="GMapLarge.printLocationsPage('+(i)+')" class="pagination">'+ (i+1) +'</a>';
					}
				}	
			
				textOut += pageNav;	
				textOut += '<br>';
				for (i=myIndex; i < myLimit; i++){
					textOut += PARAMS.locationListing(this.shuffledLocations[i]);
				}
		
		/////////////////////////////////////////////////////////////
		
		
		
		
		document.getElementById(locationsEl).innerHTML = textOut;	
			
	}

	//Get directions from current 'myPoint' to chosen endpoint
	// move to new class?
GMapLarge.prototype.getDirections = function(endPoint){

		// get route element and clean up any leftover HTML.
		var route = document.getElementById(routeEl);
			route.innerHTML = '';
			route.className = '';
	  
	  	// load directiosn from google
	    directions.load("from:" + myPoint +" to: "+ endPoint);
		
		//add some HTML to route elements
		var heading = document.createElement('h2');
		
			heading.innerHTML = 'Directions';
			heading.title = 'Click to Open/Close Directions';
			heading.style.cursor = 'pointer';
			
			//toggle directions visibility
			heading.onclick = function(){
				route.innerHTML = '';
				route.className = '';
				directions.clear();
				//GMapLarge.init(); // replace with remove direction function?
				for(i=0;i<myMarkers.length;i++){
					myMarkers[i].closeInfoWindow();	
				}
				
			}
			
		route.appendChild(heading);
    }
	
	
	//Directions Errors
GMapLarge.prototype.handleErrors = function(errorCode) {

      if (errorCode == 400) {
        alert("Error: Bad Request");
        return;
      }else if (errorCode == 500) {
        alert("Error: Server Error");
        return;
      }else if (errorCode == 603) {
        alert("Error: Unknown Address");
        return;
      }else{
	  	 alert("Error:" + errorCode +'\rPlease check your address and resubmit');
	  }
    }
	
	
	//Plot all locations to map 
GMapLarge.prototype.plotLocations = function(targetMapEl,caller){
		geocoder = new GClientGeocoder();
		for(i=0; i<locations.length; i++){
		//for(i in locations){
			with({i:i}){
			if(locations[i].Lat){
				
				//Check if sorting has be activatd and what to sort for.
				if(sortLoc){
					if(sortLoc.by == 'province'){
						if(locations[i].State.toLowerCase() == sortLoc.val){
							//nothing, proceed
						}else{
							continue;
						}
					}else if(sortLoc.by == 'city'){
						if(locations[i].City.toLowerCase() == sortLoc.val){
							//nothing, proceed
						}else{
						   continue;	
						}
					}
				}
				
				
				//Check business name and assign appropriate icon 
				
				if(locations[i].Name.match('Anvil Glass')){
					var mrk = new GMarker( 
							new GLatLng(locations[i].Lat,locations[i].Long),anvilMarkerOptions
						);
						GEvent.addListener(mrk, "click", function() {
							this.openInfoWindowHtml(PARAMS.locationData(locations[i]));
						});
					 targetMapEl.addOverlay(	mrk );
 
				}else if(locations[i].Name.match('True2Form Collision')){
					var mrk = new GMarker( 
							new GLatLng(locations[i].Lat,locations[i].Long),true2MarkerOptions
						);
						GEvent.addListener(mrk, "click", function() {
							this.openInfoWindowHtml(PARAMS.locationData(locations[i]));
						});
						
				    myMarkers.push(mrk);
					
				}else if(locations[i].Name.match('Gerber Collision & Glass')){
					var mrk = new GMarker( 
							new GLatLng(locations[i].Lat,locations[i].Long),gerberMarkerOptions
						);
						GEvent.addListener(mrk, "click", function() {
							this.openInfoWindowHtml(PARAMS.locationData(locations[i]));							
						});
						
				    myMarkers.push(mrk);
				
				}else if(locations[i].Name.match('Cars Collision Center')){
					var mrk = new GMarker( 
							new GLatLng(locations[i].Lat,locations[i].Long),carsMarkerOptions
						);
						GEvent.addListener(mrk, "click", function() {
							this.openInfoWindowHtml(PARAMS.locationData(locations[i]));							
						});
					//targetMapEl.addOverlay(	mrk );
				    myMarkers.push(mrk);
					
				}else if(locations[i].Name.match('Master Collision Repair')){
					var mrk = new GMarker( 
							new GLatLng(locations[i].Lat,locations[i].Long),masterMarkerOptions
						);
						GEvent.addListener(mrk, "click", function() {
							this.openInfoWindowHtml(PARAMS.locationData(locations[i]));							
						});
					//targetMapEl.addOverlay(	mrk );
				    myMarkers.push(mrk);
					
				}else{
					var mrk = new GMarker( 
							new GLatLng(locations[i].Lat,locations[i].Long),boydMarkerOptions
						);
						GEvent.addListener(mrk, "click", function() {
							this.openInfoWindowHtml(PARAMS.locationData(locations[i]));
						});

					 targetMapEl.addOverlay(	mrk );
					
				}
			}else if (geocoder) {
				
				  //If no lat/long available, geocode locations (not ideal as google only allows a small number at a time)
				  geocoder.getLatLng(locations[i].GAddress,	function(point) {
							if (!point) {
							//  alert(locations[i].gAddress + " not found")
							} else {
							  el.addOverlay(	new GMarker(point));
							  locations[i]['Lat'] = point.y;
							  locations[i]['Long'] = point.x;
							}
					  });
			}
			}
		}
	}

	var GMapLarge = new GMapLarge();


