//地図データ管理
//
//prototype.js(1.4)が必要 

var MapData = new Object();
//ヘルパーオブジェクト
MapData.Helper = Class.create();
MapData.Helper.prototype = {
	initialize:function(){
	},
	safariFilter:function(text){
		//Safari の responseText で UTF-8 コード文字化け回避
		//http://kawa.at.webry.info/200511/article_9.html
		if ( navigator.appVersion.indexOf( "KHTML" ) > -1 ) {
			var esc = escape( text );
			if ( esc.indexOf("%u") < 0 && esc.indexOf("%") > -1 ) {
				text = decodeURIComponent( esc );
			}
		}
		return text;
	}
};

//情報ウィンドウポップアップ管理
MapData.PopupManager = Class.create();
MapData.PopupManager.prototype = {
	funcArray: null,
	popupkey:'',
	
	initialize: function(){
		this.clear();
    },
    
	//登録関数をクリアする
	clear: function(){
		this.funcArray = new Object();
		this.popupkey = '';
	},
	
	//ポップアップ処理関数を登録する
	setFunction: function(key,regFunction){
		this.funcArray[key] = regFunction;
	},
	
	//tryPopup()で実行したいポップアップ関数のキーを登録する
	setKey: function(key){
		this.popupkey = key;
	},
	
	//キーに設定されたポップアップ関数があれば実行
	tryPopup: function(){
		if(this.funcArray[this.popupkey]){
			 this.funcArray[this.popupkey]();
			 this.popupkey = '';
		}
	}
};

//マーカー管理
MapData.MarkerManager = Class.create();
MapData.MarkerManager.prototype = {
	map:null,
	markers:null,
	onMapFlags:null,
	minLevel:0,
	maxLevel:19,
	
	initialize: function(gmap,minlevel,maxlevel){
		if(gmap){
			this.map = gmap;
		}
		if(minlevel){
			this.minLevel = minlevel;
		}
		if(maxlevel){
			this.maxLevel = maxlevel;
		}
		this.markers = new Object();
		this.onMapFlags = new Object();
    },
	
	clear:function(gmap,minlevel,maxlevel){
		this.hideAllMarkers();
		this.markers = new Object();
		this.onMapFlags = new Object();
	},
	
	addMarkers:function(markerArray,meshcode){
		this.markers[meshcode] = markerArray;
	},
	
	setEnableLevel:function(minlevel,maxlevel){
		this.minLevel = minlevel;
		this.maxLevel = maxlevel;
	},
		
	refresh:function(onRefresh){
		var bounds = this.map.getBounds();
		var zoomlevel = this.map.getZoom();
		var meshSW = new DMap.Meshcode(bounds.getSouthWest());
		var meshNE = new DMap.Meshcode(bounds.getNorthEast());
		
		if(zoomlevel >= this.minLevel 
		&& zoomlevel <= this.maxLevel){
			this.drawMarker(meshSW,meshNE,onRefresh);
		}
		else{
			this.hideAllMarkers();
		}
	},
		
	drawMarker:function(meshSW,meshNE,onReflesh){
		var meshcode;
		//まだ表示していない対象メッシュコードのマーカーを表示する
		var tx,ty;
		for(mx = meshSW.x,tx= meshNE.x;mx <= tx;mx++){
			for(my = meshSW.y,ty=meshNE.y;my <= ty;my++){
				var meshTarget = new DMap.Meshcode();
				meshTarget.x = mx;
				meshTarget.y = my;
				meshcode = meshTarget.meshcode();
				if(!this.onMapFlags[meshcode] && this.markers[meshcode]){
					this.onMapFlags[meshcode] = meshTarget;
					this.showMarkers(this.markers[meshcode],onReflesh);
				}
			}
		}
		
		//表示対象外のマーカーを非表示にする
		
		for(mapFlagindex in this.onMapFlags){
			meshcode = this.onMapFlags[mapFlagindex];
			if(meshcode.x < meshSW.x 
			|| meshcode.x > meshNE.x 
			|| meshcode.y < meshSW.y 
			|| meshcode.y > meshNE.y){
				this.hideMarkers(this.markers[mapFlagindex]);
				delete this.onMapFlags[mapFlagindex];
			}
		}
	},
	
	showMarkers:function(targetMarkers,onReflesh){
		if(!targetMarkers){
			return;
		}
		var i = 0;
		var l = targetMarkers.length;
		var map = this.map;
		setTimeout(function addMarker(){

			if(i >= l){
				if(onReflesh){
					onReflesh();
				}
				return;
			}
			map.addOverlay(targetMarkers[i]);
			i++;
			setTimeout(addMarker,0);
		},0);
	},
	
	hideMarkers:function(targetMarkers){
		if(!targetMarkers){
			return;
		}
		var l
		for(var i=0 ,l = targetMarkers.length;i < l; i++){
			this.map.removeOverlay(targetMarkers[i]);
		}
	},

	hideAllMarkers:function(){
		for(mapFlagindex in this.onMapFlags){
			this.hideMarkers(this.markers[mapFlagindex]);
			delete this.onMapFlags[mapFlagindex];
		}
	}
};

