/*
 *
 * 以下のように使用します
 *---------------------------------------------------------------------------------------
<html>
<head>
  <script src="http://maps.google.com/maps?file=api&v=2&key=<Google Maps API key>"
	type="text/javascript">
  </script>
  <script type="text/javascript">
  <!--//--><![CDATA[//><!--
	var use_onload=true;
	var plot_mode=1;  // 省略可能
	var user_list = [ 'foo', 'bar' ]; // 省略可能
	var trace_user = 'foo'; // 省略可能
  //--><!]]>
  </script>
  <script src="/static/script.js" type="text/javascript">
  </script>
</head>
<body>
<div id="map" style="width:400px; height:400px"></div>
</body>
</html>

 *---------------------------------------------------------------------------------------
 * HTML内のJavaScriptで上書き可能な設定は以下の通り
 * 
 * var use_onload=true;	// これを定義しないと地図は表示されません。
 *						// 地図は表示しないけど関数を使いたい時などは定義しないかfalseを設定します
 * var plot_mode = 1;	// 定義しないor0のとき軌跡をプロットしません
 *						// 1のとき点でプロットします。
 *						//  １ユーザーあたり1000ポイント(plot_countで指定可能)まで描画します。
 *						//  それ以上になったら古いほうから消えていきます
 *						// 2のとき線で描画します。
 *						//  線の場合すべて描画するので長時間表示するとブラウザが重くなることがあります
 * var plot_count = 1000; // 点の最大数を指定します。
 * var user_list = [ 'foo', 'bar' ];
 *						// プロットするユーザーを配列で指定します。'all'を指定すると全員表示します。
 * var trace_user = 'foo';
 *						// 追いかけるユーザーを指定します。
 *						// 未指定にしたい場合は'__nouser__'、全員を表示したい場合は'all'を指定します
 * var map_maximize = 0;	// 地図をブラウザサイズまで最大化する場合1。divのstyleに従う場合は0です。デフォルトは0です。
 * var use_osm = 0;		// OpenStreetMapの地図レイヤーを選択可能にする場合1、しない場合0です。デフォルトは0です。
 * var use_minimap = 1;	// OverviewMap(右下の小さい地図)を表示する場合1、しない場合0です。デフォルトは1です。
 * var use_zoom = 1;	// LargeMapControl(縮尺変更コントロール)を表示する場合1、しない場合0です。デフォルトは1です。
 * var map_region = [  { 'lat':35.951329861522666, 'lon':139.01275634765625 }, 
 *						{ 'lat':35.26580442886754, 'lon':140.25283813476562 },
 *						{ 'lat':35.266925688950074, 'lon':139.04983520507812 },
 *						{ 'lat':35.968003617226884, 'lon':140.21575927734375 }
 *					];
 *						// 地図の初期表示を指定したポイントがすべて表示される位置＆縮尺に設定します。
 *						// 未指定の場合、東京タワーを中心とした地図が表示されます。
 * var group_name = 'group名';	// 指定した場合グループ表示になります。user_listの内容は無視されます。
 */

//グローバル変数
var map;
var markeropts;
var share_markers = new Array();

var zoomFactor = 2;
var numLevels = 18;
var baseDistance = 500000;
var segments;

var hidelist = 0;
var plotmode = 0;	// 0=軌跡表示しない、1=点、2=線
var plotcount = 1000;
var traceuser = '';
var center;
var group_revision = '';

var prev_trace = "";
var levels0 = encodeNumber(numLevels);

var static_file_site = 'http://imakoko.alkn.net/img';
var screen_name_site = 'http://www.fujita-lab.com/imakoko';
var subdirectory = "";
var extension = '.php';

var timer;

