/**
 * Class PB_Map
 *
 * set google maps with a mark to element id.
 *
 * 2009-07-09:: use GClientGeocoder.
 * 2009-07-15:: not use GMarkerManager because of it is not recommended.
 * 2010-01-08:: for Google Maps API version 3.
 *
 * @param string id The element id
 * @param int ma map data array
 * @param int z The zoom value
 * @param string iurl The url of icon image
 * @param string purl The url of icon image for click point
 *
 * @copyright 2006 - 2010 (c) Captain Yamagata Corporation. All Rights Reserved.
 */
var PB_Map = function(id, ma, z, iurl, purl) {
	this.gmap = null;
	this.geocoder = null;
	this.id = id;
	this.z = z;
	this.ma = ma;
	this.iurl = iurl;
	this.purl = purl;
	this.infowindows = {};
	this.markers = {};
	this.htmls = {};
}

PB_Map.prototype.init = function() {
	// initial location
	var init_key = null;
	for (var key in this.ma) {
		if (init_key == null) {
			init_key = key;
			break;
		}
	}
	var myLatlng = new google.maps.LatLng(this.ma[init_key][0], this.ma[init_key][1]);

	var myOptions = {
		zoom: this.z,
		center: myLatlng,
		mapTypeControl: true,
		mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
		navigationControl: true,
		navigationControlOptions: {style: google.maps.NavigationControlStyle.ZOOM_PAN},
		overviewMapControl: true,
		overviewMapControlOptions: {opened: true},
		scaleControl: true,
		mapTypeId: google.maps.MapTypeId.ROADMAP,
		streetViewControl: true
	}
	this.gmap = new google.maps.Map(document.getElementById(this.id), myOptions);

	// Create Geocoder
	this.geocoder = new google.maps.Geocoder();

	for (var key in this.ma) {
		var point = new google.maps.LatLng(this.ma[key][0], this.ma[key][1]);
		var title = key;
		var address = this.ma[key][2];
		var url = this.ma[key][3];
		var html = ['<div class="mapinfo">', '<b>', title, '</b><br />', address, '<br />',
			'<a href="', url, '" target="_blank">', url, '</a>', '</div>'].join('');
		this.infowindows[key] = new google.maps.InfoWindow({ content: html });
		this.markers[key] = this.addMarker(point, this.iurl, title, this.infowindows[key]);
		this.htmls[key] = html;
	}
	google.maps.event.trigger(this.markers[init_key], 'click');

	// Add click event on the map
	this.showLatLng();
}

/**
 * add maker
 *
 * Creates a marker whose info window displays the given number
 *
 * @param GLatLng p a LatLng instance
 * @param string icon The url of icon image
 * @param string title The title strings
 * @param string iw an InfoWindow instance
 * @return a Marker instance
 */
PB_Map.prototype.addMarker = function(p, icon, title, iw) {
	var marker = icon ? new google.maps.Marker({
					position: p,
					map: this.gmap,
					icon: this.createIcon(icon),
					title: title
				}) : new google.maps.Marker({
					position: p,
					map: this.gmap,
					title: title
				});

	// Show this marker's index in the info window when it is clicked
	var mymap = this;
	google.maps.event.addListener(marker, 'click', function() {
		iw.open(mymap.gmap, marker);
	});

	return marker;
}

/**
 * Create an icon instance
 *
 * create an icon instance by MarkerImage class and return it.
 * Currently, supported only 32x32 pixel icon.
 *
 * @param string url The url of icon image
 * @return a MarkerImage instance
 */
PB_Map.prototype.createIcon = function(url) {
	return new google.maps.MarkerImage(
				url,
				new google.maps.Size(32, 32),
				new google.maps.Point(0, 0),
				new google.maps.Point(20, 30)
				);
}

PB_Map.prototype.marker = function(title) {
	return this.markers[title];
}

PB_Map.prototype.html = function(title) {
	return this.htmls[title];
}

PB_Map.prototype.generateTable = function(caption, lat, lng) {
	return ['<table class="latlng">', '<caption>', caption, '</caption>',
		'<thead><tr><th>緯度</th><th>経度</th></tr></thead>',
		'<tbody>', '<tr><td>', lat, '</td><td>', lng, '</td></tr>', '</tbody>',
		'</table>'].join('');
}

PB_Map.prototype.showLatLng = function() {
	var mymap = this;
	google.maps.event.addListener(this.gmap, "click", function(event) {
		if (!event.latLng) { // when closing InfoWindow.
			return;
		}
		mymap.geocoder.geocode({'latLng': event.latLng}, function(results, status) {
			var address = (!results[0] || status != google.maps.GeocoderStatus.OK) ?
				'住所が不明です。&emsp;ステータス: ' + status :
				results[0].formatted_address.replace(/^日本/, '');
			var html = mymap.generateTable(address, event.latLng.lat(), event.latLng.lng());
			var iw = new google.maps.InfoWindow({ content: html });
			var marker = mymap.addMarker(event.latLng, mymap.purl, address, iw);
			google.maps.event.trigger(marker, 'click');
		});
	});
}

PB_Map.prototype.showPointFrom = function(address) {
	var mymap = this;
	this.geocoder.geocode({'address': address}, function(results, status) {
	if (status == google.maps.GeocoderStatus.OK) {
		mymap.gmap.setCenter(results[0].geometry.location);
		var html = mymap.generateTable(address,
			results[0].geometry.location.lat(), results[0].geometry.location.lng());
		var iw = new google.maps.InfoWindow({ content: html });
		var marker = mymap.addMarker(results[0].geometry.location, mymap.purl, address, iw);
		google.maps.event.trigger(marker, 'click');
	} else {
		alert("Geocode was not successful for the following reason: " + status);
	}
	});
}

