var MakeMap = Class.create();
MakeMap.prototype = {

	largeCtlLimitH	: 280,		// GLargeMapControlが表示できる地図のHight
	divId			: undefined,// マップ表示のDIVタグID
	centerLat		: undefined,// 緯度　-90～+90
	centerLng		: undefined,// 経度	-180～+180
	map				: undefined,// Google Mapオブジェクト
	errorFlg		: false,
	options			: {},
	initialize : function(divId, centerLat, centerLng, options) {
		if (!divId || !centerLat || !centerLng) {
			return;
		}
		if (!GBrowserIsCompatible()) {
			this.errorFlg = true;
			return;
		}

		// 表示divタグのID
		this.divId = divId;
		// 地図の中心座標
		this.centerLat = centerLat;
		this.centerLng = centerLng;

		this.options = Object.extend({
			zoom			: 10,
			cbFuncZoom		: '',
			markerPoints	: [],
			dispCenterMarker: false,	// 中央マーカーの有無
			dispInfoWindow	: false,	// 吹き出し表示の有無
			centerInfoWinData: '',		// 中央マーカーの吹き出しの内容
			mapWidth		: '300px',
			mapHeight		: '280px',
			mapType			: G_NORMAL_MAP,	// G_NORMAL_MAP 通常, G_SATELLITE_MAP 衛星写真, G_HYBRID_MAP 地図と衛星写真の合成
			errorHtml		: '<div id="map_err" style="color:#FF0000;text-align:center;">地図を表示できません。</div>',
			streetview		: false
		}, options || {});

		this.options.iconInfo = Object.extend({
			iconImage			: '',	// アイコンイメージファイルのURL
			iconWidth			: -1,	// アイコンの幅
			iconHeight			: -1,	// アイコンの高さ
			iconAnchorX			: -1,	// アイコンが指し示す位置を、アイコン左上隅(0,0)座標からの相対座標x
			iconAnchorY			: -1,	// アイコンが指し示す位置を、アイコン左上隅(0,0)座標からの相対座標y
			iconInfoWinAnchorX	: -1,	// 吹き出しを固定する座標を、アイコン左上隅(0,0)座標からの相対座標x
			iconInfoWinAnchorY	: -1	// 吹き出しを固定する座標を、アイコン左上隅(0,0)座標からの相対座標y
		}, options.iconInfo || {});

		this.options.addControls = Object.extend({
			GSmallMapControl	: false,
			GLargeMapControl	: true,
			GScaleControl		: true,
			GMapTypeControl		: true,
			GOverviewMapControl	: true
		}, options.addControls || {});

		// Google Map の表示領域サイズ
		$(this.divId).style.width	= this.options.mapWidth;
		$(this.divId).style.height	= this.options.mapHeight;
		
		this.map = new GMap2($(divId));
		// コントロール設定
		for (var controlName in this.options.addControls) {
			if (this.options.addControls[controlName]) {
				if (controlName == 'GLargeMapControl') {
					var h = this.options.mapHeight;
					h = + h.replace(/\D/g, '');
					if (h < this.largeCtlLimitH) {
						controlName = 'GSmallMapControl';
					}
				}
				var control = eval('new ' + controlName + '()');
				this.map.addControl(control);
				if (controlName == 'GOverviewMapControl') {
					this.overview = control;
				}
			}
		}
		
		GEvent.addListener(
			this.map,
			'maptypechanged',
			function(maptype) {
				if (this.overview) {
					this.overview.setMapType(maptype);
				}
			}.bind(this)
		);
		
		this.markerPoints	= [];
		this.markers		= [];
		
		// 地図タイプ
		var type = G_NORMAL_MAP;
		var maptypes = this.map.getMapTypes();
		for (var i=0; i<maptypes.length; i++) {
			if(maptypes[i] == this.options.mapType) {
				type = this.options.mapType;
				break;
			}
		}

		// setCenter(center, zoom, type)
		// 	center 表示される地図の中央座標
		// 	zoom 縮尺（省略可能）
		// 	type マップタイプ（省略可能）
		this.map.setCenter(new GLatLng(this.centerLat, this.centerLng), this.options.zoom, type);

		// ZOOM変更のイベントハンドラ
		if (this.options.cbFuncZoom) {
			 GEvent.addListener(this.map, 'zoomend', this.options.cbFuncZoom);
		}
		
		// センターマーカー表示
		if (this.options.dispCenterMarker) {
			// アイコン設定オプションがあるとき
			if (this.options.iconInfo) {
				iconInfo = this.options.iconInfo;
			} else {
				iconInfo = "";
			}
			// 吹き出しウィンドウを表示し、表示内容が設定されているとき
			if (this.options.dispInfoWindow && this.options.centerInfoWinData) {
				infoWinData = this.options.centerInfoWinData;
			} else {
				infoWinData = "";
			}
			this.setMarker(this.centerLat, this.centerLng, infoWinData, iconInfo);
			this.dispMarker();
		}
		
		// マーカー表示
		if (this.options.markerPoints.length) {
			for (var i in this.options.markerPoints) {
				var markerPoint = this.options.markerPoints[i];
				if (markerPoint.iconInfo) {
					iconInfo = markerPoint.iconInfo;
				} else if (this.options.iconInfo) {
					iconInfo = this.options.iconInfo;
				} else {
					iconInfo = "";
				}
				this.setMarker(markerPoint.lat, markerPoint.lng, markerPoint.infoWinData, iconInfo, markerPoint.cbFunc);
			}
			this.dispMarker();
		}

		if (this.options.streetview) {
			//ストリートビュー用のコンテナ
			this.svContainer = document.createElement('div');
			this.svContainer.style.width = '300px';
			this.svContainer.style.height = '200px';
			this.map.addOverlay(new GStreetviewOverlay());
			for (var i = 0; i < this.markers.length; i++) {
				GEvent.addListener(this.markers[i], 'click', function (marker) {
					var visible = this.svObj == undefined ? true : false;
					this.dispStreetview(marker, visible);
				}.bind(this, this.markers[i]));
			}
			this.dispStreetview(this.markers[0], true);
		}
	},

	setMarker : function(lat, lng, infoWinData, iconInfo, cbFunc) {
		if (!lat || !lng) {
			return;
		}
		var mPoint = new GLatLng(lat, lng);
		this.markerPoints.push(mPoint);

		if (iconInfo && iconInfo.iconImage != '' && iconInfo.iconWidth > 0 && iconInfo.iconHeight > 0) {
			// マーカー用のアイコンオブジェクトを作成する
			var iconObj = this.makeIconObject(iconInfo);
			var marker = new GMarker(mPoint, iconObj);
		} else {
			var marker = new GMarker(mPoint);
		}
		// 吹き出しウィンドウに表示するデータがある？
		if (infoWinData) {
			marker.infoWinData = infoWinData;
			marker.onClickFunc = function (mapObj) {
				mapObj.dispMarkerInfoWin(this);
			}
		}
		
		if (cbFunc) {
			marker.onClickFunc = cbFunc;
		}
		
		if (marker.onClickFunc) {
			GEvent.addListener(marker, "click", function(marker) {
				marker.onClickFunc(this);
			}.bind(this, marker));
		}
		
		this.markers.push(marker);
	},

	dispMarker : function() {
		for (i=0;i<this.markers.length;i++) {
			this.map.addOverlay(this.markers[i]);
		}
	},

	dispMarkerInfoWin : function (marker) {
		if (!marker.infoWinData) {
			return false;
		}
		marker.openInfoWindowHtml(marker.infoWinData);
	},

	// マーカー用のアイコンオブジェクトを作成し、作成したオブジェクトを返します
	makeIconObject : function(iconInfo) {
		var iconObj;
		// アイコン関連のプロパティ設定
		if (iconInfo && iconInfo.iconImage != '' && iconInfo.iconWidth > 0 && iconInfo.iconHeight > 0) {
			iconObj = new GIcon();
			iconObj.image = iconInfo.iconImage;
			iconObj.iconSize = new GSize(iconInfo.iconWidth, iconInfo.iconHeight);
			// アイコンが指し示す位置を設定
			if (iconInfo.iconAnchorX >= 0 && iconInfo.iconAnchorY >= 0) {
				iconObj.iconAnchor = new GPoint(iconInfo.iconAnchorX, iconInfo.iconAnchorY);
			} else {
				iconObj.iconAnchor = new GPoint(iconInfo.iconWidth/2, iconInfo.iconHeight/2);
			}
			// 吹き出しを固定する座標を設定
			if (iconInfo.iconInfoWinAnchorX >= 0 && iconInfo.iconInfoWinAnchorY >= 0) {
				iconObj.infoWindowAnchor = new GPoint(iconInfo.iconInfoWinAnchorX, iconInfo.iconInfoWinAnchorY);
			} else {
				iconObj.infoWindowAnchor = new GPoint(iconInfo.iconWidth/2, iconInfo.iconHeight/2);
			}
			iconObj.transparent = iconInfo.iconImage;
		}
		return iconObj;
	},

	// 指定したマーカーへ移動し、指定した縮尺に変更する
	setMarkerPanZoom : function (marker, zoom) {
		if (zoom) {
			this.setZoom(zoom);
		}
		var latlngObj = marker.getPoint();
		this.panTo(latlngObj.lat(), latlngObj.lng());
	},

	// 移動
	panTo : function(lat, lng) {
		this.map.panTo(new GLatLng(lat, lng));
	},

	// 縮尺変更
	setZoom : function(zoom) {
		this.map.setZoom(zoom);
	},
	
	// 現在の縮尺を取得
	getZoom : function() {
		return this.map.getZoom();
	},
	
	closeInfoWindow : function() {
		this.map.closeInfoWindow();
	},
	
	// ストリートビュー表示
	dispStreetview : function(marker, visible) {
		if (!this.svContainer) return;
		var markerPos = marker.getPoint();
		if (visible) {
			//GStreetviewPanoramaの作成
			//(スレッド化させるため、setTimeout)
			setTimeout(function(markerPos){
				this.svObj = new GStreetviewPanorama(this.svContainer, {latlng:markerPos});
			}.bind(this, markerPos), 100);
			//ふきだしの表示
			marker.openInfoWindow(this.svContainer);
		} else if (this.svObj) {
			this.map.closeInfoWindow();
			this.svObj.remove();
			this.svObj = undefined;
		}
	},

	// エラー表示
	outPutMapErr : function() {
		document.getElementById(this.divId).innerHTML = this.options.errorHtml;
	}
}

