/*
 * Copyright 2006-2007 Maskat Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
maskat.syntax["googleMap"]= {
    name: {type: "string"},
    top: {type: "number"},
    left: {type: "number"},
    width: {type: "number"},
    height: {type: "number"},
    initialLongitude: {type: "number"},
    initialLatitude: {type: "number"},
    initialZoomLevel: {type: "number"},
    parent: {type: "object"},
    mapControl: {type:"enum", elem: ["large","small"]},
    typeControl: {type:"boolean"},
    doubleClickZoom: {type:"boolean"},
    continuousZoom: {type:"boolean"}
  };

maskat.transGoogleMapTag = function(pathObjArray, domElem){
  var attr = {};

  //// 属性の取得
  maskat.receiveAttributes(domElem, attr);

  //// 前変換

  // pathObjArrayの要素を降順に走査し、isContainerプロパティがtrue
  // のオブジェクトのgetRefObjメソッドの戻り値を取得する
  var refObjName=null;
  for (var i = pathObjArray.length - 1; i >= 0; i--){
    if (pathObjArray[i].isContainer){
      refObjName = pathObjArray[i].getRefObj();
      break;
    }
  }

  attr["parent"] = refObjName;

  var strObjPar = maskat.composeParam(domElem, attr);

  var output = attr.name + " = new maskat.widget.GoogleMap(" + strObjPar + ");\n";
  output += "layoutObj.components[\""+attr.name + "\"]="+attr.name+";\n";
  return output;
}

if (typeof maskat.widget == "undefined"){
    maskat.widget={};
}

maskat.widget.GoogleMap = function(objPar){
    //if parent is not specified then create a div DOM object as the parent
    var parentObj = objPar.parent;
    if (parentObj==null){
        parentObj = document.body;
        objPar.parent = document.body;
    }

    this.base=rialto.widget.AbstractComponent;
    this.base(objPar);
    this.parent = objPar.parent;

    var gmap2Defined = true;
    try{
        GMap2;
    }catch(e){gmap2Defined=false;}
    //check if gmap2 object is already defined(google maps API is already loaded)
    if (gmap2Defined==false){
        if (objPar.key==null)
            throw new MaskatError({name: "layoutXML Syntax Error",
                           message: "グーグルマップコンポーネント予めロードされていない場合key属性が必須です。",
                           fileName: "googleMapEx.js",
                           functionName: "maskat.widget.GoogleMap"});
        else{
            //if not,load gmap2 object with the key
            //
            maskat.loadJSFile("http://maps.google.com/maps?file=api&amp;v=2&amp;key="+objPar.key);
            if (GMap2==null){
                throw new MaskatError({name: "グーグルマップAPIロード失敗",
                           message: "グーグルマップAPIロードに失敗しました。",
                           fileName: "googleMapEx.js",
                           functionName: "maskat.widget.GoogleMap"});
            }
        }
    }

    this.divExt.id=this.id+"_DivGen";
    this.divExt.style.position=this.position;
    this.divExt.style.left=this.left+"px";
    this.divExt.style.top=this.top+"px";
    this.divExt.style.width=this.width+"px";
    this.divExt.style.height=this.height+"px";
    this.divExt.style.overflow='hidden';
    this.divExt.style.textOverflow="ellipsis";
    this.divExt.style.whiteSpace="nowrap";
    if(this.parent){this.placeIn(this.parent);};

    this.map = new GMap2(this.divExt);
    var longitude=0;
    var latitude=0;
    if (objPar.initialLongitude !=null && objPar.initialLatitude!=null){
    	longitude=objPar.initialLongitude;
    	latitude=objPar.initialLatitude;
    }
    var zoomLevel = 10;
    if (objPar.initialZoomLevel !=null){
    	zoomLevel=objPar.initialZoomLevel;
    }
    this.map.setCenter(new GLatLng(latitude, longitude), zoomLevel);
    if (objPar.mapControl=="large"){
        this.map.addControl(new GLargeMapControl());
    }
    if (objPar.mapControl=="small"){
        this.map.addControl(new GSmallMapControl());
    }
    if (objPar.typeControl==true){
        this.map.addControl(new GMapTypeControl());
    }
    if (objPar.doubleClickZoom==true){
    	this.map.enableDoubleClickZoom();
    }
    if (objPar.continuousZoom==true){
    	this.map.enableContinuousZoom();
    }
}

maskat.widget.GoogleMap.prototype = new rialto.widget.AbstractComponent;

maskat.widget.GoogleMap.prototype.setCenter = function(latitude,longitude){
    this.map.setCenter(new GLatLng(latitude,longitude));
}

maskat.widget.GoogleMap.prototype.setMarkerAt = function(latitude,longitude){
	var mp = new GLatLng(latitude, longitude);
	var marker = new GMarker(mp);
	this.map.addOverlay(marker);
	return marker;
}

maskat.widget.GoogleMap.prototype.getCenter = function(){
    return this.map.getCenter();
}

maskat.widget.GoogleMap.prototype.openInfoWindow = function(latitude,longitude,text){
    this.map.openInfoWindow(new GLatLng(latitude, longitude),document.createTextNode(text));
}

maskat.widget.GoogleMap.prototype.closeInfoWindow = function(){
    this.map.closeInfoWindow();
}

maskat.widget.GoogleMap.prototype.setDoubleClickZoom = function(doubleClickZoom){
    if (doubleClickZoom==true){
        this.map.enableDoubleClickZoom();
    }else{
        this.map.disableDoubleClickZoom();
    }
}

maskat.googleMap={};


//以下は電文マッピングラッパー拡張

/**
 * 電文サンプル<mapData><lat>123.456</lat><lng>12.23</lng></mapData>
 * 電文に指定する座標位置に移動する
 */
