/**
 * GMap2クラス
 * @param objId GooleMaps表示オブジェクトのID名:String
 * @param objData 情報ウィンドウ内要素格納オブジェクト:Object
 * @param objSetting 設定値格納オブジェクト:Object
 */
var GDMap2 = function(objId,objData,objSetting){
	//定数の宣言
	//引数により設定変更可能なもの
	this.zoom					= (objSetting.zoom ? parseInt(objSetting.zoom,10) : 14);								//初期ズームレベル
	this.searchOff_zoomLevel	= (objSetting.searchOffZoom ? parseInt(objSetting.searchOffZoom,10) : 11);				//検索ボタンをOFFにするズームレベル
	this.searchBtnOnId			= (objSetting.searchBtnOnId ? objSetting.searchBtnOnId : '');							//検索ボタンONのオブジェクト
	this.searchBtnOffId			= (objSetting.searchBtnOffId ? objSetting.searchBtnOffId : '');							//検索ボタンOFFのオブジェクト
	this.infoOption				= {maxWidth:(objSetting.infoMaxWidth ? parseInt(objSetting.infoMaxWidth,10) : 400)};	//情報ウィンドウオプション

	this.searchFlg				= (objSetting.searchFlg && objSetting.searchFlg == "true" ? true : false);				//検索フラグ
	this.infoFlg				= (objSetting.infoFlg && objSetting.infoFlg == "true" ? true : false);					//情報ウィンドウ表示フラグ
	this.listArea				= (objSetting.listName ? objSetting.listName : '');										//検索結果リスト表示オブジェクトID名
	//GoogleMaps関係
	this.gmapArea				= $(objId);								//GoogleMaps表示オブジェクト
	this.infoDataObj			= objData;								//情報ウィンドウデータオブジェクト
	this.iconPath				= "/shared/system/images/maps/";		//アイコンファイルへのパス
	this.icon_width				= "34";									//アイコン幅
	this.icon_height			= "37";									//アイコン高さ
	this.iconSelf				= "icon_map_arrow_self.gif";			//自身のアイコン
	this.iconFile				= {										//カテゴリごとのアイコンファイル
	};
	this.infoHtml				= {								//情報ウィンドウ内HTMLフォーマット
		title  :'<p style="margin:3px 0px;font-size:12pt;"><strong>#TITLE#</strong><p>',
		address:'<p style="margin:2px;font-size:10pt;">住所：#ADDRESS#</p>',
		tel    :'<p style="margin:2px;font-size:10pt;">電話：#TEL#</p>',
		url    :'<p align="right" style="margin:2px;font-size:10pt;"><a href="#URL#">詳細情報を見る</a></p>'
	};
	//Ajax関係
	this.s_method				= "POST";						//フォームデータのMETHOD属性値（GET/POST）
	this.s_async				= true;							//非同期通信（TRUE=有効 , FALSE=無効）
	this.s_path					= "";							//検索プログラムパス
	this.listHeader				= "";							//検索結果リスト検索種類ヘッダ
	this.listNormal				= "";							//リストの通常クラス名称
	this.listMsover				= "";							//リストのマウスオーバー時クラス名称
	this.listIconPath			= "";							//アイコンファイルへのパス
	this.listHeaderIconFile		= {								//検索結果リスト検索種類ヘッダのアイコンファイル
	};
	this.listHeaderAlt = {										//検索結果リスト検索種類ヘッダの画像ALT
	};

	//変数の宣言
	//GoogleMaps関係
	this.gmap			= null;							//GMap2インスタンス
	this.basemarker		= null;							//ページ自身のマーカー格納
	this.marker			= new Object();					//マーカー格納
	//Ajax関係
	this.resultData		= null;							//検索結果リスト格納オブジェクト

	//チェック
	if(!this.gmapArea){
		alert("System Error! [Constructor]\nGoogle Maps表示領域が存在しません。");
		return;
	}
	if(!this.infoDataObj.lat || !this.infoDataObj.lng){
		alert("System Error! [Constructor]\n緯度経度の取得に失敗しました。");
		return;
	}
	this.loading();
}