var iconImage = [
	{ 'path':'/car', 'direction': true, 'ext':'.png', 'w':32, 'h':32, 'ax':16, 'ay':16, 'wax':16, 'way':10,
		'path2':'/middle_arrow/arrow-', 'w2':52, 'h2':52, 'ax2':26, 'ay2':26, 'wax2':26, 'way2':20 },
	{ 'path':'/keitai', 'direction': false, 'ext':'.png', 'w':20, 'h':45, 'ax':10, 'ay':23, 'wax':10, 'way':18 },
	{ 'path':'http://maps.google.co.jp/mapfiles/ms/icons/plane', 'direction': false, 'ext':'.png', 'w':32, 'h':32, 'ax':16, 'ay':16, 'wax':16, 'way':16 },
	{ 'path':'/train', 'direction': false, 'ext':'.png', 'w':55, 'h':45, 'ax':28, 'ay':23, 'wax':28, 'way':19 },
	{ 'path':'/shinkansen', 'direction': false, 'ext':'.png', 'w':44, 'h':42, 'ax':22, 'ay':21, 'wax':22, 'way':17 },
	{ 'path':'http://maps.google.co.jp/mapfiles/ms/icons/bus', 'direction': false, 'ext':'.png', 'w':32, 'h':32, 'ax':16, 'ay':16, 'wax':16, 'way':16 },
	{ 'path':'http://maps.google.co.jp/mapfiles/ms/icons/cycling', 'direction': false, 'ext':'.png', 'w':32, 'h':32, 'ax':16, 'ay':16, 'wax':16, 'way':16 },
	{ 'path':'http://maps.google.co.jp/mapfiles/ms/icons/hiker', 'direction': false, 'ext':'.png', 'w':32, 'h':32, 'ax':16, 'ay':16, 'wax':16, 'way':16 },
	{ 'path':'http://maps.google.co.jp/mapfiles/ms/icons/motorcycling', 'direction': false, 'ext':'.png', 'w':32, 'h':32, 'ax':16, 'ay':16, 'wax':16, 'way':16 },
	{ 'path':'http://maps.google.co.jp/mapfiles/ms/icons/helicopter', 'direction': false, 'ext':'.png', 'w':32, 'h':32, 'ax':16, 'ay':16, 'wax':16, 'way':16 },
	{ 'path':'http://maps.google.co.jp/mapfiles/ms/icons/ferry', 'direction': false, 'ext':'.png', 'w':32, 'h':32, 'ax':16, 'ay':16, 'wax':16, 'way':16 },
];



// 移動したかどうかをチェックする(1m以上移動したかどうか)
function checkMoving(lat_from, lon_from, lat_to, lon_to)
{
	var from = new GLatLng(lat_from, lon_from);
	var to = new GLatLng(lat_to, lon_to);
	return to.distanceFrom(from) > 1;
}

// グローバル変数が定義済みかどうか
// objを指定すると、obj.vが定義済みかどうかを判定
// 指定がない場合はwindow.v(グローバル変数v)が定義済みかどうかを判定
function isDefined(v, obj)
{
	if (obj == undefined) {
		obj = 'window';
	}
	var ret = typeof(eval(obj)[v]) != 'undefined';
//	alert('variable ' + obj + '.' + v + ' is ' + (ret ? 'defined' : 'undefined'));
	return ret;
}

// メッセージ出力
function setMessage(mesg)
{
	var msg = document.getElementById('msg');
	if (msg)
	{
		msg.innerHTML = mesg;
	}
}

// -------------------------------------------
//  GoogleMap関連関数
// -------------------------------------------
// Encode a signed number in the encode format.
function encodeSignedNumber(num) {
	var sgn_num = num << 1;
	if (num < 0)
	{
		sgn_num = ~(sgn_num);
	}
	return(encodeNumber(sgn_num));
}

// Encode an unsigned number in the encode format.
function encodeNumber(num)
{
	var encodeString = "";
	while (num >= 0x20)
	{
		encodeString += (String.fromCharCode((0x20 | (num & 0x1f)) + 63));
		num >>= 5;
	}
	encodeString += (String.fromCharCode(num + 63));
	return encodeString;
}

// 線を延長する
// user = ユーザー
// latlng = 追加するポイント
function createEncodedPolyline(user, latlng)
{
	_createEncodedPointsLevels(user, latlng, true);
	return GPolyline.fromEncoded( {
		"color": user.linecolor,
		"weight": user.linewidth,
		"opacity": user.transparent,
		"points": user.points,
		"levels": user.levels,
		"zoomFactor": zoomFactor,
		"numLevels": numLevels
		} );
}