maskat.googleMap.panToLatLngTeleConsumer={};
maskat.googleMap.panToLatLngTeleConsumer.consume=function(targetObj,teleNode){
    if ((targetObj==null) || !(targetObj instanceof maskat.widget.GoogleMap)){
        throw new MaskatError({name: "panToLatLngTeleConsumerエラー",
                         message: "targetObjはmaskat.widget.GoogleMapではありません",
                         fileName: "googleMapEx.js",
                         functionName: "maskat.googleMap.panToLatLngTeleConsumer.consume"});
    }
    //電文にteleNodeは一個しかないであるはず
    var lat = maskat.xpath(teleNode[0], 'lat/text()');
    var lng = maskat.xpath(teleNode[0], 'lng/text()');
    targetObj.setCenter(lat,lng);
}
ObjWrapper.registerTeleConsumer("googleMap.panToLatLng",maskat.googleMap.panToLatLngTeleConsumer);

/**
 * 電文サンプル<mapData><lat>123.456</lat><lng>12.23</lng></mapData>
 * 電文に指定する座標位置にマーカーを作る
 */
maskat.googleMap.markAtLatLngTeleConsumer={};
maskat.googleMap.markAtLatLngTeleConsumer.consume=function(targetObj,teleNode){
    if ((targetObj==null) || !(targetObj instanceof maskat.widget.GoogleMap)){
        throw new MaskatError({name: "markAtLatLngTeleConsumerエラー",
                         message: "targetObjはmaskat.widget.GoogleMapではありません",
                         fileName: "googleMapEx.js",
                         functionName: "maskat.googleMap.markAtLatLngTeleConsumer.consume"});
    }
    //電文にteleNodeは一個しかないであるはず
    var lat = maskat.xpath(teleNode[0], 'lat/text()');
    var lng = maskat.xpath(teleNode[0], 'lng/text()');
    targetObj.setMarkerAt(lat,lng);
}
ObjWrapper.registerTeleConsumer("googleMap.markAtLatLng",maskat.googleMap.markAtLatLngTeleConsumer);

/**
 * 電文サンプル<mapData><lat>123.456</lat><lng>12.23</lng><text>吹き出しテキスト</text></mapData>
 * 電文に指定する座標位置に吹き出しを作る
 */
maskat.googleMap.infoWinAtLatLngTeleConsumer={};
maskat.googleMap.infoWinAtLatLngTeleConsumer.consume=function(targetObj,teleNode){
    if ((targetObj==null) || !(targetObj instanceof maskat.widget.GoogleMap)){
        throw new MaskatError({name: "infoWinAtLatLngTeleConsumerエラー",
                         message: "targetObjはmaskat.widget.GoogleMapではありません",
                         fileName: "googleMapEx.js",
                         functionName: "maskat.googleMap.infoWinAtLatLngTeleConsumer.consume"});
    }
    //電文にteleNodeは一個しかないであるはず
    var lat = maskat.xpath(teleNode[0], 'lat/text()');
    var lng = maskat.xpath(teleNode[0], 'lng/text()');
    var text = maskat.xpath(teleNode[0], 'text/text()');
    targetObj.openInfoWindow(lat,lng,text);
}
ObjWrapper.registerTeleConsumer("googleMap.infoWinAtLatLng",maskat.googleMap.infoWinAtLatLngTeleConsumer);

