/////////////////////////////////////////////////
//
// BGMap class
//
// $bgmap = new BGMap();   # get instance
//

BGMap = Class.create();
BGMap.prototype = {
  initialize: function () {
      if (GBrowserIsCompatible()) {
  	this.map = new GMap2(document.getElementById('map'));
  	this.map.addControl(new GLargeMapControl());
  	this.map.addControl(new GHierarchicalMapTypeControl());
	this.map.addMapType(G_PHYSICAL_MAP);

      	this.map.setCenter(new GLatLng(35.6858144043428, 139.730000495911 ), 13);

      }
      this.onClickFunc = null;
      this.point_marker = null;       		// for pointMode() previous marker
      this.point_icon_url = '/images/white_pin.png';
                                      		// for pointMode() icon_url
      this.point_form_id = ''         		// for pointMode() hidden form name
      this.markers = new Object();    		// for point list
      this.route_markers = new Object();    // for route_marker
      this.tour_markers = new Object();    // for tour_marker
		this.geocoder = new GClientGeocoder();

      // pedal mileage overlay 2009.11.21 nakagoshi
      this.pedalmileageOverlay = null;

      this.initRoute();
  },


  /////////////////////////////////////////////////
  // set event listner callback function to map
  //   (automatic remove previouse callback)
  //
  onClick: function (f) {
      this.removeOnClick();
      this.onClickFunc = GEvent.addListener(this.map, "click", f);
  },

  removeOnClick: function () {
      if (this.onClickFunc) {
	  GEvent.removeListener(this.onClickFunc);
	  this.onClickFunc = null;
      }
  },


  /////////////////////////////////////////////////
  // delegate functions
  //   (just as short cut to GMap function)
  //
  // $bgmap.centerAndZoom(..);
  //   is equal to
  // $bgmap.map.centerAndZoom(..);
  //
  centerAndZoom: function (point, level) { this.map.setCenter(point, level); },
  centerAtLatLng: function (point) { this.map.setCenter(point); },
//  centerAtLatLng: function (lon, lat) { this.map.centerAndZoom(new GLatLng(lon, lat)); },
  centerAtLatLngScale: function (lon, lat, scale) { this.map.setCenter(new GLatLng(lat,lon ), scale); },
  /////////////////////////////////////////////////
  // register & remove GMarker by JSON attrs
  //
  // ('key' means icon type)
  //
  // $bgmap.registGMarker(key, attrs);  # put GMarkers on Map by attrs
  // $bgmap.removeGMarker(key);         # remove GMarkers by key
  // $bgmap.removeGMarkerAll();         # remove all
  //

  registGMarker: function (key, attrs) {
      // 他のアイテムを表示する時はペダルマイレージのオーバーレイを削除 2009.11.21 nakagoshi
      if (this.pedalmileageOverlay != null) {
        this.map.removeOverlay(this.pedalmileageOverlay);
        this.pedalmileageOverlay = null;
      }
      
      if (this.markers[key]) {
	      this.removeGMarker(key);
	      return true;
      }

      this.markers[key] = new Array();
      for (var i = 0; i < attrs.length; i++) {
        // 
  	    // var m = BGMap.newMarker(this.map, attrs[i]);
  	    var m = BGMap.newMarkerWithTab(this.map, attrs[i]);
  	    this.markers[key].push(m);
  	    this.map.addOverlay(m);
      }
  },

  removeGMarker: function (key) {
      if (this.markers[key]) {
        for (var i = 0; i < this.markers[key].length; i++) {
            this.map.closeInfoWindow();
            this.map.removeOverlay(this.markers[key][i]);
        }
        this.markers[key] = null;
      }
  },

  registRouteGMarker: function (key, attrs) {
      // 他のアイテムを表示する時はペダルマイレージのオーバーレイを削除 2009.11.21 nakagoshi
      if (this.pedalmileageOverlay != null) {
        this.map.removeOverlay(this.pedalmileageOverlay);
        this.pedalmileageOverlay = null;
      }

      if (this.route_markers[key]) {
	      this.removeRouteGMarker(key);
	      return true;
      }

      this.route_markers[key] = new Array();
      for (var i = 0; i < attrs.length; i++) {
        // 
  	    // var m = BGMap.newMarker(this.map, attrs[i]);
  	    var m = BGMap.newMarkerWithTab(this.map, attrs[i]);
  	    this.route_markers[key].push(m);
  	    this.map.addOverlay(m);
      }
  },
  
  removeRouteGMarker: function (key) {
      if (this.route_markers[key]) {
        for (var i = 0; i < this.route_markers[key].length; i++) {
            this.map.closeInfoWindow();
            this.map.removeOverlay(this.route_markers[key][i]);
        }
        this.route_markers[key] = null;
      }
  },

  registTourGMarker: function (key, attrs) {
      if (this.tour_markers[key]) {
	      this.removeTourGMarker(key);
	      return true;
      }

      this.tour_markers[key] = new Array();
      for (var i = 0; i < attrs.length; i++) {
  	    var m = BGMap.newMarkerWithTab(this.map, attrs[i]);
  	    this.tour_markers[key].push(m);
  	    this.map.addOverlay(m);
      }
  },

  removeTourGMarker: function (key) {
      if (this.tour_markers[key]) {
        for (var i = 0; i < this.tour_markers[key].length; i++) {
            this.map.closeInfoWindow();
            this.map.removeOverlay(this.tour_markers[key][i]);
        }
        this.tour_markers[key] = null;
      }
  },

  removeGMarkerAll: function () {
      for (key in this.markers) this.removeGMarker(key);
      for (key in this.route_markers) this.removeRouteGMarker(key);
      for (key in this.tour_markers) this.removeTourGMarker(key);
  },

  /////////////////////////////////////////////////
  // route mode functions
  //
  // $bgmap.addRoute(key, json)    # add route
  // $bgmap.removeRoute(key)       # remove route
  // $bgmap.resetRoute(key)        # reset all route
  //
  // $bgmap.addRoutePoint(point);  # edit: add route point
  // $bgmap.revertRoutePoint();    # edit: undo route point
  // $bgmap.resetRoutePoint();     # edit: reset all route point
  // $bgmap.routeToQuery();        # edit: route point to query string
  //

  // call from initialize()
  initRoute: function () {
      // for edit
      this.route = new Object();
      this.route.points = new Array();  // clicked points
      this.route.lines = new Array();   // GPoliLine objects for edit

      // for display
      this.routes = new Object();       // GPoliLine objects for display

      // default attributes
      this.rt_color = "#ff0000";
      this.rt_weight = 5;
      this.rt_opacity = 0.5;
  },

  // make general polyline
  polyline: function (points) {
      return new GPolyline(points, this.rt_color, this.rt_weight, this.rt_opacity);
  },

  // --- for polyline display functions ---
  // drow polyline
  //
  // params
  //   disp: false(nomal), true(force displaying, not remove)
  addRoute: function (key, json, disp) {
      if (this.routes[key]) {
	 if (!disp) this.removeRoute(key);
      }
      else {
	  var points = new Array();
	  for (i = 0; i < json.length; i++)
	      points.push(new GLatLng(json[i].lat, json[i].lng));
	  var line = this.polyline(points);
	  this.routes[key] = line;
	  this.map.addOverlay(line);
      }
  },

  removeRoute: function (key) {
      if (this.routes[key]) {
	  this.map.removeOverlay(this.routes[key]);
	  this.routes[key] = null;
      }
  },
  
  resetRoute: function () {
      for (key in this.routes) this.removeRoute(key);
  },

  // --- for polyline edit functions ---
  // add point of route
  addRoutePoint: function (point) {
      this.route.points.push(point);
      if (this.route.points.length > 1) {
  	var pts = [this.route.points[this.route.points.length - 2], point];
  	var gpline = this.polyline(pts);
  	this.route.lines.push(gpline);
  	this.map.addOverlay(gpline);

        // 経路の距離を求める added by nakagoshi 2009.11.19
        if (this.route.points.length >= 2) {
          pathwayDistance += (this.route.points[this.route.points.length-2]).distanceFrom(this.route.points[this.route.points.length-1]);
          $('route_distance').innerHTML = (pathwayDistance * 0.001).toFixed(3).toString();
          $('route_distance_param').setAttribute('value',pathwayDistance);
        }

      }
  },

  // undo previous point
  revertRoutePoint: function () {
      if (this.route.points.length > 0) {
	  this.route.points.pop();
	  if (this.route.lines.length > 0) {
	      this.map.removeOverlay(this.route.lines.pop());
	  }
          // 経路の距離を再計算する added by nakagoshi 2009.11.19
          pathwayDistance = 0;
          if (this.route.points.length >= 2) {
            for(i=1;i<this.route.points.length;i++) {
                pathwayDistance += (this.route.points[i-1]).distanceFrom(this.route.points[i]);
            }
          }
          $('route_distance').innerHTML = (pathwayDistance * 0.001).toFixed(3).toString();
          $('route_distance_param').setAttribute('value',pathwayDistance);
      }
  },

  // reset all points
  resetRoutePoint: function () {
      for (p in this.route.points) this.revertRoutePoint();
  },

  // convert route point's to query string
  routeToQuery: function () {
      var q = new Array();
      for (i = 0; i < this.route.points.length; i++) {
	  point = this.route.points[i];
	  q.push(point.x + ',' + point.y);
      }
      return q.join('_');
  },


  /////////////////////////////////////////////////
  // point mode function
  //
  // $bgmap.setPointFormId('point_');
  //   # setting form id
  //   # set point.x to id 'point_longitude'
  //   # set point.y to id 'point_latiitude'
  //   # when setMarkPoint() was calld.(ex. user click)
  //
  // ex. set default url
  //   $bgmap.setPointIconUrl(url);
  //   $bgmap.pointMode();    # use default icon url
  //
  // ex. direct url
  //   $bgmap.pointMode(url); # use url for icon
  //
  setPointIconUrl: function(url) { this.point_icon_url = url; },
  setPointFormId: function(id) { this.point_form_id = id; },

  setMarkPoint: function (point, icon_url) {
      if (icon_url == null) icon_url = this.point_icon_url;
      this.resetMarkPoint();
      this.point_marker = BGMap.createMarker(point.x, point.y, icon_url);
      this.map.addOverlay(this.point_marker);
      try {
	  $(this.point_form_id+'longitude').value = point.x;
	  $(this.point_form_id+'latitude').value = point.y;
      } catch (e) {
	  log('setMarkPoint(): point set to form');
	  log(this.point_form_id+'longitude');
	  log(this.point_form_id+'latitude');
      }
  },

  resetMarkPoint: function() {
      if (this.point_marker) {
	  this.map.removeOverlay(this.point_marker);
	  this.point_marker = null;
      }
  },


  /////////////////////////////////////////////////
  // change mode
  //
  // $bgmap.defaultMode();   # reset all data
  // $bgmap.pointMode();     # point edit mode
  // $bgmap.routeMode();     # route edit mode
  //
  defaultMode: function () {
      this.removeOnClick();
      this.resetMarkPoint();
      this.resetRoute();
      this.resetRoutePoint();
  },

  pointMode: function (icon_url) {
      t = this; // need this for callback
      this.onClick(function (overlay, point) {
	  if (point) { t.setMarkPoint(point, icon_url) }
      })
  },

  routeMode: function () {

      pathwayDistance = 0; // added by nakagoshi 2009.11.19

      t = this; // need this for callback
      this.onClick(function (overlay, point) {
	  if (point) t.addRoutePoint(point);
      })
  },
  
  jumpByAddress: function (address)  {
    var map = this.map ;

    if (this.geocoder) {
    	this.geocoder.getLatLng(
           	address,
          	function(point) {
                    if (!point) {
                        alert(address + " not found");
                    } else {
                        map.setCenter(point, 13);
                        var marker = new GMarker(point);
                        map.addOverlay(marker);
                        marker.openInfoWindowHtml(address);
                    }
          	}
        );
    }
  },
	
  // Zero Point is left & bottom
  addScreenOverlay: function (logo_url, x, y, width, height) {
    gso = new GScreenOverlay(logo_url,
        new GScreenPoint(x, y, 'pixels', 'pixels'),  // screenXY
        new GScreenPoint(0, 0),  // overlayXY
        new GScreenSize(width, height)  // size on screen
    );
    this.map.addOverlay(gso);
  },

  // カスタムオーバーレイでペダルマイレージを表示
  // 2009.11.21 nakagoshi
  pedalMileage: function () {
        function PedalMileage() {
        }

        PedalMileage.prototype = new GOverlay();

        // Creates the DIV representing this rectangle.
        PedalMileage.prototype.initialize = function(map) {
            // Create the DIV representing our rectangle
            var div = $('pedal_mileage');
            // Our rectangle is flat against the map, so we add our selves to the
            // MAP_PANE pane, which is at the same z-index as the map itself (i.e.,
            // below the marker shadows)
            map.getPane(G_MAP_MAP_PANE).appendChild(div);
            this.map_ = map;
            this.div_ = div;
        }
        // Redraw the rectangle based on the current projection and zoom level
        PedalMileage.prototype.redraw = function(force) {
            // We only need to redraw if the coordinate system has changed
            if (!force) return;

            // Calculate the DIV coordinates of two opposite corners of our bounds to
            // get the size and position of our rectangle
            var c1 = this.map_.fromLatLngToDivPixel(this.bounds_.getSouthWest());
            var c2 = this.map_.fromLatLngToDivPixel(this.bounds_.getNorthEast());

            // Now position our DIV based on the DIV coordinates of our bounds
            this.div_.style.width = Math.abs(c2.x - c1.x) + "px";
            this.div_.style.height = Math.abs(c2.y - c1.y) + "px";
            this.div_.style.left = (Math.min(c2.x, c1.x) - this.weight_) + "px";
            this.div_.style.top = (Math.min(c2.y, c1.y) - this.weight_) + "px";

            //this.map_.removeOverlay(this);
        }

        this.pedalmileageOverlay = new PedalMileage();
        this.map.addOverlay(this.pedalmileageOverlay);

  },



  // just as dummy for remove ',' character
  __final_dummy: null
}