function _createEncodedPointsLevels(user, latlng, last_point)
{
	// レベルグループ 0 をデフォルトとする。
	var level = numLevels - 1;

	// それぞれレベルグループに於いて、定めた距離を超えた時に点を打つようにする。
	// その距離を計るために、最後に打った点を覚えておくための変数。
	if (!user.lastGlatlng[0])
	{
		for (var z = 0; z < numLevels; z++)
		{
			user.lastGlatlng[z] = latlng;
		}
	}
	else
	{
		for (var z = numLevels - 1 ; 0 <= z  ; --z)
		{
			var distance = latlng.distanceFrom(user.lastGlatlng[z]);
			if( segments[z] < distance )
			{
				level = numLevels - 1 - z;
				user.lastGlatlng[z] = latlng;
			}
		}
	}

	// エンコード
	var late5 = Math.floor(latlng.lat() * 1e5);
	var lone5 = Math.floor(latlng.lng() * 1e5);
	var dlat = late5 - user.plat;
	var dlon = lone5 - user.plon;
	user.plat = late5;
	user.plon = lone5;
	var points = encodeSignedNumber(dlat) + encodeSignedNumber(dlon);
	var level = encodeNumber(numLevels-1 /*level*/);

	if (last_point)
	{
		if (user.levels.length > 0)
		{
			user.levels = user.levels.substr(0, user.levels.length - levels0.length);
			user.levels += user.last_level;
		}
		user.last_level = level;
		level = levels0;
	}
	user.levels += level;
	user.points += points;
}

// 現在時刻文字列作成
function makeTimeString()
{
	var mySysDate = new Date();
	var myYear = mySysDate.getFullYear();
	var myMonth = mySysDate.getMonth()+1;
	var myDate = mySysDate.getDate();
	var myHour = mySysDate.getHours();
	var myMin = mySysDate.getMinutes();
	var mySec = mySysDate.getSeconds();
	if (myMonth < 10) { myMonth = "0" + myMonth; }
	if (myDate < 10) { myDate = "0" + myDate; }
	if (myHour < 10) { myHour = "0" + myHour; }
	if (myMin < 10) { myMin = "0" + myMin; }
	if (mySec < 10) { mySec = "0" + mySec; }
	return myYear + '-' + myMonth + '-' + myDate + ' ' + myHour + ':' + myMin + ':' + mySec;
}

// マーカーを消す
function removeUserMarker(user)
{
	if (typeof(user.prev_marker) != 'undefined')
	{
		map.removeOverlay(user.prev_marker);
		user.prev_marker = undefined;
	}
	if (user.prev_marker2 != undefined)
	{
		map.removeOverlay(user.prev_marker2);
	}
	if (user.polyline != undefined)
	{
		map.removeOverlay(user.polyline);
	}
	while (user.track.length > 0) {
		var mk = user.track.shift();
		map.removeOverlay(mk);
	}
}


// 現在地アイコンの作成
function makeDirectionIcon(td, userinfo)
{
	var ic = new GIcon();
	var icm;

	if (iconImage[userinfo.type])
	{
		icm = iconImage[userinfo.type];
	}
	else
	{
		icm = iconImage[0];
	}

	if (!isNaN(td) && icm.direction)
	{
		// 方位に合わせたアイコン
		if (userinfo.ustream_status == 'live')
		{
			ic.image = static_file_site + icm.path2 + String(parseInt(td)) + "_ust" + icm.ext;
		}
		else
		{
			ic.image = static_file_site + icm.path2 + String(parseInt(td)) + icm.ext;
		}
		ic.iconSize = new GSize(icm.w2, icm.h2);
		ic.iconAnchor = new GPoint(icm.ax2, icm.ay2);
		ic.infoWindowAnchor = new GPoint(icm.wax2, icm.way2);
	}
	else
	{
		if (icm.path.substr(0,7) == "http://") {
			ic.image = icm.path + icm.ext;
		} else {
			ic.image = static_file_site + icm.path + icm.ext;
		}
		ic.iconSize = new GSize(icm.w, icm.h);
		ic.iconAnchor = new GPoint(icm.ax, icm.ay);
		ic.infoWindowAnchor = new GPoint(icm.wax, icm.way);
	}
	return ic;
}

