google.load('maps', '2');

/**
 * マップオブジェクトを格納するグローバル変数
 * markers プロットされたマーカ配列
 * baseicon ベースアイコン
 * open_marker マイマップをひらいたマーカ
 * target_marker インフォウィンドウを開いたマーカ
 */
var map;

/**
 * マップの初期化とベースアイコンの定義
 */
function initMap() {
  map = new GMap2(document.getElementById("map"));
  map.setCenter(new GLatLng(-25.335448,135.745076), 4); // Center of Australia
  map.addControl(new GLargeMapControl());
  map.addControl(new GMapTypeControl());
  map.addControl(new GOverviewMapControl());
  map.markers = new Array();
  icon = new GIcon();
  icon.image = "http://maps.google.co.jp/mapfiles/ms/micons/blue-dot.png";
  icon.shadow = "http://www.google.com/mapfiles/ms/micons/msmarker.shadow.png";
  icon.iconSize = new GSize(32, 32);
  icon.iconAnchor = new GPoint(9, 34);
  icon.infoWindowAnchor = new GPoint(14, 12);
  icon.shadowSize = new GSize(59, 32);
  map.baseicon = icon;
}

/**
 * プロットされたすべてのマーカを含むのに必要なレベルへズームし
 * その中心にパン。
 * マイマップが開かれていれば、閉じる。
 */
function resetZoom() {
  if (map.open_marker) {
    _closeMyMap(map.open_marker);
  }
  var s, w, n, e;
  var str = '';
  for (var i in map.markers) {
    var marker = map.markers[i];
    var ll = marker.getLatLng();
    var lat = parseFloat(ll.lat());
    var lng = parseFloat(ll.lng());

    if (lat == -90 || lat == 90) {
      continue;
    }

    if (!s) { s = lat; };
    if (!n) { n = lat; };
    if (!w) { w = lng; };
    if (!e) { e = lng; };

    if (lat < s) { s = lat; }
    if (lat > n) { n = lat; }
    if (lng < w) { w = lng; }
    if (lng > e) { e = lng; }
  }
  var llb = new GLatLngBounds(new GLatLng(s, w), new GLatLng(n, e));
  map.setZoom(map.getBoundsZoomLevel(llb));
  map.panTo(llb.getCenter());
}

/**
 * マイマップのインフォウィンドウを開く。
 * @param index map.markersのインデックス
 * インデックスはプロットした順に一致。
 */
function openMyMapInfo(index) {
  var marker = map.markers[index];
  _markerOnClick(marker);
}

/**
 * 開いているマイマップのマーカのインフォウィンドウを開く。
 */
function reopenMyMapInfo() {
  if (map.open_marker) {
    var marker = map.open_marker;
    map.setZoom(marker.zoom);
    _markerOnClick(marker);
  }
}

/**
 * エントリ配列からマーカをプロットしていき、
 * そのマーカをmap.markersに格納する。
 * @param entries エントリ配列
 */
function plotMarkers(entries) {
  if (map.target_marker) {
    map.target_marker.closeInfoWindow();
  }
  map.clearOverlays();
  var markers = new Array();
  for (var i in entries) {
    var entry = entries[i];
    markers[i] = mark(entry);
  }
  map.markers = markers;
}

/**
 * マーカをプロットする。
 * @param entry エントリ情報オブジェクト
 * @return marker マーカ
 */
function mark(entry) {
  var ll = entry.point.split(',');
  var icon = new GIcon(map.baseicon);
  icon.image = [
                'images/map-icon-',
                entry.icon,
                '.png'
                ].join('');
  marker = new GMarker(new GLatLng(ll[0], ll[1]), icon);
  marker.title = entry.title;
  marker.date = [
                      entry.date.getDate(),
                      '/',
                      (entry.date.getMonth() + 1),
                      '/',
                      entry.date.getFullYear(),
                 ].join('');
  marker.nick = entry.nick;
  marker.desc = entry.desc;
  marker.type = entry.type;
  marker.link = entry.link;
  marker.icon = entry.icon;
  var zoomExpr = new RegExp('&z=([0-9]+)&', 'i');
  if (marker.link.match(zoomExpr)) {
    marker.zoom = parseInt(RegExp.$1);
  } else {
    marker.zoom = 4;
  }
  if (marker.type == 'guest') {
    marker.photo = entry.photo;
  }
  map.addOverlay(marker);
  GEvent.addListener(marker, 'click', markerOnClick);
  return marker;
}