/////////////////////////////////////////////////
// BGMap 'class function'
//
// these functions can call directly
// no instance required
//
// icon = BGMap.newIcon(image_url);        # create icon
// str = BGMap.sanitizeForInfowindow(str); # sanizize for Safari
// marker = BGMap.createMarker(lon, lat, icon_url);
//                                         # create primitive marker
// marker = BGMap.newMarker(map, opts);    # create marker with click-up window
//

// default icon setup
BGMap.newIcon = function (image_url) {
    	var icon = new GIcon();

    icon.image = image_url;
    icon.iconSize = new GSize(40, 40);
    icon.infoWindowAnchor = new GPoint(20, 20);
    icon.iconAnchor = new GPoint(14, 40);

    return icon;
}

BGMap.createMarker = function (lon, lat, icon_url, title) {
	if ( icon_url )
	{
		var marker_options = new Object();
		marker_options.title = title;
		marker_options.icon = BGMap.newIcon(icon_url);
    	return new GMarker((new GLatLng(lat,lon)),marker_options);		
	}else
	{
		var marker_options = new Object();
		marker_options.title = title;
    	return new GMarker((new GLatLng(lat,lon)),marker_options);		
	}
}

// default GMarker setup by opts
BGMap.newMarker = function (map, opts) {

    var marker = BGMap.createMarker(opts.lon, opts.lat, opts.icon_url,opts.title);
    var f = function()
    {
	map.setCenter(new GLatLng(opts.lat, opts.lon));
  
	marker.openInfoWindowHtml(opts.html);
    }
    GEvent.addListener(marker, "click", f);

    var marker_field = document.getElementById('marker_link' + opts.id);
    if (marker_field)
	marker_field.onmousedown = f;

    return marker;
}

// default GMarker setup by opts
BGMap.newMarkerWithTab = function (map, opts) {

    var marker = BGMap.createMarker(opts.lon, opts.lat, opts.icon_url,opts.title);
    var f = function()
    {  
      var infoTabs = [
        new GInfoWindowTab(opts.tab1,opts.html ),
        new GInfoWindowTab(opts.tab2,opts.html2 ),
        new GInfoWindowTab(opts.tab3,opts.html3 )
      ];
      
      marker.openInfoWindowTabsHtml(infoTabs); 

    }
    GEvent.addListener(marker, "click", f);

    var marker_field = document.getElementById('marker_link' + opts.id);
    if (marker_field)
	marker_field.onmousedown = f;

    return marker;
}