//ライブドア天気管理
MapData.lwwsManager = Class.create();
MapData.lwwsManager.prototype = {
	linkarea:null,
	weatherarea:null,
	backid:null,
	weatherhtml:"",

	initialize:function(linkarea,weatherarea){
		this.linkarea = linkarea;
		this.weatherarea = weatherarea;
		this.backid = null;
		this.weatherhtml = "";
	},
	
	clear:function(){
		this.linkarea.innerHTML = "";
		this.weatherarea.innerHTML = "";
	},
	
	setWeatherInfo:function(damdata){
		if(!damdata.lwws){
			this.clear();
			return;
		}
		var lwwsid = damdata.lwws.pointcode;

		var h = "<a href='" + damdata.lwws.pointURL + "' target='_blank'>";
		h += damdata.lwws.areaname + "(" + damdata.lwws.pointname + ")</a> ";
		h += "-<a href='" + damdata.lwws.municipalityURL + "' target='_blank'>";
		h += "ピンポイント天気 " + damdata.lwws.municipality + "</a><br>";
		this.linkarea.innerHTML = h;
		
		
		//前回取得したIDと同じ場合はキャッシュを返す
		if(lwwsid == this.backid){
			this.weatherarea.innerHTML = this.weatherhtml;
			return;
		}
		else{
			this.weatherarea.innerHTML = "データ取得中です…";
		}

		var url = "dws/lwwsdata.cgi";
		var opt = {
			onComplete:this.displayWeatherInfo.bind(this),
			method: 'get',
			parameters: "id=" + lwwsid
		};
		
		new Ajax.Request(url,opt);
	},
	displayWeatherInfo:function(req){
		this.weatherarea.innerHTML = "";
		var helper = new MapData.Helper();
		var text = helper.safariFilter(req.responseText);

		var response = eval("(" + text  + ")");
		
		this.weatherarea.innerHTML = "";
		this.backid = null;
		this.weatherhtml = "";

		if(response.error){
			return;
		}
		
		var h = "<table align='center'><tbody><tr>";
		h += "<td align='center'>(" + response.weather[0].day + ")" + response.weather[0].telop + "</td>";
		h += "<td align='center'>(" + response.weather[1].day + ")" + response.weather[1].telop + "</td>";
		h += "<td align='center'>(" + response.weather[2].day + ")" + response.weather[2].telop + "</td>";
		h += "</tr>";
		h += "<tr class='weatherimage'>";
		h += "<td align='center'>";
		h += "<img src='" + response.weather[0].imgurl + "'/>";
		h += "</td>";
		h += "<td align='center'>";
		h += "<img src='" + response.weather[1].imgurl + "'/>";
		h += "</td>";
		h += "<td align='center'>";
		h += "<img src='" + response.weather[2].imgurl + "'/>";
		h += "</td>";
		h += "</tr>";
		h += "<tr>";
		h += "<td align='center'>";
		h += "<span style='color: rgb(255, 117, 117);'>" + response.weather[0].tmax + "℃</span>";
		h += "/";
		h += "<span style='color: rgb(0, 182, 242);'>" + response.weather[0].tmin + "℃</span>";
		h += "</td>";
		h += "<td align='center'>";
		h += "<span style='color: rgb(255, 117, 117);'>" + response.weather[1].tmax + "℃</span>";
		h += "/";
		h += "<span style='color: rgb(0, 182, 242);'>" + response.weather[1].tmin + "℃</span>";
		h += "</td>";
		h += "<td align='center'>";
		h += "<span style='color: rgb(255, 117, 117);'>" + response.weather[2].tmax + "℃</span>";
		h += "/";
		h += "<span style='color: rgb(0, 182, 242);'>" + response.weather[2].tmin + "℃</span>";
		h += "</td>";
		h += "</tr>";
		h += "<tr>";
		h += "<td colspan='3' align='left'>";
		h += response.updatedate;
		h += "</td>";
		h += "</tr>";
		h += "</tbody>";
		h += "</table>";

		this.weatherarea.innerHTML = h;
		this.backid = response.id;
		this.weatherhtml = h;
	}
};