// マーカー
function createClickableMarker(pt, opts, username)
{
	var mk = new GMarker(pt, opts);
	mk.user = username; // イベントで使う
	// 現在時刻（情報ウィンドウ内に表示）
	mk.plottime = makeTimeString();

	// 情報ウィンドウを閉じたときのイベント
	GEvent.addListener(mk, 'infowindowclose', function()
	{
		mk.hasInfoWindow = false;
		setTraceUser(prev_trace);
		prev_trace = "";
	});

	// マーカーをクリックしたときのイベント
	GEvent.addListener(mk, 'click', function()
	{
		var txt = "";
		if (!users[mk.user].user_info || users[mk.user].user_info == "") {
			// ユーザー情報がなければサーバからとってくる
			var req = GXmlHttp.create();
			req.open("GET", subdirectory + "/api/getuserinfo" + extension + "?user=" + mk.user +"&t="+ new Date().getTime() , false);
			req.send("");
			if (req.status == 200 && req.responseText != "")
			{
				var res = eval(req.responseText);
				// 情報ウィンドウ内のHTML
				if (res && res.result)
				{
					txt = "<div style='width:140px; height:48px;'>" +
						"<div>" + mk.user + "<br>最終表示時刻 <span id='plot_time'>" + mk.plottime + "</span></div>" +
						"<hr>" +
						"<div><a href='" + res.url + "'>User Web</a>" +
						"</div>";
						users[mk.user].user_info = txt;
				}
				else
				{
					txt = "<div style='width:120px; height:60px;'>" +
						"<div id='plot_time'>" + mk.plottime + "</div>" +
						"</div>";
				}
			}
			else
			{
				txt = "情報の取得に失敗しました";
			}
		}
		else
		{
			txt = users[mk.user].user_info;
		}

		for (var user in users)
		{
			if (users[user].prev_marker)
			{
				users[user].prev_marker.hasInfoWindow = false;
			}
		}

		users[mk.user].prev_marker.hasInfoWindow = true;
		users[mk.user].prev_marker.openInfoWindowHtml(txt);
		if (prev_trace == "")
		{
			prev_trace = traceuser;
		}
		setTraceUser(mk.user, 14);
	});
	return mk;
}

function createSharedMarker(pt, key, desc)
{
	var marker = new GMarker(pt);
	GEvent.addListener(marker, 'click', function()
		{
			updateOff();
			marker.openInfoWindowHtml('<div><pre>' + desc + '</pre></div><hr>');
		}
	);
	GEvent.addListener(marker, 'infowindowclose', function()
		{
			updateOn();
		}
	);
	return marker;
}