/**
 * マーカのクリックにアタッチする関数。
 */
function markerOnClick() {
  _markerOnClick(this);
}

/**
 * マーカのクリックにアタッチする関数から
 * マイマップが開かれているかどうかで処理を切り替える。
 * @param marker マーカ
 */
function _markerOnClick(marker) {
  if (map.open_marker == marker) {
    _markerOnClickSecond(marker);
  } else {
    _markerOnClickFirst(marker);
  }
}

/**
 * マーカのクリックにアタッチする関数の
 * マイマップが開かれていない場合
 * @param marker マーカ
 */
function _markerOnClickFirst(marker) {
  if (map.open_marker) {
    _closeMyMap(map.open_marker);
  }
  var img = '';
  if (marker.type == 'guest') {
    img = [ '<img src="images/guest-',
            marker.photo,
            '.jpg" alt="',
            marker.nick,
            '" />'
            ].join('');
  }
  var str = [
             '<div class="mymap">',
             '<h2>',
             marker.title,
             '</h2>',
             '<h3>',
             marker.nick,
             '　',
             marker.date,
             '</h3>',
             img,
             '<p>',
             marker.desc,
             '</p>',
             '<ul>',
             '<li>',
             '<a href="',
             marker.link,
             ,'">',
             'View in detail on Google Maps',
             '</a>',
             '</li>',
             '</ul>',
             '</div>'
             ].join('');
  marker.openInfoWindowHtml(str);
  map.target_marker = marker;
}

/**
 * マーカのクリックにアタッチする関数の
 * マイマップが開かれている場合
 * @param marker マーカ
 */
function _markerOnClickSecond(marker) {
  var img = '';
  if (marker.type == 'guest') {
    img = [ '<img src="images/guest-',
            marker.photo,
            '.jpg" alt="',
            marker.nick,
            '" />'
            ].join('');
  }
  var str = [
             '<div class="mymap">',
             '<h2>',
             marker.title,
             '</h2>',
             '<h3>',
             marker.nick,
             '　',
             marker.date,
             '</h3>',
             img,
             '<p>',
             marker.desc,
             '</p>',
             '<ul>',
             '<li>',
             '<a href="#" onclick="closeMyMap(); return false;">',
             'Close this map',
             '</a>',
             '</li>',
             '<li>',
             '<a href="',
             marker.link,
             ,'">',
             'View in detail on Google Maps',
             '</a>',
             '</li>',
             '</ul>',
             '</div>'
             ].join('');
  marker.openInfoWindowHtml(str);
  map.target_marker = marker;
}

/**
 * インフォウィンドウを開いているマーカのマイマップを開く
 */
function seeMyMap() {
  _seeMyMap(map.target_marker);
}

/**
 * マイマップを開く
 * @param marker マーカ
 */
function _seeMyMap(marker) {
  map.setZoom(marker.zoom);
  if (map.open_marker) {
    _closeMyMap(map.open_marker);
  }
  marker.closeInfoWindow();

  var mymap = new GGeoXml(marker.link + '&output=kml');
  marker.mymap = mymap;
  map.addOverlay(mymap);
  map.open_marker = marker;
  _markerOnClick(marker);
  for (var i in map.markers) {
    map.markers[i].hide();
  }
  marker.show();
  setMapName(marker);
}

/**
 * インフォウィンドウを開いているマーカのマイマップを閉じる
 */
function closeMyMap() {
  _closeMyMap(map.target_marker);
}

/**
 * マイマップを閉じる
 * @param marker マーカ
 */
function _closeMyMap(marker) {
  marker.closeInfoWindow();
  map.removeOverlay(marker.mymap);
  map.open_marker = null;
  resetZoom();
  for (var i in map.markers) {
    map.markers[i].show();
  }
  clearMapName();
}