MapData.DataManager = Class.create();
MapData.DataManager.prototype = {
	popman: null,
	markerman: null,
	datamesh:null,
	map:null,

	//対象ズームレベル値の設定（継承側でオーバーライドして設定）
	minzoom: 0,
	maxzoom: 19,
	
	
	//コンストラクタ 引数にはMapData.MarkerManagerオブジェクト
	initialize: function(parm){
		this.popman = new MapData.PopupManager();
		this.markerman = null;
		this.map = null;
		this.datamesh = new Array();	//データメッシュ管理用
		this.onInitialize(parm);
    },
	
	clear: function(){
		this.popman.clear();
		this.markerman.clear();
		this.datamesh = new Array();
	},
	
	setGMap:function(map){
		this.map = map;
		this.markerman = new MapData.MarkerManager(map,this.minzoom,this.maxzoom);
	},
	
	//ズームが表示対象かどうか判定
	isZoomrange:function(zoomlevel){
		return (this.minzoom <= zoomlevel && this.maxzoom >= zoomlevel);
	},
	
	//ポップアップさせたいマーカーを識別するキーを設定
	setPopupKey:function(key){
		this.popman.setKey(key);
	},

	//ポップアップ可能ならばポップアップさせる
	tryPopup:function(){
		this.popman.tryPopup();
	},
	
	setEnableLevel:function(minlevel,maxlevel){
		this.minzoom = minlevel;
		this.maxzoom = maxlevel;
		this.markerman.setEnableLevel(minlevel,maxlevel);
	},
	
	//メッシュコードのデータを取得する
	getMeshData:function(mesh){
		//すでに取得済みのデータかチェックする
		if(this.datamesh[mesh.meshcode()] == true){
			return;
		}
		//存在しないのでデータ取得する
		this.datamesh[mesh.meshcode()] = true;
		
		//displayMeshData()をコールバック関数に指定してデータ取得
		var url = this.getRequestUrl(mesh);
		var opt = {
			onComplete:this.displayMeshData.bind(this),
			method: 'get',
			parameters: this.getRequestParm(mesh)
		};

		new Ajax.Request(url,opt);
	},
	
	//データ取得時の処理
	displayMeshData:function(req){
		var helper = new MapData.Helper();
		var text = helper.safariFilter(req.responseText);

		var response = eval("(" + text  + ")");

		if(response.error == 0){
			var meshArray = response.records;
			var l;
			for(var i = 0,l = meshArray.length;i < l ;i++){
				this.registerMarkerManager(this.onRequestSuccess(meshArray[i]));
			}
			this.markerman.refresh(this.popman.tryPopup.bind(this.popman));
		}
	},

	//マーカーをMarkerManagerに登録
	registerMarkerManager:function(returnValue){
		var markerArray = returnValue.records;
		var mesh = returnValue.mesh;
		
		this.markerman.addMarkers(markerArray,mesh);

	},
	
	//初期化処理
	onInitialize:function(){},

	//WebAPIのリクエストURL
	getRequestUrl: function(mesh){},

	//WebAPIのリクエストパラメータ
	getRequestParm: function(mesh){},

	//値取得時の処理
	onRequestSuccess:function(response){}
	
};
//ダムデータ管理クラス
MapData.DamDataManager = Class.create();
MapData.DamDataManager.prototype = Object.extend(new MapData.DataManager(), {

	damIconFactory: null,
	minzoom: 11,
	maxzoom: 19,
	zoommap:null,
	zoommarker:null,
	lwwsman:null,
	specflag:null,
	
	//初期化処理
	onInitialize: function(parm){
		//ズーム用マップオブジェクトを作成する
		this.zoommap = new GMap2(parm.zoommap,{mapTypes:[G_HYBRID_MAP,G_SATELLITE_MAP]});
		this.zoommap.addControl(new GSmallMapControl());
		this.zoommap.addControl(new GMapTypeControl());
		this.zoommap.addControl(new GScaleControl());
		this.zoommap.setCenter(new GLatLng(parm.zoommapy,parm.zoommapx),14,G_HYBRID_MAP);
		
		//天気予報管理オブジェクトを作成する
		this.lwwsman = new MapData.lwwsManager(parm.linkarea,parm.weatherarea);
		
		this.specflag = parm.specflag;
		
	},

	//WebAPIのリクエストURL
	getRequestUrl: function(){
		return "dws/meshdata.cgi";
	},

	getRequestParm: function(mesh){
		//$("debug").innerHTML = "mx=" + mesh.x + "&my=" + mesh.y;
		return "mx=" + mesh.x + "&my=" + mesh.y;
	},

	//値取得時の処理
	onRequestSuccess:function(retvalue){
		var newMarkers = new Array();
		var meshcode = retvalue.mesh;
		var resDams = retvalue.records;
		var l;
		for(var i = 0,l = resDams.length;i < l ;i++){
			if(resDams[i].location){
				newMarkers[newMarkers.length] = this.createMarker(resDams[i]);
			}
		}
		return {mesh:meshcode,records:newMarkers};
	},

	//マーカーを作成
	createMarker: function(damData){
		var damIcon = this.damIconFactory.createIcon(damData);
		var lat = this.hourTohms(damData.location.y);
		var latString = lat.h + "°" + lat.m + "′" + Math.round(lat.s) + "″";
		var lng = this.hourTohms(damData.location.x);
		var lngString = lng.h + "°" + lng.m + "′" + Math.round(lng.s) + "″";
		
		var marker = new GMarker(
			new GLatLng(parseFloat(damData.location.y),parseFloat(damData.location.x)),
			{icon :damIcon,title:damData.name.escapeHTML()});
		var onClick = function() {
			var info;
			if(this.specflag.checked){
				info = "<div id='daminfotable'>";
				info += "<a href='?d=" + damData.damno.escapeHTML() + "'>";
				info += "[" + damData.damno.escapeHTML() + "]";
				info += damData.name.escapeHTML()+ "（" +damData.kana.escapeHTML() + "）";
				info += "／" + damData.prefname.escapeHTML();
				info += "</a>" ;

				info += "<div id='daminfoall'>";
				info += "<table cellspacing='0'>";
				info += "<tr><td class='tabletitle'>所在地</td>";
				info += "<td class='tablevalue' colspan='3'>" + damData.address.escapeHTML();
				if(damData.location.confirmed == 0){
					info += "(位置未確認ダム)";
				}
				info += "</td></tr>";
				info += "<tr><td class='tabletitle'>河川</td>";
				info += "<td class='tablevalue'>" + damData.riverSystem.escapeHTML() + "水系"  + damData.river.escapeHTML() + "</td>";
				info += "<td class='tabletitle'>着手/竣工</td>";
				info += "<td class='tablevalue'>" + damData.syear.escapeHTML() + "/" + damData.cyear.escapeHTML() + "</td></tr>";
				info += "<tr><td class='tabletitle'>目的</td>";
				info += "<td class='tablevalue'>" + damData.purpose.escapeHTML() + "</td>";
				info += "<td class='tabletitle'>形式</td>";
				info += "<td class='tablevalue'>" + damData.type.escapeHTML() +"(" + damData.typecode.escapeHTML() + ")"  + "</td></tr>";
				info += "<tr><td class='tabletitle'>堤高</td>";
				info += "<td class='tablevalue'>" + damData.height.escapeHTML() + "m</td>";
				info += "<td class='tabletitle'>堤頂長</td>";
				info += "<td class='tablevalue'>" + damData.width.escapeHTML() + "m</td></tr>";
				info += "<tr><td class='tabletitle'>総貯水量</td>";
				info += "<td class='tablevalue'>" + damData.capacity.escapeHTML() + "m<sup>3</sup></td>";
				info += "<td class='tabletitle'>有効貯水量</td>";
				info += "<td class='tablevalue'>" + damData.ecapacity.escapeHTML() + "m<sup>3</sup></td></tr>";
				info += "<tr><td class='tabletitle'>ダム事業者</td>";
				info += "<td class='tablevalue'>" + damData.owner.escapeHTML() + "</td>";
				info += "<td class='tabletitle'>本体施工者</td>";
				info += "<td class='tablevalue'>" + damData.builder.escapeHTML() + "</td></tr>";
				info += "<tr><td class='tabletitle'>経緯度</td>";
				info += "<td class='tablevalue'  colspan='3'>" + latString + " " + lngString + "</td></tr>";
				
				if(damData.mmdata.length > 0){
					info += "<tr><td class='tabletitle'>";
					info += "<a href='http://doboku.pekori.jp/wiki.cgi?page=%A5%C0%A5%E0%A4%E1%A4%B0%A4%EA%2F%A4%E2%A4%EA%A4%DF%A4%BA2008' target='_blank'>もりみず情報</a></td>";
					info += "<td class='tablevalue' colspan='3'>";
					for(var i = 0;i < damData.mmdata.length;i++){
						info += damData.mmdata[i].span.escapeHTML() + ":";
						info += damData.mmdata[i].name.escapeHTML() + "<br>";
					}
					info += "</td></tr>";
				}
				info += "</table>";
				info += "<a href='" + damData.url.escapeHTML() + "' target='_blank'>ダム便覧/全項目表 (財団法人 日本ダム協会）</a>";
				info += " <a href='/kml/?d=" + damData.damno.escapeHTML() + "'>GoogleEarth</a><br>";
				info += "<a href='http://damnet.or.jp/cgi-bin/binran/PA.cgi?ban=" + damData.damno.escapeHTML() + "' target='_blank'>ダム便覧/フォトアーカイブス (財団法人 日本ダム協会）</a><br>";
				if(damData.kburl){
					info +="<a href='" + damData.kburl.escapeHTML() + "' target='_blank'>ダム諸量（川の防災情報/試験運用中）</a><br>";
				}
				info += "</div>";
				info += "</div>";
			}
			else{
				info = "<div id='daminfotable'>";
				info += "<a href='?d=" + damData.damno.escapeHTML() + "'>";
				info += "[" + damData.damno.escapeHTML() + "]";
				info += damData.name.escapeHTML()+ "（" +damData.kana.escapeHTML() + "）";
				info += "／" + damData.prefname.escapeHTML();
				info += "</a>" ;

				info += "<div id='daminfoall'>";
				info += "<table cellspacing='0'>";
				info += "<tr><td class='tabletitle'>所在地</td>";
				info += "<td class='tablevalue' colspan='3'>" + damData.address.escapeHTML();
				if(damData.location.confirmed == 0){
					info += "(位置未確認ダム)";
				}
				info += "</td></tr>";
				info += "<tr><td class='tabletitle'>河川</td>";
				info += "<td class='tablevalue'>" + damData.riverSystem.escapeHTML() + "水系"  + damData.river.escapeHTML() + "</td>";
				info += "<td class='tabletitle'>着手/竣工</td>";
				info += "<td class='tablevalue'>" + damData.syear.escapeHTML() + "/" + damData.cyear.escapeHTML() + "</td></tr>";
				info += "<tr><td class='tabletitle'>堤高</td>";
				info += "<td class='tablevalue'>" + damData.height.escapeHTML() + "m</td>";
				info += "<td class='tabletitle'>形式</td>";
				info += "<td class='tablevalue'>" + damData.type.escapeHTML() +"(" + damData.typecode.escapeHTML() + ")"  + "</td></tr>";
				info += "<tr><td class='tabletitle'>経緯度</td>";
				info += "<td class='tablevalue'  colspan='3'>" + latString + " " + lngString + "</td></tr>";
				if(damData.mmdata.length > 0){
					info += "<tr><td class='tabletitle'>";
					info += "<a href='http://doboku.pekori.jp/wiki.cgi?page=%A5%C0%A5%E0%A4%E1%A4%B0%A4%EA%2F%A4%E2%A4%EA%A4%DF%A4%BA2008' target='_blank'>もりみず情報</a></td>";
					info += "<td class='tablevalue' colspan='3'>";
					for(var i = 0;i < damData.mmdata.length;i++){
						info += damData.mmdata[i].span.escapeHTML() + ":";
						info += damData.mmdata[i].name.escapeHTML() + "<br>";
					}
					info += "</td></tr>";
				}
				info += "</table>";
				info += "<a href='" + damData.url.escapeHTML() + "' target='_blank'>ダム便覧/全項目表 (財団法人 日本ダム協会）</a>";
				info += " <a href='/kml/?d=" + damData.damno.escapeHTML() + "'>GoogleEarth</a><br>";
				info += "<a href='http://damnet.or.jp/cgi-bin/binran/PA.cgi?ban=" + damData.damno.escapeHTML() + "' target='_blank'>ダム便覧/フォトアーカイブス (財団法人 日本ダム協会）</a><br>";
				if(damData.kburl){
					info +="<a href='" + damData.kburl.escapeHTML() + "' target='_blank'>ダム諸量（川の防災情報/試験運用中）</a><br>";
				}
				info += "</div>";
				info += "</div>";
				
			}
			//拡大地図にダムを表示する
			this.zoommap.setCenter(new GLatLng(damData.location.y,damData.location.x),14,G_HYBRID_MAP);
			
			this.map.panTo(new GLatLng(damData.location.y,damData.location.x));
			marker.openInfoWindowHtml(info);
			document.title = "DamMaps - " + damData.name.escapeHTML()+ "（" +damData.kana.escapeHTML() + "）";
			this.lwwsman.setWeatherInfo(damData);
		}
		
		GEvent.addListener(marker, "click",onClick.bind(this));

		var onInfowindowOpen = function(){
			this.zoommarker = new GMarker(new GLatLng(damData.location.y,damData.location.x));
			this.zoommap.addOverlay(this.zoommarker);
		};
		GEvent.addListener(marker, "infowindowopen",onInfowindowOpen.bind(this));
		
		var onInfowindowClose = function(){
			this.zoommap.clearOverlays();
			document.title = "DamMaps - 日本全国Web地図でダムめぐり";
		};
		GEvent.addListener(marker, "infowindowclose",onInfowindowClose.bind(this));

		this.popman.setFunction(damData.damno,onClick.bind(this));
		return marker;
	},

	hourTohms:function(hour){
		var h = Math.floor(hour);
		var m = Math.floor((hour - h) * 60);
		var s = Math.floor((hour - h - m * (1/60)) * 3600 * 10) / 10;
		if(Math.floor(s) == s){
			s = s + ".0";
		}
		return {"hour":hour,
				"h":h,
				"m":m,
				"s":s};
	},
	
	//表示アイコンを生成するオブジェクトを設定する
	setDamIconFactory:function(iconFactory){
		this.damIconFactory = iconFactory;
	}
});