// 地図のスクロールとマーキング
function update() 
{
	if (!isDefined('group_name'))
	{
		// 位置情報を取得するユーザー
		var ul = "";
		if (isDefined('user_list') && user_list[0] == 'all')
		{
			ul = 'all,';
		}
		else
		{
			for (var user in users)
			{
				if (users[user].watch)
				{
					ul += user + ",";
				}
			}
		}
		if (ul == "")
		{
			return false;
		}
		ul = 'user=' + ul.substr(0, ul.length-1);
	}
	else
	{
		ul = 'group=' + group_name;
		if (group_revision != "")
		{
			ul += ('&revision=' + group_revision);
		}
	}
	// 位置情報を取得する
	var request = GXmlHttp.create();
	request.open("GET", subdirectory + "/api/latest" + extension + "?"+ ul + "&for_top=0&t="+ new Date().getTime() , true);
	request.onreadystatechange = function() 
	{
		if (request.readyState == 4) 
		{
			if (request.status != 200 || request.responseText == "")
			{
				return false;
			}
			var d = eval(request.responseText);
			if (!d) {
				// update();
				return false;
			}

			if (!d.result)
			{
				clearInterval(timer);
				alert(d.errmsg);
				return false;
			}

			// 全体を表示するための範囲情報
			var min_lat = 91;
			var min_lon = 181;
			var max_lat = -91;
			var max_lon = -181;
			var valid_users = 0;

			// 共有マーカー表示
			if (d.group_updated == undefined || d.group_updated)
			{
				if (d.group_revision != undefined)
				{
					group_revision = d.group_revision;
				}
				if (d.group)
				{
					for (var idx in share_markers)
					{
						share_markers[idx].valid = false;
					}
					for (var grp=0; grp<d.group.length; grp++)
					{
						var key = d.group[grp].key;
						if (share_markers[key] == undefined)
						{
							share_markers[key] = new Object();
							share_markers[key].marker = createSharedMarker(new GLatLng(d.group[grp].lat, d.group[grp].lon), key, d.group[grp].desc)
							map.addOverlay(share_markers[key].marker);
						}
						share_markers[key].valid = true;
					}
					for (var idx in share_markers)
					{
						if (!share_markers[idx].valid)
						{
							map.removeOverlay(share_markers[idx].marker);
							delete share_markers[idx];
						}
					}
				}
			}
			for (var key in share_markers)
			{
				var lat = parseFloat(share_markers[key].marker.getLatLng().lat());
				var lon = parseFloat(share_markers[key].marker.getLatLng().lng());
				if (lat < min_lat) { min_lat = lat; }
				if (max_lat < lat) { max_lat = lat; }
				if (lon < min_lon) { min_lon = lon; }
				if (max_lon < lon) { max_lon = lon; }
				valid_users++;
			}

			for (var u in users)
			{
				users[u].update = false;
			}
			// 全員分ループ
			for (var i=0; i<d.points.length; i++)
			{
				var username = d.points[i].user;
				if (!isDefined(username, 'users'))
				{
					initUser(username, true);
				}

				users[username].update = true;

				// ステータス表示
				var el = document.getElementById('status_' + username);
				if (el)
				{
					el.className = (d.points[i].valid ? 'active' : 'inactive');
				}

				// データがあるか
				if (!d.points[i].valid)
				{
					removeUserMarker(users[username]);
					continue;
				}

				// 位置・方位
				var lat = parseFloat(d.points[i].lat);
				var lon = parseFloat(d.points[i].lon);
				var td = parseFloat(d.points[i].dir);

				// 無効なデータかどうか
				if (lat == 0 && lon == 0) { continue; }

				var user = users[username];

				// 前回の座標と違った場合はプロットする
				if (checkMoving(user.lat, user.lon, lat, lon))
				{
					// 現在位置に置くマーカー
					var opts = new Object();
					opts.icon = makeDirectionIcon(td, d.points[i]);
					opts.title = username;

					// 現在位置マーカー
					var pt = new GLatLng(lat, lon);
					var mk = createClickableMarker(pt, opts, username);

					// ニックネームのマーカー
					var mk1 = new GMarker(pt, user.user_markeropts);

					// 前回配置したニックネームマーカーを削除
					if (user.prev_marker2 != undefined)
					{
						map.removeOverlay(user.prev_marker2);
					}

					var hasInfoWindow = false;
					var prev_trace_tmp = prev_trace;
					var current_trace = traceuser;
					if (user.prev_marker != undefined)
					{
						// 情報ウィンドウを持っていたかどうか
						hasInfoWindow = user.prev_marker.hasInfoWindow ? user.prev_marker.hasInfoWindow : false;

						if (plotmode == 1)
						{
							// 描画モードが点
							// ひとつ前の場所に点を打つ
							var mk2 = new GMarker(user.prev_point, user.markeropts);
							map.addOverlay(mk2);
							user.track.push(mk2);

							// プロット数を制限する
							if (user.track.length > plotcount) {
								mk2 = user.track.shift();
								map.removeOverlay(mk2);
							}
						}
						else if (plotmode == 2)
						{
							// 描画モードが線
							// 前のラインを削除
							map.removeOverlay(user.polyline);
						}
						// 一つ前の現在位置マーカーを削除
						map.removeOverlay(user.prev_marker);
					}

					if (plotmode == 2)
					{
						// 描画モードが線
						// 新しくラインを描画
						pl = createEncodedPolyline(user, pt);
						map.addOverlay(pl);
						user.polyline = pl;
					}
					// 新たに現在位置マーカーとニックネームマーカーを描画
					map.addOverlay(mk);
					map.addOverlay(mk1);

					if (hasInfoWindow)
					{
						// 情報ウィンドウを再表示する
						mk.openInfoWindowHtml(user.user_info);
						mk.hasInfoWindow = true;
						var t = document.getElementById('plot_time');
						if (t) {
							t.innerHTML = mk.plottime;
						}
						prev_trace = prev_trace_tmp;
						setTraceUser(current_trace);
					}

					// 次回のためにマーカーと位置情報を保存
					user.prev_marker = mk;
					user.prev_marker2 = mk1;
					user.prev_point = pt;
					user.lat = lat;
					user.lon = lon;

					if (user.trace)
					{
						// 注目しているユーザーに移動
						map.panTo(pt);
						center = map.getCenter();
					}
				}
				if (lat < min_lat) { min_lat = lat; }
				if (max_lat < lat) { max_lat = lat; }
				if (lon < min_lon) { min_lon = lon; }
				if (max_lon < lon) { max_lon = lon; }
				valid_users++;
			}

			for (var u in users)
			{
				if (!users[u].update)
				{
					removeUserMarker(users[u]);
				}
			}

			if (traceuser == 'all' && valid_users > 0)
			{
				var avg_lat = (min_lat + max_lat) / 2;
				var avg_lon = (min_lon + max_lon) / 2;
				var ct = new GLatLng(avg_lat, avg_lon);
				if (valid_users == 1)
				{
					map.setCenter(ct, 14);
				}
				else
				{
					// 全体が表示できる矩形座標を計算
					var region = new GLatLngBounds(new GLatLng(min_lat, min_lon), new GLatLng(max_lat, max_lon));
					// 全体が表示できるように位置とズームを設定
					map.setCenter(ct, map.getBoundsZoomLevel(region));
				}
				center = ct;
			}
		}
	}
	request.send("");
	return false;
}