/**
 * 処理関数郡の宣言
 * GoogleMaps表示に使用する関数郡
 */
GDMap2.prototype = {
	/**
	 * ロード画面を表示
	 * GoogleMaps表示エリアにロード中であることを示す文字を描画する
	 */
	loading : function(){
		if(this.gmapArea) this.gmapArea.innerHTML = '<div style="font-size:80%;padding:10px;">Now Loading...</div>';
		this.initGmap();
	},

	/**
	 * GoogleMaps初期化
	 * GoogleMapsを初期化する
	 */
	initGmap : function(){
		//ブラウザチェック
		if(!GBrowserIsCompatible()){
			alert("ご利用のブラウザではGoogleMapsを表示することができません。");
			return;
		}
		//GoogleMapsの初期セット
		this.gmap = new GMap2(this.gmapArea);
		var point = new GLatLng(this.infoDataObj.lat,this.infoDataObj.lng);
		this.gmap.setCenter(point, this.zoom);
		this.gmap.addControl(new GLargeMapControl());
		this.gmap.addControl(new GScaleControl());
		new GKeyboardHandler(this.gmap);
		this.gmap.enableContinuousZoom();		//連続した滑らかなズーム処理
		this.gmap.enableDoubleClickZoom();		//ダブルクリックによるズーム処理
		//情報ウィンドウ表示処理
		this.basemarker = this.createMarker(this.infoDataObj);
		if(this.basemarker){
			this.gmap.addOverlay(this.basemarker);
			//infoFlgがtrueの場合
			if(this.infoFlg == true){
				//InfoWindowを表示
				this.basemarker.openInfoWindowHtml(this.createInfoWindowHtml(this.infoDataObj),this.infoOption);
			}
		}
		//listAreaが指定されている場合
		if(this.listArea != ""){
			//結果表示
			this.resultData = new Object();
			this.resultData[this.infoDataObj.id] = this.infoDataObj;	//検索結果情報のセット
			this.createResultList(this.infoDataObj,0);					//検索結果リストのセット
		}
		//searchFlgがtrueの場合
		if(this.searchFlg == true){
			//検索ボタン用イベント登録
			GEvent.addListener(this.gmap,"zoomend",
				function(oldLevel,newLevel){
					//検索ボタンOFF
					if(this.searchOff_zoomLevel > newLevel){
						if($(this.searchBtnOnId)) $(this.searchBtnOnId).style.display = "none";
						if($(this.searchBtnOffId)) $(this.searchBtnOffId).style.display = "block";
					}
					//検索ボタンON
					else{
						if($(this.searchBtnOffId)) $(this.searchBtnOffId).style.display = "none";
						if($(this.searchBtnOnId)) $(this.searchBtnOnId).style.display = "block";
					}
				}.bind(this)
			);
		}
	},

	/**
	 * GoogleMaps表示領域範囲の緯度経度取得
	 * GoogleMaps表示領域範囲の緯度経度を取得する
	 * @return lat_min:最小緯度 lat_max:最大緯度 lng_min:最小経度 lng_max:最大経度
	 */
	getFourLatLng : function(){
		var bounds  = this.gmap.getBounds();	//矩形領域を取得
		var ne      = bounds.getNorthEast();	//矩形領域の北東ポイントを取得
		var sw      = bounds.getSouthWest();	//矩形領域の南西ポイントを取得
		var lat_min = sw.lat();					//最小緯度
		var lat_max = ne.lat();					//最大緯度
		var lng_min = sw.lng();					//最小経度
		var lng_max = ne.lng();					//最大経度
		return{
			lat_min:lat_min,
			lat_max:lat_max,
			lng_min:lng_min,
			lng_max:lng_max
		};
	},

	/**
	 * GoogleMapsマーカー生成
	 * GoogleMaps表示用のマーカーを生成する
	 * @param obj マーカー作成用オブジェクト
	 * @return 作成したマーカー
	 */
	createMarker : function(obj){
		//引数チェック
		var key = ((obj.id) ? obj.id : "");
		if(key == ""){
			alert("System Error! [Func:createMarker]\nデータIDの取得に失敗しました。");
			return;
		}
		if(this.basemarker && key == this.infoDataObj.id) return;
		//アイコンの作成
		var icon;
		if(key == this.infoDataObj.id && this.iconSelf != "") icon = this.createIcon(this.iconSelf);
		else if(obj.purpose && this.iconFile[obj.purpose]) icon = this.createIcon(this.iconFile[obj.purpose]);
		//マーカーの作成
		var marker;
		if(icon) marker = new GMarker(new GLatLng(obj["lat"],obj["lng"]),{icon:icon,title:obj["title"]});
		else marker = new GMarker(new GLatLng(obj["lat"],obj["lng"]),{title:obj["title"]});
		//infoFlgがtrueの場合
		if(this.infoFlg == true){
			//クリックイベントの登録
			GEvent.addListener(marker, "click",
				function(){
					//InfoWindowを表示
					marker.openInfoWindowHtml(this.createInfoWindowHtml(obj),this.infoOption);
				}.bind(this)
			);
		}
		this.marker[key] = marker;
		return marker;
	},

	/**
	 * GoogleMapsアイコン生成
	 * GoogleMapsマーカー作成用のアイコンを生成する
	 * @param iconFileName アイコンファイルのファイル名
	 * @return 作成したアイコン
	 */
	createIcon : function(iconFileName){
		//引数チェック
		if(!this.iconPath || !this.icon_width || !this.icon_height || !iconFileName) return false;
		//アイコン作成
		var icon = new GIcon();
		icon.image = this.iconPath + iconFileName;
		icon.iconSize = new GSize(this.icon_width,this.icon_height);
		icon.iconAnchor = new GPoint(this.icon_width / 2,this.icon_height);	//アイコンと地図ポイントの位置関係：中央×下
		icon.infoWindowAnchor = new GPoint(this.icon_width / 2,0);
		return icon;
	},

	/**
	 * GoogleMaps情報ウィンドウ内HTML生成
	 * GoogleMaps情報ウィンドウ内のHTMLを生成する
	 * @param obj 情報ウィンドウに必要な値を持ったオブジェクト
	 * @return 作成したhtml
	 */
	createInfoWindowHtml : function(obj){
		var html = '';
		if(obj.title)   html += this.infoHtml.title.replace("#TITLE#",htmlspecialchars(obj.title));
		if(obj.address) html += this.infoHtml.address.replace("#ADDRESS#",htmlspecialchars(obj.address));
		if(obj.tel)     html += this.infoHtml.tel.replace("#TEL#",htmlspecialchars(obj.tel));
		if(obj.url)     html += this.infoHtml.url.replace("#URL#",htmlspecialchars(obj.url));
		return html;
	},

	/**
	 * 検索クエリ
	 * 検索処理を実行する
	 * @param query 検索に使用する値を持った文字列
	 * @return 作成したhtml
	 */
	doQuery : function(query){
		var chache = true;							//キャッシュ無効スイッチ(true/false)
		var xmlhttpobj = createXMLHttpRequest();	//XMLHttpRequestオブジェクト
		//Ajaxで検索開始
		xmlhttpobj.open(this.s_method,this.s_path,this.s_async);
		if(this.s_method == 'POST') xmlhttpobj.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
		//キャッシュを見に行かないようにする
		if(chache) xmlhttpobj.setRequestHeader("If-Modified-Since", "Thu, 01 Jun 1970 00:00:00 GMT");
		xmlhttpobj.onreadystatechange = function(){
			if(xmlhttpobj.readyState == 4){
				if(xmlhttpobj.status == 200) this.getResult(xmlhttpobj);
				else alert("検索に失敗しました。【 " + xmlhttpobj.status + " 】");
			}
		}.bind(this);
		xmlhttpobj.send(query);
	},

	/**
	 * 結果取得
	 * 検索結果を取得する
	 * @param query 検索に使用する値を持った文字列
	 * @return 作成したhtml
	 */
	getResult : function(obj){
		if(obj.responseText != "") eval('var data=' + obj.responseText);
		else var data = new Object();
		this.resultData = data;
		//リストの初期化
		if(this.listArea != "" && $(this.listArea)) $(this.listArea).innerHTML = "<ul></ul>";
		//マーカーの作成
		var key,id,marker,result;
		var loop_cnt = 0;
		//自身のマーカーを表示
		if(this.basemarker) this.gmap.addOverlay(this.basemarker);
		//その他のマーカーを表示
		for(key in data){
			//マーカーの作成
			marker = this.createMarker(data[key]);
			if(marker) this.gmap.addOverlay(marker);
			//検索結果リスト表示
			this.createResultList(data[key],loop_cnt);
			loop_cnt++;
		}
		//リストエリアに何も表示が無ければ、指定文字を表示
		if(this.listArea != "" && $(this.listArea) && ($(this.listArea).innerHTML == "" || $(this.listArea).innerHTML.match(/<ul><\/ul>/i))) $(this.listArea).innerHTML = '<p style="font-size:12px;">該当する情報はありません</p>';
	},

	/**
	 * 結果リスト生成
	 * 検索結果リストを生成する
	 * @param obj 検索結果が入っているオブジェクト
	 * @param loop_cnt 何件目の結果か分かるようにするためのカウンター
	 * @return 作成したhtml
	 */
	createResultList : function(obj,loop_cnt){
		//表示エリアの存在チェック
		if(this.listArea == "" || !$(this.listArea)) return;
		//objのIDがページ自身のIDと同じならreturnする
		if(obj.id == this.infoDataObj.id) return;
		//リストに表示するデータを作成
		var data = document.createElement('li');
		data.id = obj.id;
		data.map_name = this.gmapArea.id;
		if(loop_cnt % 2 == 0) data.className = 'odd';
		data.innerHTML = '<a href="javascript:void(0)">' + htmlspecialchars(obj.title) + '</a>';
		$(this.listArea).firstChild.appendChild(data);
		//onClickイベントの処理登録
		data.onclick = function(){
			eval("gmap2_" + this.map_name + ".listClickEventListener(this.id)");
		};
	},

	/**
	 * 結果リストクリックイベント
	 * 検索結果リストをクリックしたときのイベント
	 * @param key クリックされたリストのID
	 */
	listClickEventListener : function(key){
		//データのチェック
		if(!this.marker[key] || !this.resultData[key]){
			alert("System Error! [Func:listClickEventListener]\nマーカー情報の取得に失敗しました。");
			return;
		}
		//infoFlgがtrueの場合
		if(this.infoFlg == true){
			//InfoWindowを表示
			this.marker[key].openInfoWindowHtml(this.createInfoWindowHtml(this.resultData[key]),this.infoOption);
		}
		//infoFlgがfalseの場合
		else{
			//マーカーをセンタリング
			this.gmap.setCenter(this.marker[key].getPoint(),this.zoom);
		}
	},

	/**
	 * 表示範囲内の検索処理
	 * 表示範囲内で検索を行った際の処理
	 * @param purpose_id クリックされたボタンのID
	 * @return false:処理終了
	 */
	reSearch : function(purpose_id){
		//検索なしならば、そのままリターンする
		if(this.searchFlg == false) return false;
		//情報ウィンドウ非表示
		this.gmap.closeInfoWindow();
		//全マーカー削除
		this.gmap.clearOverlays();
		this.marker = new Object();
		//緯度経度範囲の抽出
		var pointRange = this.getFourLatLng();
		var lat_min = pointRange.lat_min;
		var lat_max = pointRange.lat_max;
		var lng_min = pointRange.lng_min;
		var lng_max = pointRange.lng_max;
		//リストのヘッダー画像を変更
		if(this.listHeaderIconFile[purpose_id] && this.listHeaderAlt[purpose_id]){
			if($(this.listHeader)) $(this.listHeader).innerHTML = '<img src="' + this.listIconPath + this.listHeaderIconFile[purpose_id] + '" alt="' + this.listHeaderAlt[purpose_id] + '" />';
		}
		//引数の作成
		var query   = "lat_min=" + lat_min + "&lat_max=" + lat_max + "&lng_min=" + lng_min + "&lng_max=" + lng_max + "&purpose=" + purpose_id;
		//検索処理
		this.doQuery(query);
		return false;
	}
}

