// Version 10.01.07

// For valid values for opts, see http://code.google.com/apis/maps/documentation/v3/reference.html#MapOptions
function MapSet(id, center_lat, center_lng, zoom, opts)
{
	var fn, body;
	
	this.map=null;
	this._marker_icons={};
	this.markers=[];
	this.circle=null;
	this.centerMarker=null;
	this._ready=false;
	
	fn=function()
	{
		if((typeof(opts)) != 'object')
			opts={};
		
		opts.zoom=zoom;
		opts.center=new google.maps.LatLng(center_lat, center_lng),
		opts.mapTypeId=google.maps.MapTypeId.ROADMAP
		
		this.map = new google.maps.Map(document.getElementById(id), opts);
		
		this._ready=true;
	}.bind(this).defer(function(){return (!!document.getElementById(id) && !!google && !!google.maps);}.bind(this));
	
	return this;
}

MapSet.prototype.addIcon=function(name, image, shadow)
{
	this._marker_icons[name]={};
	this._marker_icons[name].image=image;
	this._marker_icons[name].shadow=false;
	if(!!shadow)
		this._marker_icons[name].shadow=shadow;
	return this;
}

MapSet.prototype.fitMarkers=function()
{
	var i, min_lat=false, max_lat=false, min_lng=false, max_lng=false;
	
	if(this.markers.length > 0)
	{
		for(i in this.markers)
		{
			if(min_lat===false || this.markers[i].position.lat() < min_lat)
				min_lat=this.markers[i].position.lat();
			if(max_lat===false || this.markers[i].position.lat() > max_lat)
				max_lat=this.markers[i].position.lat();
			if(min_lng===false || this.markers[i].position.lng() < min_lng)
				min_lng=this.markers[i].position.lng();
			if(max_lng===false || this.markers[i].position.lng() > max_lng)
				max_lng=this.markers[i].position.lng();
		}
		
		this.map.fitBounds(new google.maps.LatLngBounds(new google.maps.LatLng(min_lat, min_lng), new google.maps.LatLng(max_lat, max_lng)));
	}
	
	return this;
}

MapSet.prototype.addMarker=function(num, lat, lng, icon, info, onclick)
{
	var fn=function(lat, lng, html)
	{
		var options, marker, info_window;
		
		options=
		{
			position: new google.maps.LatLng(lat, lng),
			map: this.map
		};
		
		if(!!icon)
		{
			options.icon=new google.maps.MarkerImage(this._marker_icons[icon].image);
			if(this._marker_icons[icon].shadow)
				options.shadow=new google.maps.MarkerImage(this._marker_icons[icon].shadow);
			else
				options.zIndex=0;
		}
		
		marker = new google.maps.Marker(options);
		
		if(!!info)
		{
			info_window=new google.maps.InfoWindow(
			{
				content: info
			});
			info_window.open(this.map, marker);
		}
		
		if(!!onclick)
			google.maps.event.addListener(marker, 'click', onclick.bind(this));
		else
			marker.setClickable(false);
		
		this.markers[num]=marker;
	}.partial(lat, lng, onclick).bind(this).defer(function()
	{
		return (this._ready);
	}.bind(this));
	
	return this;
}

MapSet.prototype.drawLocations=function(resp)
{
	var locations, i, html, lat, lng;
	
	this.map.clearOverlays();
	this.map.setCenter(new google.map.LatLng(resp.zipcode.lat, resp.zipcode.lng), 11);

	locations = resp.locations;
	var i = locations.length;
	while(i--)
	{
		html = '<div><strong>'+htmlentities(locations[i].name)+'</strong><br />'+htmlentities(locations[i].address)+'<br />'+htmlentities(locations[i].city)+', '+htmlentities(locations[i].state)+', '+htmlentities(locations[i].zip);
		if(!!locations[i].phone)
			html+= '<br />'+htmlentities(locations[i].phone);
		if(!!locations[i].services)
			html+='<br />'+htmlentities(locations[i].services);
		html+='</div>';
		this.addMarker(locations[i].id, locations[i].lat, locations[i].lng, null, html);
	}
	
	this.drawCircle(resp.radius);
}

MapSet.prototype.drawCircle=function(radius, units)
{
	var center, bounds, points, d, lat1, lng1, lat2, lng2, a, tc, y, dlng, x, point;
	
	if(!units)
		units='mi';
	
	center = this.map.getCenter();
	bounds = new GLatLngBounds();
	points = [];
	
	if(!!this.circle)
		this.map.removeOverlay(circle);
	
	if(units == 'km')
		d = radius/6378.8;	// radians
	else //miles
		d = radius/3963.189;	// radians
	
	lat1 = (Math.PI/180)* center.lat(); // radians
	lng1 = (Math.PI/180)* center.lng(); // radians
	
	for (a = 0; a < 361; a++)
	{
		tc = (Math.PI/180)*a;
		y = Math.asin(Math.sin(lat1)*Math.cos(d)+Math.cos(lat1)*Math.sin(d)*Math.cos(tc));
		dlng = Math.atan2(Math.sin(tc)*Math.sin(d)*Math.cos(lat1),Math.cos(d)-Math.sin(lat1)*Math.sin(y));
		x = ((lng1-dlng+Math.PI) % (2*Math.PI)) - Math.PI;
		point = new GLatLng(parseFloat(y*(180/Math.PI)),parseFloat(x*(180/Math.PI)));
		points.push(point);
		bounds.extend(point);
	}
	
	if (d < 1.5678565720686044)
		this.circle = new GPolygon(points, '#000000', 2, 1, '#000000', 0.25);
	else
		this.circle = new GPolygon(points, '#000000', 2, 1);
	this.map.addOverlay(this.circle); 
	
	this.map.setZoom(this.map.getBoundsZoomLevel(bounds));
	
	return this;
}