// プロットのON/OFFの切り替え
function getCheck(obj)
{
	var user = users[obj.id.substr(3)];
	if (user) {
		user.watch = obj.checked;
		if (!obj.checked && user.prev_marker) {
			map.removeOverlay(user.prev_marker);
			user.prev_marker = null;
		}
	}
}

// 注目するユーザーを設定
function setTraceUser(username, magnify)
{
	// まず全員のフラグをクリア
	for (var user in users)
	{
		users[user].trace = false;
	}

	if (username != '__nouser__' && isDefined(username, 'users'))
	{
//		alert("setTraceUser("+username+") user found");
		// 引数のユーザーがいた
		var user = users[username];
		user.trace = true;
		if (user.lat != 0 && user.lon != 0)
		{
			if (magnify != undefined)
			{
				map.setCenter(new GLatLng(user.lat, user.lon), magnify);
			}
			else
			{
				map.panTo(new GLatLng(user.lat, user.lon));
			}
			center = map.getCenter();
		}
	}
	var sel = document.getElementById("traceuser");
	if (sel) {
		for (var idx = 0; idx < sel.length; idx++)
		{
			if (sel.options[idx].value == username)
			{
				sel.options.selectedIndex = idx;
			}
		}
	}
	traceuser = username;
}

// 描画モードを設定
function setPlotMode(mode)
{
	plotmode = mode;
	var trace = '';
	for (user in users) {
		if (users[user].trace) {
			trace = user;
		}
		initUser(user, users[user].watch);
	}
	if (trace != '') {
		users[trace].trace = true;
	}
	map.clearOverlays();
	return false;
}

// ユーザー一覧をサーバから取得する
function loadUserList(watch)
{
	var request = GXmlHttp.create();
	request.open("GET", subdirectory + "/api/user_list" + extension + "?id="+ new Date().getTime() , false);
	request.send("");
	if (request.readyState == 4) 
	{
		if (request.status != 200 || request.responseText == "")
		{
			return false;
		}
		var d = eval(request.responseText);
		if (!d) {
			// loadUserList();
			return false;
		}
		if (d.result)
		{
			var sel = document.getElementById("traceuser");
			if (sel)
			{
				sel.length = 2;
				sel.options[0].value = '__nouser__';
				sel.options[0].text = "注目しない";
				sel.options.selectedIndex = 0;
				sel.options[1].value = 'all';
				sel.options[1].text = '全体';
			}
			var list = "";
			for (var i=0; i<d.list.length; i++)
			{
				var username = d.list[i].user;
				if (!users[username])
				{
					initUser(username, watch);
				}

				if (sel)
				{
					sel.length++;
					sel.options[sel.length-1].value = username;
					sel.options[sel.length-1].text = username;
				}
				list += "<span id=\"status_" + username + "\">" + username + "</span><br>";
			}
			var p = document.getElementById("userlist");
			if (p) {
				p.innerHTML = list;
			}
		}
	}
	return false;
}

function getGroupUser(groupid)
{
	var request = GXmlHttp.create();
	request.open("GET", subdirectory + "/api/getgroupinfo" + extension + "?group="+ groupid + "&t=" + new Date().getTime() , false);
	request.send("");
	if (request.readyState == 4) 
	{
		if (request.status != 200 || request.responseText == "")
		{
			return false;
		}
		var d = eval(request.responseText);
		if (!d) {
			return false;
		}
		if (d.result)
		{
			user_list = d.users;
		}
	}
	return false;
}