/**
 * 電文サンプル<mapData><lat>123.456</lat><lng>12.23</lng><text>吹き出しテキスト</text></mapData>
 * 電文に指定する座標でマーカーを作って、マーカーのonclick度にテキスト吹き出しを表示
 */
maskat.googleMap.markExAtLatLngTeleConsumer={};
maskat.googleMap.markExAtLatLngTeleConsumer.consume=function(targetObj,teleNode){
    if ((targetObj==null) || !(targetObj instanceof maskat.widget.GoogleMap)){
        throw new MaskatError({name: "markExAtLatLngTeleConsumerエラー",
                         message: "targetObjはmaskat.widget.GoogleMapではありません",
                         fileName: "googleMapEx.js",
                         functionName: "maskat.googleMap.markExAtLatLngTeleConsumer.consume"});
    }
    //電文にteleNodeは一個しかないであるはず
    var lat = maskat.xpath(teleNode[0], 'lat/text()');
    var lng = maskat.xpath(teleNode[0], 'lng/text()');
    var text = maskat.xpath(teleNode[0], 'text/text()');
    targetObj.setMarkerAt(lat,lng);
    GEvent.addListener(targetObj.map, 'click', function(overlay, point) {
        if (overlay && overlay.openInfoWindow!=null) {
          overlay.openInfoWindow(document.createTextNode(text));
        }
    });
}
ObjWrapper.registerTeleConsumer("googleMap.markExAtLatLng",maskat.googleMap.markExAtLatLngTeleConsumer);


/**
 * 電文サンプル
 * <mapData><lat>123.456</lat><lng>12.23</lng><name>吹き出しテキスト１</name></mapData>
 * <mapData><lat>122.334</lat><lng>32.23</lng><name>吹き出しテキスト２</name></mapData>
 * 電文に指定する座標でマーカーを作って、マーカーのonclick度にテキスト吹き出しを表示
 */
maskat.googleMap.marksExAtLatLngTeleConsumer={};
maskat.googleMap.marksExAtLatLngTeleConsumer.consume=function(targetObj,teleNode){
    if ((targetObj==null) || !(targetObj instanceof maskat.widget.GoogleMap)){
        throw new MaskatError({name: "marksExAtLatLngTeleConsumerエラー",
                         message: "targetObjはmaskat.widget.GoogleMapではありません",
                         fileName: "googleMapEx.js",
                         functionName: "maskat.googleMap.marksExAtLatLngTeleConsumer.consume"});
    }
    //電文にteleNodeは一個しかないであるはず
    for (var i=0;i<teleNode.length;i++){
        var lat = maskat.xpath(teleNode[i], 'lat/text()');
        var lng = maskat.xpath(teleNode[i], 'lng/text()');
        var text = maskat.xpath(teleNode[i], 'name/text()');
	    var mp = new GLatLng(lat, lng);
       	targetObj.map.addOverlay(maskat.googleMap.createMarker(mp,text));
    }
}
ObjWrapper.registerTeleConsumer("googleMap.marksExAtLatLng",maskat.googleMap.marksExAtLatLngTeleConsumer);

maskat.googleMap.createMarker = function (point, text) {
  var marker = new GMarker(point);
  GEvent.addListener(marker, "click", function() {
    marker.openInfoWindow(text);
  });
  return marker;
}

//電文メーカー
maskat.googleMap.latLngTeleMaker={};
maskat.googleMap.latLngTeleMaker.make = function(obj,validator,sourceNode){
    if ((obj==null) || !(obj instanceof maskat.widget.GoogleMap)){
        throw new MaskatError({name: "latLngTeleMakerエラー",
                         message: "objはmaskat.widget.GoogleMapではありません",
                         fileName: "googleMapEx.js",
                         functionName: "maskat.googleMap.latLngTeleMaker.make"});
    }
    var center = obj.getCenter();
    var content = "<lat>"+center.lat()+"</lat><lng>"+center.lng()+"</lng>";
    
    var nodeName = maskat.xpath(sourceNode,"@node");
    if (nodeName!=null)
      return "<" + nodeName + ">" + content + "</" + nodeName + ">";
    else
      return content;
}
ObjWrapper.registerTeleMaker("googleMap.latLng",maskat.googleMap.latLngTeleMaker);


