/*
	TODO:
	addMarker and move
	moveTo accepting string argument
*/
/**************************************
 * GOOGLE MAPS
 **************************************/
function GoogleMaps($mainObj){
	
	if(!$mainObj)
		return fb.info('ERRO: Map $mainObj is missing.');
		
	if(!window['G_DEFAULT_ICON'])
		return fb.info('ERRO: Google Maps include code is missing.');
		
	var _this = this;
	
	// this.markers['name'].customMarkerIco = {};
	// this.markers['name'].customMarkerOpt = {};
	// this.markers['name'].customMarker = {};
	// this.markers['name'].customMarkerIcoOver = {};
	// this.markers['name'].customMarkerOptOver = {};
	// this.markers['name'].customMarkerOver = {};
	
	/**************************************
	 * MAP OPTIONS
	 **************************************/
	//{
	this.setMapOptions = function($obj){
		/*
		$obj.controlType: "smallZoom" || "small", "large";
		$obj.miniMap: true;
		$obj.scale: true;
		$obj.mapType: true;
		*/
		
		if(!$obj) return;
		
		if($obj.controlType && this.mapControlType){
			this.removeMapOptions("controlType");
		}

		switch($obj.controlType){
			case 'small':
				this.mapControlType = new GSmallMapControl();
				break;
			case 'large':
				this.mapControlType = new GLargeMapControl();
				break;
			case 'smallZoom':
				this.mapControlType = new GSmallZoomControl();
				break;
				
		}

		if($obj.controlType && this.mapControlType){
			this.GMapObj.addControl(this.mapControlType);
		}

		if($obj.miniMap){
			this.removeMapOptions("miniMap");
			this.miniMap = new GOverviewMapControl();
			this.GMapObj.addControl(this.miniMap);
		}

		if($obj.scale){
			this.removeMapOptions("scale");
			this.scale = new GScaleControl();
			this.GMapObj.addControl(this.scale);
		}

		if($obj.mapType){
			this.removeMapOptions("mapType");
			this.mapType = new GMapTypeControl();
			this.GMapObj.addControl(this.mapType);
		}
	}
	this.removeMapOptions = function(name){
		switch(name){
			case "controlType":
				this.GMapObj.removeControl(this.mapControlType);
				break;
			case "miniMap":
				this.GMapObj.removeControl(this.miniMap);
				break;
			case "scale":
				this.GMapObj.removeControl(this.scale);
				break;
			case "mapType":
				this.GMapObj.removeControl(this.mapType);
				break;
			default:
				this.GMapObj.removeControl(this.mapControlType);
				this.GMapObj.removeControl(this.miniMap);
				this.GMapObj.removeControl(this.scale);
				this.GMapObj.removeControl(this.mapType);
				break;
		}
	}
	//}

	/**************************************
	 * MARKER STUFF
	 **************************************/
	//{
	
	//{ CREATE ICON
	this.applyIcon = function(name,$obj){
		
		if(!$obj)return;
		
		var temp = null;
		temp = this.cloneObject(this.markers.global.customMarkerIco);
		
		if($obj){
			temp.image = $obj.image || temp.image;
			temp.shadow = "";
			//temp.shadow = $obj.shadow || ($obj.image ? ($obj.image.slice(0,$obj.image.indexOf('.png'))+"_shadow"+$obj.image.slice($obj.image.indexOf('.png'))) : temp.shadow);
			//temp.transparent = $obj.transparent || ($obj.image ? $obj.image.slice(0,$obj.image.indexOf('.png'))+"_ie"+$obj.image.slice($obj.image.indexOf('.png')) : temp.transparent);
			
			if($obj.iconSize){
				if($obj.iconSize.length > 1){
					temp.iconSize = new GSize($obj.iconSize[0],$obj.iconSize[1]);
					// fb.info('temp.iconSize: '+temp.iconSize);
					//temp.shadowSize = ($obj.shadowSize && $obj.shadowSize.length > 1) ? new GSize($obj.shadowSize[0],$obj.shadowSize[1]) : new GSize($obj.iconSize[0]*2,$obj.iconSize[1]);
					temp.iconAnchor = ($obj.iconAnchor && $obj.iconAnchor.length > 1) ? new GPoint($obj.iconAnchor[0],$obj.iconAnchor[1]) : new GPoint($obj.iconSize[0]/2,$obj.iconSize[1]); 
					temp.infoWindowAnchor = ($obj.infoWindowAnchor && $obj.infoWindowAnchor.length > 1) ? new GPoint($obj.infoWindowAnchor[0],$obj.infoWindowAnchor[1]) : new GPoint($obj.iconSize[0],$obj.iconSize[1]);
					temp.imageMap = ($obj.imageMap && $obj.imageMap.length > 1) ? $obj.imageMap : [0,0, $obj.iconSize[0],0, $obj.iconSize[0],$obj.iconSize[0]*2, 0,$obj.iconSize[0]*2, 0,0];
					temp.dragCrossSize = $obj.dragCrossSize || temp.iconSize;
					temp.dragCrossAnchor = $obj.dragCrossAnchor || temp.iconAnchor;
				}
			}
			temp.maxHeight = $obj.maxHeight || temp.maxHeight;
			temp.dragCrossImage = $obj.dragCrossImage || temp.image;
			return new GIcon(temp);
		}else{
			return false;
		}
	}
	//}
	//{ SET GLOBAL ICON
	this.setGlobalIcon = function($obj){
		this.markers.global.customMarkerIco = this.applyIcon('global',$obj);
		this.markers.global.customMarkerIcoOver = $mainObj.globalIconOver;
	}
	//}
	//{ ADD MARKER
	this.addMarker = function(name,$obj){
		/*
		name = "markerName";
		$obj.pos = []; || alert(ERRO);
		$obj.icon = {} || this.globalIcon;

		$obj.markerOpt = {};
			$obj.markerOpt.icon = $obj.icon;
			$obj.markerOpt.draggable = true;
			$obj.markerOpt.clickable = true;
		
		$obj.click = function($obj.overElement){} || this.globalClick;
		$obj.mouseover = function($obj.overElement){} || this.globalMouseOver;
		$obj.mouseoout = function($obj.overElement){} || this.globalMouseOut;
		$obj.labelElm = DOM Node;
		*/
		
		//{ debug
		if(!$obj) return alert('addMarker ERROR: $obj is not defined');
		if(!$obj.pos) return alert('addMarker ERROR: $obj.pos is not defined');
		if(!name) return alert('addMarker ERROR: "name" is not defined');
		if(this.markers[name]) return alert('addMarker ERROR: The name "'+name+'" is already been used');
		//}
		
		//{ initiate obj
		var opt = null;
		var ico = null;
		var icoOver = null;
		var pos = null;

		this.markers[name] = {};
		this.markers[name].pos = [$obj.pos[0],$obj.pos[1]];
		this.markers[name].posObj = new GLatLng(this.markers[name].pos[0],this.markers[name].pos[1]);
		this.allMarkers[this.allMarkers.length] = name;
		opt = this.markers[name].customMarkerOpt = {};
		//}
		
		
		//{set icon
		ico = this.markers[name].customMarkerIco = this.applyIcon(name,$obj.icon) || this.markers['global'].customMarkerIco;
		
		// ObjectUtil.list(ico);
		
		this.markers[name].customMarkerIcoOver = $obj.iconOver || this.markers['global'].customMarkerIcoOver;
		opt.icon = ico;
		opt.draggable = $obj.markerOpt ? $obj.markerOpt.draggable : false;
		opt.clickable = $obj.markerOpt ? $obj.markerOpt.clickable : (($obj.click || this.markers['global'].customMarkerIcoOver) ? true : false);
		//}
		
		//marker object based on the name
		this.markers[name].customMarker = new GMarker(this.markers[name].posObj,opt);
		
		//record anchor position in pixels related to the document
		pos = this.getMarkerPositionInPixel(name);
		this.markers[name].pos = [pos[0],pos[1]];
		
		//{ handlers
		this.addMouseOverHandler(name,$obj.mouseover,$obj.extra);
		this.addMouseOutHandler(name,$obj.mouseout,$obj.extra);
		if($obj.click)
			this.addClickHandler(name,$obj.click,$obj.extra);
		// this.markers[name].labelElm = $obj.labelElm || null;

		//}

		//put Marker on the map
		
		// ObjectUtil.list(this.markers[name].customMarker);
		
		this.GMapObj.addOverlay(this.markers[name].customMarker);
		if($obj.moveTo === true)
			this.moveTo(name);
	}
	//}
	
	//{ GET MARKER POSITION IN PIXEL
	this.getMarkerPositionInPixel = function(name){
		this.actMarker = this.markers[name];
		var map = this.GMapObj;
		var mapPos = map.getCurrentMapType().getProjection().fromLatLngToPixel(map.getBounds().getNorthEast(),map.getZoom());
		var markerPos = map.getCurrentMapType().getProjection().fromLatLngToPixel(this.actMarker.customMarker.getPoint(),map.getZoom());
		var posValues = [];
		posValues[0] = markerPos.x + this.mapElm.offsetWidth - mapPos.x + this.actMarker.customMarkerIco.iconSize.width - this.actMarker.customMarkerIco.iconAnchor.x + findPos(this.mapElm)[0];
		
		// new ObjectUtil(this.actMarker.customMarkerIco,'box').list();
		
		posValues[1] = markerPos.y - mapPos.y - this.actMarker.customMarkerIco.iconSize.height + findPos(this.mapElm)[1];
		return posValues;
	}
	this.actLabel = null;
	this.insertElm = function($obj){

		this.actLabel = $obj.elm;
	
		var xpos = $obj.pos[0]+($obj.margin?$obj.margin[0]:0);
		var ypos = $obj.pos[1]+($obj.margin?$obj.margin[1]:0);
		
		if(!this.mouseOut){
			$obj.elm.style.visibility = "hidden";
			sDiv($obj.elm);
		}

		if(xpos > (findPos(this.mapElm)[0] + this.mapElm.offsetWidth - $obj.elm.offsetWidth))
			xpos -= this.actMarker.customMarkerIco.iconSize.width + $obj.elm.offsetWidth + ($obj.margin?$obj.margin[0]*2:0);

		if(ypos > (findPos(this.mapElm)[0] + this.mapElm.offsetHeight - $obj.elm.offsetHeight))
			ypos -= $obj.elm.offsetHeight + ($obj.margin?$obj.margin[1]*2:0);
		
		var pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(xpos,ypos));
		this.mouseOut = false;
		pos.apply($obj.elm);
		
		setTimeout(function(){
			// fb.info("insertElm: "+_this.mouseOut);
			if(!_this.mouseOut){
				sDiv($obj.elm);
				$obj.elm.style.visibility = "visible";
			}
		},$obj.delay ? $obj.delay*1000 : 0);
		
		removeEvent($obj.elm,'mouseover',this.elmMouseOverFnc);
		removeEvent($obj.elm,'mouseout',this.elmMouseOutFnc);
		
		addEvent($obj.elm,'mouseover',this.elmMouseOverFnc);
		addEvent($obj.elm,'mouseout',this.elmMouseOutFnc);
		
		return $obj.elm;
	}
	this.removeElm = function($obj){
		this.mouseOut = true;
		setTimeout(function(){
			// fb.info("removeElm: "+_this.mouseOut);
			if(_this.mouseOut){
				hDiv($obj.elm);
				$obj.elm.style.visibility = "hidden";
			}
		},$obj.delay ? $obj.delay*1000 : 500);
	}
	this.elmMouseOverFnc = function(){_this.mouseOut = false;}
	this.elmMouseOutFnc = function(){_this.removeElm({elm:_this.actLabel});}
	//}
	
	//{ REMOVE MARKER
	this.removeMarker = function(name){
		this.GMapObj.removeOverlay(this.markers[name].customMarker);
		this.markers[name] = null;
	}
	//}
	//{ REMOVE ALL MARKERS
	this.removeAllMarkers = function(){
		for(var a in this.markers)
			if(a != "global")
				this.removeMarker(a);
	}
	//}
	
	//{ ADD HANDLER
	this.addMouseOverHandler = function(name,fnc,extra){
		var obj = this.markers[name];
		obj.mouseover = fnc || null;
		GEvent.addListener(obj.customMarker,"mouseover",function(){
			if(obj.customMarkerIcoOver)
				obj.customMarker.setImage(obj.customMarkerIcoOver);
			if(typeof(obj.mouseover) == 'function')obj.mouseover(_this.getMarkerPositionInPixel(name),extra);
		});
	}
	this.runMouseOver = function(name,fnc,extra){
		var obj = this.markers[name];
		if(fnc)this.addMouseOverHandler(name,fnc);

		if(obj.customMarkerIcoOver)
			obj.customMarker.setImage(obj.customMarkerIcoOver);
		if(typeof(obj.mouseover) == 'function')obj.mouseover(_this.getMarkerPositionInPixel(name),extra);
	}

	this.addMouseOutHandler = function(name,fnc,extra){
		var obj = this.markers[name];
		obj.mouseout = fnc || null;
		GEvent.addListener(obj.customMarker,"mouseout",function(){
			if(obj.customMarkerIco.image)
				obj.customMarker.setImage(obj.customMarkerIco.image);
			if(typeof(obj.mouseout) == 'function')obj.mouseout(_this.getMarkerPositionInPixel(name),extra);
		});
	}
	this.runMouseOut = function(name,fnc,extra){
		var obj = this.markers[name];
		if(fnc)this.addMouseOutHandler(name,fnc);

		if(obj.customMarkerIco.image)
			obj.customMarker.setImage(obj.customMarkerIco.image);
		if(typeof(obj.mouseout) == 'function')obj.mouseout(_this.getMarkerPositionInPixel(name),extra);
	}

	this.addClickHandler = function(name,fnc,extra){
		var obj = this.markers[name];
		obj.click = fnc || null;
		GEvent.addListener(obj.customMarker,"click",function(){
			if(typeof(obj.click) == 'function')obj.click(_this.getMarkerPositionInPixel(name),extra);
		});
	}
	this.runClick = function(name,fnc,extra){
		var obj = this.markers[name];
		if(fnc)this.runClick(name,fnc);
		if(typeof(obj.click) == 'function')obj.click(_this.getMarkerPositionInPixel(name),extra);
	}
	//}
	
	//{ MARKER POSITION
	this.getMarkerPosition = function(name){
		if(this.markers[name])
			return {
				obj:this.markers[name].posObj,
				array:[this.markers[name].posObj.y,this.markers[name].posObj.x]
			}
	}
	//}
	//}
	
	/**************************************
	 * UTIL STUFF
	 **************************************/
	//{
	this.cloneObject = function($obj){
		var temp = {};
		for(var i in $obj){
			temp[i] = $obj[i];
		}
		return temp;
	}
	this.returnElm = function($elm){
		return typeof($elm) == 'string' ? $($elm) : $elm;
	}
	//}

	/**************************************
	 * PROPERTIES
	 **************************************/
	//{
	this.allMarkers = [];
	this.markers = {};
	
	this.markers.global = {};
	this.markers.global.customMarkerIco = this.cloneObject(G_DEFAULT_ICON);
	this.markers.global.customMarkerIcoOver = this.cloneObject(G_DEFAULT_ICON);
	this.markers.global.onmouseover = null;
	this.markers.global.onmouseout = null;
	this.markers.global.onclick = null;
	//}
	
	/**************************************
	 * INIT
	 **************************************/
	//{
	if(GBrowserIsCompatible()){
		this.mapElm = this.returnElm($mainObj.elm);
		this.GMapObj = new GMap2(this.mapElm);
		
		// set map center
		this.GMapObj.setCenter(new GLatLng($mainObj.pos[0],$mainObj.pos[1]),$mainObj.zoom);
		
		// set map type
		switch($mainObj.type){
			case "satellite":
				this.GMapObj.setMapType(G_SATELLITE_MAP);
				break;
			case "hybrid":
				this.GMapObj.setMapType(G_HYBRID_MAP);
				break;
			case "normal":
			default:
				this.GMapObj.setMapType(G_NORMAL_MAP);
				break;
		}
		
		// apply Global Icon
		this.setGlobalIcon($mainObj.globalIcon || null);
		
		// map settings
		this.setMapOptions($mainObj.controls || null);
		
		//unload function
		addEvent(window,'unload',GUnload);
	}
	//}
	
	//{ get Map
	this.getMapDomElm = function(){
		return this.GMapObj.getContainer();
	}
	this.getMap = function(){
		return this.GMapObj;
	}
	this.getCanvas = function(){
		return {
			topRight:[this.GMapObj.getBounds().getNorthEast().lat(),this.GMapObj.getBounds().getNorthEast().lng()],
			bottomLeft:[this.GMapObj.getBounds().getSouthWest().lat(),this.GMapObj.getBounds().getSouthWest().lng()]
		}
	}
	this.moveTo = function(pos){
		this.GMapObj.panTo(typeof(pos)=='string' ? this.getMarkerPosition(pos).obj : new GLatLng(pos[0],pos[1]));
	}
	//}
}
/**************************************
 * RETURN NODE ELEMENT
 **************************************/
var NodeUtil = {
	getElm:function($elm){
		return typeof($elm) == 'string' ? $($elm) : $elm;
	}
}

/**************************************
 * OBJECT UTIL
 **************************************/
var ObjectUtil = {
	txt: '',
	list: function($obj,type){
		for(var i in $obj)
			this.txt += i+': '+$obj[i]+' -- '+typeof($obj[i])+'\n';
		
		switch(type){
			case 'write':
				document.write(this.txt.replace(/\n/g,'<br>'));
				break;
			case 'alert':
				alert(this.txt);
			case 'box':
			default:
				if(!$('boxObjectList'))
					createElm(null,[
						'div',{id:'boxObjectList', style:'position:absolute;top:0;left:0;width:100%;height:100%;overflow:auto;background:#fff;'},''						
					]);
				$('boxObjectList').innerHTML += '<p style="text-align:center;font-size:12px;font-weight:bold;"><a href="javascript:delElm(\'boxObjectList\');">[FECHAR]</a></p>'+this.txt.replace(/\n/g,'<br><br>');
				break;
		}
	}
}