// ユーザー情報を初期化
function initUser(username, flag)
{
	if (username)
	{
		var icon = new GIcon();
		icon.image = screen_name_site + "/user/" + encodeURIComponent(username) + ".png";
		icon.iconAnchor = new GPoint(0, 24);

		var mo = new Object();
		mo.icon = icon;
		mo.clickable = false;

		user = new Object();
		user.lat = 0;
		user.lon = 0;
		user.markeropts = markeropts;
		user.user_markeropts = mo;
		user.linecolor = '#FF0000';
		user.linewidth = 2;
		user.transparent = 0.8;
		user.watch = flag;
		user.trace = false;
		user.track = new Array();
		user.lastGlatlng = new Array(numLevels);
		user.plat = 0;
		user.plon = 0;
		user.points = "";
		user.levels = "";
		user.level_len = 0;
		user.last_level = "";
		user.update = false;
		users[username] = user;
	}
}

// 地図の大きさを変える
function setMapSize(w, h)
{
	var d = document.getElementById("map");
	if (d && d.style)
	{
		var center = map.getCenter();
		d.style.width = w;
		d.style.height = h;
		map.checkResize();
		map.panTo(center);
	}
	return false;
}

//----------------------------------------------- get_browser_width
function get_browser_width()
{
	if ( window.innerWidth )
	{
		return window.innerWidth;
	}
	else if ( document.documentElement && document.documentElement.clientWidth != 0 )
	{
		return document.documentElement.clientWidth;
	}
	else if ( document.body )
	{
		return document.body.clientWidth;
	}
	return 0;  
}

//----------------------------------------------- get_browser_height
function get_browser_height()
{
	if ( window.innerHeight )
	{
		return window.innerHeight;
	}
	else if ( document.documentElement && document.documentElement.clientHeight != 0 )
	{
		return document.documentElement.clientHeight;
	}
	else if ( document.body )
	{
		return document.body.clientHeight;
	}
	return 0;
}

function resize()
{
	var winWidth = get_browser_width();
	var winHeight = get_browser_height();
	var map_div = document.getElementById("map");
	if (map_div && map_div.style)
	{
		map_div.style.width = (winWidth - 20) + "px";
		if (hidelist)
		{
			map_div.style.height = (winHeight - 40) + "px";
		}
		else
		{
			map_div.style.height = (winHeight - 0) + "px";
		}
	}
	if( map )
	{
		map.checkResize();
		map.panTo(center);
	}
}

function updateOff()
{
	if (prev_trace == "")
	{
		prev_trace = traceuser;
		setTraceUser('__nouser__');
	}
}

function updateOn()
{
	if (prev_trace != "")
	{
		setTraceUser(prev_trace);
		prev_trace = "";
	}
}

function CancelEvent(event)
{
	e = event;
	if (typeof e.preventDefault  == 'function') 
		e.preventDefault();
	if (typeof e.stopPropagation == 'function')
		e.stopPropagation();
	if (window.event) {
		window.event.cancelBubble = true; // for IE
		window.event.returnValue = false; // for IE
	}
}

function SignatureBox() {} 
SignatureBox.prototype = new GControl();
SignatureBox.prototype.initialize = function(map) 
{
	container = document.createElement("div"); 
	container.style.border = "0px"; 
	container.style.padding = "0px 0px 0px 0px"; 
	container.style.textAlign = "center"; 
	container.innerHTML = '<a href="http://imakoko-gps.appspot.com/" target="_blank"><img src="http://www.fujita-lab.com/imakoko/imakoko.png" height="33" width="114" border="0"></a>'; 

	map.getContainer().appendChild(container); 
	return container; 
}

SignatureBox.prototype.getDefaultPosition = function() 
{ 
	return new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(2, 34)); 
}

