var module_map={
   maps:{}
   ,markers:{}
   ,defaultMap:''
   ,init:function(mapId,type,conf){
      if($('#'+mapId).length<=0) return;
      module_map.defaultMap=mapId;
      var mapOptions = {
         zoom: Number(conf.zoom),
         mapTypeId: google.maps.MapTypeId.ROADMAP,
         center: new google.maps.LatLng(conf.lat,conf.lng)
      };
      module_map.maps[mapId] = new google.maps.Map(document.getElementById(mapId),mapOptions);
      module_map.markers[mapId]={};
      if(typeof(conf.markers)=='string'){
         conf.markers=eval(conf.markers);
      }
      switch(type){
        default://map with markers
        module_map.enableSearch(mapId);
	var markerName='marker';
	var val=$('#'+mapId+'op').val();
	if(val.length>0){
	   var latLng=eval(val);
	   if(isset(latLng)) latLng=module_map.toKaLa(latLng);
	   module_map.maps[mapId].setCenter(new google.maps.LatLng(latLng.Ka,latLng.La));
	   module_map.addDraggableMarker(mapId,latLng,markerName);
	}
	google.maps.event.addListener(module_map.maps[mapId],'click',function(param){
	       module_map.addDraggableMarker(mapId,param.latLng,markerName);
	});
	break;
	case 'view':
	   if(isset(conf.markers)){
	     if(conf.markers[0].cord) conf.markers[0].cord=eval(conf.markers[0].cord);
	     var first=new google.maps.LatLng(conf.markers[0].cord.Ka,conf.markers[0].cord.La);
	     var bounds=new google.maps.LatLngBounds(first,first);
	     var mc=0;
	     $.each(conf.markers,function(k,v){
	       if(typeof(v.cord)=='string'&&v.cord) v.cord=eval(v.cord);
	       if(isset(v.cord.Ka)&&isset(v.cord.La)){
	         var cord=new google.maps.LatLng(v.cord.Ka,v.cord.La);
		 module_map.addMarker(mapId,v.cord,(isset(v.name)?v.name:markerName+k),'','',v.info);
		 bounds.extend(cord);
		 mc++;
	       } 
	     });
	     if(mc>1) module_map.maps[mapId].fitBounds(bounds);
	   }
	break;
      }
   }
   ,openInfoW:function(markername,mapid){
     if(!isset(mapid)) var mapid=module_map.defaultMap;
     $.each(module_map.markers[mapid],function(k,v){
       if(isset(v.infoWindow)) v.infoWindow.close();
     });
     module_map.markers[mapid][markername].infoWindow.open(module_map.maps[mapid],module_map.markers[mapid][markername]);
   }
   ,enableSearch:function(mapId){
      var input = document.getElementById(mapId+'search');
        var autocomplete = new google.maps.places.Autocomplete(input);
	var geocoder = new google.maps.Geocoder();
        var infowindow = new google.maps.InfoWindow();
        var marker = new google.maps.Marker({
          map: module_map.maps[mapId]
        });
	$(input).keypress(function(e){
	   if((e.keyCode?e.keyCode:e.which)==13){
	      e.preventDefault();
	      infowindow.close();
	      var addr=$('div.pac-container div.pac-item:first').html().replace(/(<([^>]+)>)/ig,'');
	      geocoder.geocode({address:addr},function(r,s){
	         if(s=='OK'){
		    module_map.setLocationMarker(mapId,r[0],marker,infowindow);
		    //module_map.maps[mapId].setCenter(r[0].geometry.location);
		 }
	      });
	   }
	});
        autocomplete.bindTo('bounds', module_map.maps[mapId]);


        google.maps.event.addListener(autocomplete, 'place_changed', function() {
          infowindow.close();
          var place = autocomplete.getPlace();
	  module_map.setLocationMarker(mapId,place,marker,infowindow);
        });
   }
   ,setLocationMarker:function(mapId,place,marker,infowindow){
          if (place.geometry.viewport) {
            module_map.maps[mapId].fitBounds(place.geometry.viewport);
          } else {
            module_map.maps[mapId].setCenter(place.geometry.location);
            module_map.maps[mapId].setZoom(17);  // Why 17? Because it looks good.
          }
          var image = new google.maps.MarkerImage('');
          marker.setIcon(image);
          marker.setPosition(place.geometry.location);

          var address = '';
          if (place.address_components) {
            address = [(place.address_components[0] &&
                        place.address_components[0].short_name || ''),
                       (place.address_components[1] &&
                        place.address_components[1].short_name || ''),
                       (place.address_components[2] &&
                        place.address_components[2].short_name || '')
                      ].join(' ');
          }
          infowindow.setContent((isset(place.name)?'<div><strong>'+place.name+'</strong><br>':'')
	  		        +address);
          infowindow.open(module_map.maps[mapId], marker);
   }
   ,addDraggableMarker:function(id,latLng,markerName){
       if(isset(latLng)) latLng=module_map.toKaLa(latLng);
       module_map.addMarker(id,latLng,markerName,{draggable:true}
 			,{dragend:function(e){
			if(isset(e.latLng)) e.latLng=module_map.toKaLa(e.latLng);
		   	$('#'+id+'op').val(fm2.serialize(e.latLng));
       }});
       $('#'+id+'op').val(fm2.serialize(latLng));
   }
   ,toKaLa:function(position){
      if(isset(position.Na)){
        position.Ka=position.Na;
	position.La=position.Oa;
	delete position.Na;
	delete position.Oa;
      }
      return position;
   }
   ,addMarker:function(mapid,position,markername,conf,events,info){
      if(isset(position)) position=module_map.toKaLa(position);
      var param={
      	  	 map:module_map.maps[mapid]
		 ,position:(typeof(position.lat)=='number'&&typeof(position.lng)=='number'
		            ?new google.maps.LatLng(position.lat,position.lng)
			    :new google.maps.LatLng(position.Ka,position.La)
			    )
		 };
      if(typeof(conf)=='object') $.extend(param,conf)
      if(isset(module_map.markers[mapid][markername])){
         module_map.markers[mapid][markername].setOptions(param);
	 google.maps.event.clearInstanceListeners(module_map.markers[mapid][markername]);
      }
      else{
         module_map.markers[mapid][markername] = new google.maps.Marker(param);
      }
      if(typeof(events)=='object'){
         $.each(events,function(k,v){
	    google.maps.event.addListener(module_map.markers[mapid][markername],k,v);
	 });
      }
      if(isset(info)&&info.length>0){
         module_map.markers[mapid][markername].infoWindow=new google.maps.InfoWindow({content:info});
	 google.maps.event.addListener(module_map.markers[mapid][markername],'click',function(){
	    module_map.openInfoW(markername,mapid);
         });
      }
   }
};

