/* TKMaps 2007-11-22
Need prototype.js
Need Google Maps API
See http://webtips.open-log.net/

2007-11-22 Marker ID Return
2007-11-01 Polyline
*/

var TKMapsObj = new function(){
  if(typeof( Prototype ) != "object") {
    alert("prototype.jsが読込まれていません");return null;
  }else if ( typeof( GMap2 ) != "function" ) {
    alert("Google Maps API が読込まれていません");return null;
  }
  this.mapid = "map";
  this.defLat = 37.6;
  this.defLon = 139.8;
  this.defZoom = 5;
  this.defMapType = 3;
  this.mapObj = null; //Map Object
  this.markers = {}; //marker Objects
  this.markerid = 0;
  this.markerCh = {};//marker channel
  this.markerChId = {};//marker channel marker id
  this.markerIdObjs = {}; //markerid key
  this.markerListIds = {};
  this.geocoder = null; //geocoder Object
  this.controls = ["L","T","O","SC"];
  this.moveFuncs = []; // moveend Functions
  this.clickFuncs = []; // click Functions
  this.clickMarkerFuncs = []; // Marker click Functions
  this.windowOpenFlg = 0;
  this.listFormat = "<li id=\"TKMapsMarkerList_%%mid%%\"><a href=\"#\" onclick=\"GEvent.trigger( TKMapsObj.markers[%%id%%], 'click'); return false;\">%%str%%</a></li>";
  this.listFormats = {};
  this.maxlat = null;
  this.minlat = null;
  this.maxlon = null;
  this.minlon = null;
  this.addCreditDiv = "addAPI";
  //Initialize
  this.init = function (initObj){
    if(initObj){
      if(initObj.mapid) this.mapid = initObj.mapid;
      if(initObj.defLat) this.defLat = initObj.defLat;
      if(initObj.defLon) this.defLon = initObj.defLon;
      if(initObj.defZoom) this.defZoom = initObj.defZoom;
      if(initObj.defMapType) this.defMapType = initObj.defMapType;
      if(initObj.controls) this.controls = initObj.controls;
      if(initObj.listFormats) this.listFormats = initObj.listFormats;
    }
    $(this.mapid).innerHTML = "";
    var div = document.createElement("div");
    div.id = this.mapid+"_map";
    div.style.width = "100%";
    div.style.height = "100%";
    $(this.mapid).appendChild(div);
    this.mapObj = new GMap2( $(this.mapid+"_map") ); 
    this.mapObj.setCenter( new GLatLng(this.defLat, this.defLon), this.defZoom);
    this.setMapType(this.defMapType);
    this.geocoder = new GClientGeocoder();
    this.setControls( this.controls );
    this.addMoveListener(this);
    this.addClickListener(this);
    this.addStatusDiv(this.mapid);
    for(var i=0;i<this.moveFuncs.length;i++){
      this.moveFuncs[i](this.mapObj);
    }
  }
  this.setMapType = function (type) {
    switch (type) {
      case 1: this.mapObj.setMapType( G_MAP_TYPE ); break;
      case 2: this.mapObj.setMapType( G_SATELLITE_TYPE ); break;
      case 3: this.mapObj.setMapType( G_HYBRID_TYPE ); break;
    }
  }
  this.setControls = function (c){
    for(var i=0;i<c.length;i++){
      switch(c[i]){
        case "S": this.mapObj.addControl(new GSmallMapControl());break;
        case "L": this.mapObj.addControl(new GLargeMapControl());break;
        case "Z": this.mapObj.addControl(new GSmallZoomControl());break;
        case "SC": this.mapObj.addControl(new GScaleControl());break;
        case "T": this.mapObj.addControl(new GMapTypeControl());break;
        case "O": this.mapObj.addControl(new GOverviewMapControl());break;
      }
    }
  }

  //移動時に呼び出す関数
  this.addMoveListener = function(obj){
    GEvent.addListener(obj.mapObj, "moveend", function(){
      var c = obj.mapObj.getCenter();
      for(var i=0;i<obj.moveFuncs.length;i++){
        obj.moveFuncs[i](obj.mapObj);
      }
    });
  }
  //クリック時に呼び出す関数
  this.addClickListener = function(obj){
    GEvent.addListener(obj.mapObj, "click", function(overlayObj, mapPoint){
      for(var i=0;i<obj.clickFuncs.length;i++){
        obj.clickFuncs[i](overlayObj, mapPoint);
      }
    });
  }

  //環境変数取得用
  this.getEnv = function(){
    var b = this.mapObj.getBounds();
    var c = this.mapObj.getCenter();
    var ne = b.getNorthEast();
    var sw = b.getSouthWest();
    var env = { id : this.mapid , 
      center : c,
      mapType : this.mapObj.getCurrentMapType().getName(),
      zoom : this.mapObj.getZoom() , 
      size : this.mapObj.getSize(),
      bounds : b,
      minlon : sw.lng(),
      minlat : sw.lat(),
      maxlon : ne.lng(),
      maxlat : ne.lat(),
      dminlon : c.lng() - b.toSpan().lng(),
      dminlat : c.lat() - b.toSpan().lat(),
      dmaxlon : c.lng() + b.toSpan().lng(),
      dmaxlat : c.lat() + b.toSpan().lat()
    }
    return env;  
  }

  //Geocoding用
  this.getAddress = function (address){
    this.getAddress2(address, this.mapObj);
  }
  this.getAddress2 = function(address,mapObj){
    if (this.geocoder) {
      this.geocoder.getLatLng(address,function(point) {
        if (!point) {
          alert( address + " は見つかりません");
        } else {
          mapObj.setCenter(point);
          mapObj.openInfoWindowHtml( point , address);
        }
      });
    }
  }

  //Marker Functions
  this.addAndRemoveMarker = function(ch, mObj, max){
    if(! this.markerCh[ch]){
      this.markerCh[ch] = [];
    }
    if(! this.markerChId[ch]){
      this.markerChId[ch] = {};
    }
    if(! this.markerChId[ch][mObj.id] ){
      this.setMarker(mObj);
    }
    if(max < this.markerCh[ch].length){
      var mid = this.markerCh[ch].shift();
      var O = this.markerIdObjs[mid];
      this.removeMarker(mid, ch);
      return O;
    }else{
      return null;
    }
  }
  this.setMarker = function(mObj){
    var id = this.markerid;
    var opt = (mObj.opt)? mObj.opt : null ;
    this.markerCh[mObj.chname].push( id );
    this.markerChId[mObj.chname][mObj.id] = id;
    this.markerIdObjs[id] = { chname:mObj.chname, chid:mObj.id };
    this.markers[id] = new GMarker( new GLatLng(mObj.lat,mObj.lon), opt );
    this.markers[id].addVars = {ch: mObj.chname, id:id } ;//属性追加
    this.mapObj.addOverlay(this.markers[id]);
    this.setMarkerWindow(this.markers[id], mObj, this);    
    var listId = ( mObj.listId )? mObj.listId : this.mapid+"_"+mObj.chname+"_List";
    if( mObj.str && $(listId) != null ){
      this.addList(id, mObj.str, listId);
    }
    this.setMaxMin(mObj.lat, mObj.lon);
    this.addMarkerClickListener(this.markers[id], this);
    this.markerid++;
    return id;
  }
  this.setMaxMin = function(lat,lon){
    if(this.maxlat == null) this.maxlat = lat;
    if(this.maxlon == null) this.maxlon = lon;
    if(this.minlat == null) this.minlat = lat;
    if(this.minlon == null) this.minlon = lon;
    if(this.maxlat < lat ) this.maxlat = lat;
    if(this.maxlon < lon ) this.maxlon = lon;
    if(this.minlat > lat ) this.minlat = lat;
    if(this.minlon > lon ) this.minlon = lon;
  }
  this.setMarkerWindow = function(marker, mObj, obj){
    GEvent.addListener( marker, "click", function() {
      if( mObj.window ){
        marker.openInfoWindowHtml( mObj.window );
      }else if( mObj.windowTabs ){
        marker.openInfoWindowTabsHtml( mObj.windowTabs );
      }
      obj.windowOpenFlg = 1;
    });
    GEvent.addListener( marker, "infowindowclose", function() {
      obj.windowOpenFlg = 0;
    });
  }
  this.removeMarker = function(id, ch){
    id = id*1;
    this.mapObj.removeOverlay(this.markers[id]);
    var O = this.markerIdObjs[id];
    var ch = O.chname;
    var chid = O.chid;
    delete this.markerChId[ch][chid];
    delete this.markerIdObjs[id];
    var listId = this.mapid+"_"+ch+"_List";
    if($("TKMapsMarkerList_"+id) != null && $(listId) != null){
      $(listId).removeChild($("TKMapsMarkerList_"+id) );
    }
  }
  this.clearMarkers = function(){
    this.mapObj.clearOverlays();
    this.markers = {};
    this.markerCh = {};
    this.markerChId = {};
    this.markerIdObjs = {};
    this.markers = {};
    this.maxlat = null;
    this.minlat = null;
    this.maxlon = null;
    this.minlon = null;
    for(var listId in this.markerListIds){
      if($(listId) != null){
        $(listId).innerHTML = "";
      }
    }
  }
  this.clearChMarkers = function(ch){
    var mid = 1;
    while( mid = this.markerCh[ch].shift() ){
      this.removeMarker(mid, ch);
    }
  }
  this.addMarkerClickListener = function( marker, obj){
    GEvent.addListener(marker, "click", function(){
      for(var i=0;i<obj.clickMarkerFuncs.length;i++){
        obj.clickMarkerFuncs[i]( marker );
      }
    });
  }

  this.setAutoBounds = function(){
    var rect = new GLatLngBounds(new GLatLng(this.minlat, this.minlon), new GLatLng(this.maxlat, this.maxlon));
    var zm = this.mapObj.getBoundsZoomLevel(rect);
    this.mapObj.setCenter(rect.getCenter(), zm );
  }

  this.addScript = function(url){
    var el = document.createElement("script");
    el.setAttribute("src",url);
    el.setAttribute("type","text/javascript");
    el.setAttribute("charset","UTF-8");
    document.getElementsByTagName("head").item(0).appendChild(el);
  }

  this.addStatusDiv = function(id){
    var div = document.createElement("div");
    div.id = id+"_status";
    div.style.color = "orange";
    div.style.position = "relative";
    div.style.top = "-20px";
    div.style.left = "180px";
    $(id).appendChild(div);
  }
  this.addStatusSpan = function(ch){
    var divid = this.mapid+"_status";
    var span = document.createElement("span");
    span.id = divid+"_"+ch;
    span.innerHTML = ch+"読み込み";
    $(divid).appendChild(span);
  }
  this.addList = function(id, str, listId){
    this.markerListIds[listId] = listId;
    var lstr = ( this.listFormats[listId] )? this.listFormats[listId] : this.listFormat;
    lstr = lstr.replace("%%str%%",str);
    lstr = lstr.replace("%%mid%%",id);
    lstr = lstr.replace("%%id%%",id);
    lstr += $(listId).innerHTML;
    $(listId).innerHTML = lstr;
  }

  //変換関数
  this.deg2min = function (a){
    var t = a * 3600 * 100;
    t = Math.ceil(t) / 100 ;
    return t;
  }
  this.tokyo2wgs = function (jlat, jlon){
    var wlat = jlat - 0.00010695 * jlat + 0.000017464 * jlon + 0.0046017;
    var wlon = jlon - 0.000046038 * jlat - 0.000083043 * jlon + 0.010040;
    return { lat:wlat, lon:wlon } ;
  }
  this.wgs2tokyo = function (wlat,wlon){
    var jlat = wlat + 0.00010696 * wlat - 0.000017467 * wlon - 0.0046020;
    var jlon = wlon + 0.000046047 * wlat + 0.000083049 * wlon - 0.010041;
    return { "lat":jlat, "lon":jlon } ;
  }
  this.addCredit = function(ch, str){
    var divid = ch + "_Credit";
    if($(divid) == null){
      $(this.addCreditDiv).innerHTML += "\n&nbsp;|&nbsp;<span id=\""+divid+"\">"+str+"</span>";      
    }
  }
  this.getPrefBorders = function(pref){
    if(pref == 0 || pref > 47 ) return null;
    var url = "http://maps.open-log.net/api/getPrefBorder.php?cb=TKMapsObj.addPrefBorders&pref="+pref;
    this.addScript(url);
  }
  this.addPrefBorders = function(obj){
    for(var i=0;i<obj.coordinates.length;i++){
      var c = obj.coordinates[i];
      var p = [];
      for(var t=0;t<c.points.length;t++){
        p.push( new GLatLng(c.points[t].lat*1, c.points[t].lon*1) );
      }
      this.addPoly({ "points":p, "type":2 });
    }
  }
  this.addPoly = function(obj){
    if(! obj.points) return null;
    var type = (obj.type)? obj.type : 1;
    var color = (obj.color)? obj.color :"#ffbb00";
    var weight = (obj.weight)? obj.weight : 3;
    var alpha = (obj.alpha)? obj.alpha : 0.5 ;
    if(type == 1){
      this.mapObj.addOverlay(new GPolyline( obj.points , color, weight, alpha ));
    }else{
      var acolor = ( obj.acolor )? obj.acolor : "#005500";
      var aalpha = ( obj.aalpha )? obj.aalpha : 0.2;
      this.mapObj.addOverlay(new GPolygon( obj.points , color, weight, alpha, acolor, aalpha ));
    }
  }
}