function initialize()
{
	if (GBrowserIsCompatible())
	{
		// 地図を最大化するかどうか
		if (isDefined('map_maximize') && map_maximize)
		{
			window.onresize = function()
			{
				resize();
			}
			resize();
		}

		// 地図レイヤーの種類
		var myMapTypes = [];
		myMapTypes.push(G_NORMAL_MAP);
		myMapTypes.push(G_SATELLITE_MAP);
		myMapTypes.push(G_HYBRID_MAP);
		myMapTypes.push(G_PHYSICAL_MAP);

		// OpenStreetMapレイヤーを使うかどうか
		if (isDefined('use_osm') && use_osm) {
			var copyOSM = new GCopyrightCollection("<a href=\"http://www.openstreetmap.org/\">OpenStreetMap</a>");
			copyOSM.addCopyright(new GCopyright(1, new GLatLngBounds(new GLatLng(-90,-180), new GLatLng(90,180)), 0, " "));

			var tilesMapnik     = new GTileLayer(copyOSM, 1, 17, {tileUrlTemplate: 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png'});
			var tilesOsmarender = new GTileLayer(copyOSM, 1, 17, {tileUrlTemplate: 'http://tah.openstreetmap.org/Tiles/tile/{Z}/{X}/{Y}.png'});

			var mapMapnik     = new GMapType([tilesMapnik],     G_NORMAL_MAP.getProjection(), "Mapnik");
			var mapOsmarender = new GMapType([tilesOsmarender], G_NORMAL_MAP.getProjection(), "Osmarend");
			myMapTypes.push(mapMapnik);
			myMapTypes.push(mapOsmarender);
		}

		// 地図オブジェクトの作成
		map = new GMap2(document.getElementById("map"), { mapTypes: myMapTypes });

		// ズームコントロールを使うか
		if (!isDefined('use_zoom') || use_zoom) {
			map.addControl(new GLargeMapControl());
			map.enableContinuousZoom();
			map.enableDoubleClickZoom();
			map.enableScrollWheelZoom();
			GEvent.addDomListener(map, "DOMMouseScroll", CancelEvent); // Firefox
			GEvent.addDomListener(map, "mousewheel",     CancelEvent); // IE
		}
		map.addControl(new GMapTypeControl());
		map.addControl(new GScaleControl());

		if (!isDefined('use_minimap') || use_minimap)
		{
			map.addControl(new GOverviewMapControl());
		}

		// 今ココなう！アイコン表示
		map.addControl(new SignatureBox());

		if (isDefined('map_region'))
		{
			var min_lat = 91;
			var min_lon = 181;
			var max_lat = -91;
			var max_lon = -181;

			for (var idx in map_region)
			{
				if (map_region[idx].lat < min_lat) { min_lat = map_region[idx].lat; }
				if (max_lat < map_region[idx].lat) { max_lat = map_region[idx].lat; }
				if (map_region[idx].lon < min_lon) { min_lon = map_region[idx].lon; }
				if (max_lon < map_region[idx].lon) { max_lon = map_region[idx].lon; }
			}
			var avg_lat = (min_lat + max_lat) / 2;
			var avg_lon = (min_lon + max_lon) / 2;
			var ct = new GLatLng(avg_lat, avg_lon);
			// 全体が表示できる矩形座標を計算
			var region = new GLatLngBounds(new GLatLng(min_lat, min_lon), new GLatLng(max_lat, max_lon));
			// 全体が表示できるように位置とズームを設定
			map.setCenter(ct, map.getBoundsZoomLevel(region));
			center = ct;
		}
		else
		{
			var point = new GLatLng(35.658634, 139.745411); // 初期位置は東京タワー
			map.setCenter(point, 14);
			center = point;
		}

		var icon = new GIcon();
		icon.image = static_file_site + "/aka.png";
		icon.iconSize = new GSize(4, 4);
		icon.iconAnchor = new GPoint(0, 0);

		markeropts = new Object();
		markeropts.icon = icon;
		markeropts.clickable = false;

		if (isDefined('plot_mode'))
		{
			plotmode = plot_mode;
		}

		if (isDefined('plot_count'))
		{
			plotcount = plot_count;
		}

		users = new Object();
		if (isDefined('group_name'))
		{
			getGroupUser(group_name);
			for (var u in user_list)
			{
				initUser(user_list[u], true);
			}
		}
		else if (!isDefined('user_list'))
		{
			loadUserList(false);
		}
		else if (user_list[0] == 'all')
		{
			loadUserList(true);
			setTraceUser('all');
		}
		else
		{
			for (var u in user_list)
			{
				initUser(user_list[u], true);
			}
		}

		segments = new Array(numLevels);
		for( var z = numLevels - 1; 0 <= z; --z )
		{
			segments[z] = baseDistance * Math.pow( zoomFactor, -1 * z );
		}

		setTimeout(load_next, 10);
	}
}

function load_next()
{
	if (isDefined('trace_user'))
	{
		setTraceUser(trace_user);
	}

	update();
	timer = window.setInterval("update()", 1000);
}

if (typeof use_onload != 'undefined' && use_onload) {
	window.onload = initialize;
}