maskat.googleMap.panToLatLngLocalWorker={};
maskat.googleMap.panToLatLngLocalWorker.work = function(obj,inObj){
    if ((obj==null) || !(obj instanceof maskat.widget.GoogleMap)){
        throw new MaskatError({name: "panToLatLngLocalWorkerエラー",
                         message: "objはmaskat.widget.GoogleMapではありません",
                         fileName: "googleMapEx.js",
                         functionName: "maskat.googleMap.panToLatLngLocalWorker.work"});
    }
    if (inObj == null){
        return;//TODO エラーをスロー？
    }
    obj.setCenter(inObj.lat,inObj.lng);
}
ObjWrapper.registerLocalWorker("googleMap.panToLatLng",maskat.googleMap.panToLatLngLocalWorker);

maskat.googleMap.markAtLatLngLocalWorker={};
maskat.googleMap.markAtLatLngLocalWorker.work=function(targetObj,inObj){
    if ((targetObj==null) || !(targetObj instanceof maskat.widget.GoogleMap)){
        throw new MaskatError({name: "markAtLatLngLocalWorkerエラー",
                         message: "targetObjはmaskat.widget.GoogleMapではありません",
                         fileName: "googleMapEx.js",
                         functionName: "maskat.googleMap.markAtLatLngLocalWorker.consume"});
    }
    //電文にteleNodeは一個しかないであるはず
    targetObj.setMarkerAt(inObj.lat,inObj.lng);
}
ObjWrapper.registerLocalWorker("googleMap.markAtLatLng",maskat.googleMap.markAtLatLngLocalWorker);

maskat.googleMap.marksExAtLatLngLocalWorker={};
maskat.googleMap.marksExAtLatLngLocalWorker.work=function(targetObj,inObj){
    if ((targetObj==null) || !(targetObj instanceof maskat.widget.GoogleMap)){
        throw new MaskatError({name: "marksExAtLatLngLocalWorkerエラー",
                         message: "targetObjはmaskat.widget.GoogleMapではありません",
                         fileName: "googleMapEx.js",
                         functionName: "maskat.googleMap.marksExAtLatLngLocalWorker.consume"});
    }
    //inObjは配列
    for (var i=0;i<inObj.length;i++){
        var oneObj = inObj[i];
	    var mp = new GLatLng(oneObj.lat, oneObj.lng);
       	targetObj.map.addOverlay(maskat.googleMap.createMarker(mp,oneObj.name));
    }
}
ObjWrapper.registerLocalWorker("googleMap.marksExAtLatLng",maskat.googleMap.marksExAtLatLngLocalWorker);

maskat.googleMap.infoWinAtLatLngLocalWorker={};
maskat.googleMap.infoWinAtLatLngLocalWorker.work = function(obj,inObj){
    if ((obj==null) || !(obj instanceof maskat.widget.GoogleMap)){
        throw new MaskatError({name: "infoWinAtLatLngLocalWorkerエラー",
                         message: "objはmaskat.widget.GoogleMapではありません",
                         fileName: "googleMapEx.js",
                         functionName: "maskat.googleMap.infoWinAtLatLngLocalWorker.work"});
    }
    if (inObj == null){
        return;//TODO エラーをスロー？
    }
    obj.openInfoWindow(inObj.lat,inObj.lng,inObj.text);
}
ObjWrapper.registerLocalWorker("googleMap.infoWinAtLatLng",maskat.googleMap.infoWinAtLatLngLocalWorker);

maskat.googleMap.storeLatLngLocalWorker={};
maskat.googleMap.storeLatLngLocalWorker.work = function(obj,inObj,targetNode){
    //inObjはGoogleMapオブジェクト
    if ((inObj==null) || !(inObj instanceof maskat.widget.GoogleMap)){
        throw new MaskatError({name: "storeLatLngLocalWorkerエラー",
                         message: "inObjはmaskat.widget.GoogleMapではありません",
                         fileName: "googleMapEx.js",
                         functionName: "maskat.googleMap.storeLatLngLocalWorker.work"});
    }
    if (obj == null){
        var outName = maskat.xpath(targetNode, '@out');
        eval(outName+"={};");
        obj = eval(outName);
    }
    var center = inObj.getCenter();
    obj.lat = center.lat();
    obj.lng = center.lng();
}
ObjWrapper.registerLocalWorker("googleMap.storeLatLng",maskat.googleMap.storeLatLngLocalWorker);
