function gmap() {
	this.bound = {};
	this.map = {};
	this.startCenter = {}
	this.mapType = {};
	this.infoWindow = {};
	this.markerList = [];
	this.mapOptions = {
	   zoom: 15,
	   center: this.startCenter,
	   mapTypeId: this.mapType,
	   mapTypeControl: false
	};
	// options related to this object, not the google map obj itself
	this.options = {
		fitMarkers: true,
		fitOnCenter: false, // keep the map centered and fit all markers?
		maxDistance: false // to set a max distance from center, enter the distance as a float and the unit (either km or mi) 
	};
}

gmap.prototype.init = function(config) {
    this.bound = new google.maps.LatLngBounds();
    // init center
    this.initStartCenter(config.center[0], config.center[1]);
    // init maptype
    this.initMapType(config.map_type);
    // init map
    this.map = new google.maps.Map(document.getElementById(config.map_id), this.mapOptions);
    // info window
    this.initInfoWindow();
    // set options
    for (i in config.options) {
        this.options[i] = config.options[i];
    }
    // load markers from data
    if (0 < config.marker_array.length) {
        var tmp_marker;
        var maxDist = this.options.maxDistance.distance;
        for (i = 0; i < config.marker_array.length; i++) {
            if (false != this.options.maxDistance) {
                if (maxDist < this.distance(this.startCenter, [config.marker_array[i][config.lat_key], config.marker_array[i][config.long_key]], this.options.maxDistance.uom)) {
                    i++;
                    break;
                }
            }
            if (i==0)
            {
                tmp_marker = this.placeMarker(config.marker_array[i][config.lat_key], config.marker_array[i][config.long_key], 'images/this-marker.png');
            }
            else
            {
                tmp_marker = this.placeMarker(config.marker_array[i][config.lat_key], config.marker_array[i][config.long_key], 'images/new-marker.png');
            }
            tmp_marker.data = config.marker_array[i];
            tmp_marker._parent = this;
            this.markerList[this.markerList.length] = tmp_marker;
            // bind event
            mapEvent = google.maps.event.addListener(tmp_marker, 'click', function() {
                window.location = "detail.asp?id=" + this.data.apt_id;
            });
        }
        if (this.options.fitMarkers && 1 < config.marker_array.length) {
            this.fitMarkers(this.startCenter);
        }
        
    }
}

gmap.prototype.distance = function(p1, p2, uom) {
	var latLng1, latLng2;
	try {
		p1.lat();
		latLng1 = p1;
	} catch(e) {
		if (p1 instanceof Array) {
			latLng1 = new google.maps.LatLng(p1[0], p1[1]);
		}
	}
	try {
		p2.lat();
		latLng2 = p2;
	} catch(e) {
		if (p2 instanceof Array) {
			latLng2 = new google.maps.LatLng(p2[0], p2[1]);
		}
	}
	var rad = function(x) { return x * Math.PI/180; }
	var R = 6371; // earth's mean radius in km
	var dLat = rad(latLng2.lat() - latLng1.lat());
	var dLong = rad(latLng2.lng() - latLng1.lng());

	var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(rad(latLng1.lat())) * Math.cos(rad(latLng2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
	var d = R * c;

	if ('mi' == uom) {
		return this.kmMi(d.toFixed(3));
	} else {
		return d.toFixed(3);
	}
}	

gmap.prototype.kmMi = function(x) {
	var mi = 0.621371192;
	var c = x * mi;
	return c.toFixed(2);
}

gmap.prototype.initStartCenter = function(lat, lng) {
	this.startCenter = new google.maps.LatLng(lat, lng);
	this.mapOptions.center = this.startCenter;
}

gmap.prototype.initMapType = function(type) {
   this.mapType =  google.maps.MapTypeId.ROADMAP;
   this.mapOptions.mapTypeId = this.mapType;
}

gmap.prototype.initInfoWindow = function() {
   this.infoWindow = new google.maps.InfoWindow({content: '<p>Test</p>'});
}

gmap.prototype.placeMarker = function(lat, lng, img) {
	var latLng = new google.maps.LatLng(lat, lng);
	var image = new google.maps.MarkerImage(img,
	// image dimenstions are width by height
                        new google.maps.Size(20, 34),
	// the origin for this image is 0,0
                        new google.maps.Point(0, 0),
	// the anchor of the image is the point of the tear-drop at 9,34
                        new google.maps.Point(9, 34)
                    );
	var shadow = new google.maps.MarkerImage('images/marker-shadow.png',
	// note this image is larger by 17px
                        new google.maps.Size(37, 34),
	// origin and anchor points remain the same
                        new google.maps.Point(0, 0),
                        new google.maps.Point(9, 34)
                    );
	// defines the clickable region of the icon. Traces polygon as a series of X,Y coords
	var shape = {
	    coord: [9, 0, 6, 1, 4, 2, 2, 4, 0, 8, 0, 12, 1, 14, 2, 16, 5, 19, 7, 23, 8, 26, 9, 30, 9, 34, 11, 34, 11, 30, 12, 26, 13, 24, 14, 21, 16, 18, 18, 16, 20, 12, 20, 8, 18, 4, 16, 2, 15, 1, 13, 0],
	    type: 'poly'
	}
	var marker = new google.maps.Marker({
	    position: latLng,
	    map: this.map,
	    shadow: shadow,
	    icon: image,
	    shape: shape
	});
	this.bound.extend(latLng);
	
	return marker;
}

gmap.prototype.fitMarkers = function(latLngObj) {
	if (undefined == latLngObj) {
		this.map.setCenter(this.bound.getCenter()); 
	} else {
		this.map.setCenter(latLngObj);
	}
	this.map.fitBounds(this.bound);
}

