/*
/**
 * @author mpeccini
 */
/*
* DragZoomControl Class v1.3 
*  Copyright (c) 2005-2007, Andre Lewis, andre@earthcode.com
*
* Back Button functionality
*  Copyright (c)  2007, Richard Garland, papabear.newyork@gmail.com
*
* 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.
*
* This class lets you add a control to the map which will let the user
*  zoom by dragging a rectangle.
*  More info on original GZoom at http://earthcode.com
*
* Back Button functionality provides the user with a one click means to return the map state 
*  to its state prior to the DragZoom.  Sequential DragZooms are backed out in reverse order.
*/

/**
 * Constructor for DragZoomControl, which takes 3 option hashes and
 *  uses them to customize the control.
 * @param {opts_boxStyle} Named optional arguments:
 *   opts_boxStyle.opacity {Number} Opacity from 0-1
 *   opts_boxStyle.fillColor {String} Hex value of fill color
 *   opts_boxStyle.border {String} CSS-style declaration of border
 * @param {opts_other} Named optional arguments:
 *   opts_other.buttonHTML {String} The zoom button HTML in non-activated state
 *   opts_other.buttonStartingStyle {Object} A hash of css styles for the 
 *     zoom button which are common to both un-activated and activated state
 *   opts_other.buttonStyle {Object} A hash of css styles for the zoom button 
 *     which will be applied when the button is in un-activated state.
 *   opts_other.rightMouseZoomOutEnabled {Boolean} Whether to zoom out when a drag
 *     with the right mouse button occurs.
 *   opts_other.buttonZoomingHTML {String} HTML which is placed in the 
 *     zoom button when the button is activated. 
 *   opts_other.buttonZoomingStyle {Object} A hash of css styles for the 
 *    zoom button which will be applied when the button is activated.
 *   opts_other.overlayRemoveTime {Number} The number of milliseconds to wait before
 *     removing the rectangle indicating the zoomed-in area after the zoom has happened.
 *   opts_other.stickyZoomEnabled {Boolean} Whether or not the control stays in 
 *     "zoom mode" until turned off. When true, the user can zoom repeatedly, 
 *     until clicking on the zoom button again to turn zoom mode off.
 *   opts_other.backButtonEnabled {Boolean} enables Back Button functionality
 *   opts_other.backButtonHTML {String} The back button HTML
 *   opts_other.backButtonStyle {Object} A hash of css styles for the back button
 *     which will be applied when the button is created.
 *   opts_other.minDragSize {Number} The minimum size of the rectangle when it is
 *     released for a zoom to happen.
 * @param {opts_callbacks} Named optional arguments:
 *   opts_callbacks.buttonclick {Function} Called when the DragZoom is activated 
 *     by clicking on the "zoom" button. 
 *   opts_callbacks.dragstart {Function} Called when user starts to drag a rectangle.
 *     Callback args are x,y -- the PIXEL values, relative to the upper-left-hand 
 *     corner of the map, where the user began dragging.
 *   opts_callbacks.dragging {Function} Called repeatedly while the user is dragging.
 *     Callback args are startX,startY, currentX,currentY -- the PIXEL values of the 
 *     start of the drag, and the current drag point, respectively.
 *   opts_callbacks.dragend {Function} Called when the user releases the mouse button 
 *     after dragging the rectangle. Callback args are: NW {GLatLng}, NE {GLatLng}, 
 *     SE {GLatLng}, SW {GLatLng}, NW {GPoint}, NE {GPoint}, SE {GPoint}, SW {GPoint}.
 *     The first 4 are the latitudes/longitudes; the last 4 are the pixel coords on the map.
 *   opts_callbacks.backbuttonclick {Function} Called when the back button is activated 
 *     after the map context is restored. Callback args: methodCall (boolean) set true if
 *     this backbuttonclick was to restore context set by the mathod call, else false.
 * Method
 *    this.saveMapContext(text) Call to push map context onto the backStack and set the button text 
 *    this.initiateZoom() Call to simulate clicking the dragZoom button
 *    this.initiateZoomBack() Call to simulate clicking the dragZoom back button
 **/

/**
 *  Versions
 *  1.0 original version (v 189) 5/24/2007
 *  1.1 backbutton functionality added  (v 211) 7/30/2007
 *  1.2 bug fixes and 2 new methods 9/6/2007
 *    fix text selection conflict in IE
 *    fix align-text:center inheritance problem in IE
 *    create methods initiateZoom and initiateZoomBack which call buttonclick_() and backbuttonclick_()
 **/

///start here
function DragZoomControl(opts_boxStyle,opts_other,opts_callbacks){
	
	//alert("here")
	this.globals={
		draggingOn:false,cornerTopDiv:null,
		cornerRightDiv:null,
		cornerBottomDiv:null,
		cornerLeftDiv:null,
		mapPosition:null,
		outlineDiv:null,
		mapWidth:0,
		mapHeight:0,
		mapRatio:0,
		startX:0,
		startY:0,
		borderCorrection:0};
		
	this.globals.style={
		opacity:.2,
		fillColor:"#000",
		border:"2px solid blue"
		};
		
	var style=this.globals.style;
		for(var s in opts_boxStyle){
			style[s]=opts_boxStyle[s]
		}
		
	var borderStyleArray=style.border.split(' ');
	style.outlineWidth=parseInt(borderStyleArray[0].replace(/\D/g,''));style.outlineColor=borderStyleArray[2];
	style.alphaIE='alpha(opacity='+(style.opacity*100)+')';
	this.globals.backStack=[];
	this.globals.options={
		buttonHTML:'zoom ...',
		buttonStartingStyle:{width:'52px',border:'1px solid black',padding:'2px'},
		buttonStyle:{background:'#FFF'},
		backButtonHTML:'<img src="images/nav_buttons/back_small.gif" />',
		backButtonStyle:{display:'none'},
		buttonZoomingHTML:'Drag a region on the map',
		buttonZoomingStyle:{background:'#FF0'},
		overlayRemoveTime:600,
		backButtonEnabled:true,
		stickyZoomEnabled:false,
		rightMouseZoomOutEnabled:true,
		minDragSize:0
	};
		for(var s in opts_other){
			this.globals.options[s]=opts_other[s]
		}
			
		if(opts_callbacks==null){
			opts_callbacks={}
			}
	this.globals.callbacks=opts_callbacks
};

DragZoomControl.prototype=new GControl();

DragZoomControl.prototype.saveMapContext=function(text){
	if(this.globals.options.backButtonEnabled){
		this.saveBackContext_(text,true);
		this.globals.backButtonDiv.style.display='block'
		}
	};
	
DragZoomControl.prototype.initiateZoom=function(){
	this.buttonclick_()
};

DragZoomControl.prototype.initiateZoomBack=function(){
	if(this.globals.options.backButtonEnabled)
		this.backbuttonclick_()
};

DragZoomControl.prototype.initButton_=function(buttonContainerDiv){
		var G=this.globals;
		var buttonDiv=document.createElement('div');
		buttonDiv.innerHTML=G.options.buttonHTML;
		DragZoomUtil.style([buttonDiv],{cursor:'pointer',zIndex:200});
		DragZoomUtil.style([buttonDiv],G.options.buttonStartingStyle);
		DragZoomUtil.style([buttonDiv],G.options.buttonStyle);buttonContainerDiv.appendChild(buttonDiv);
		return buttonDiv
};

DragZoomControl.prototype.initBackButton_=function(buttonContainerDiv){
	var G=this.globals;
	var backButtonDiv=document.createElement('div');
	backButtonDiv.innerHTML=G.options.backButtonHTML;
	DragZoomUtil.style([backButtonDiv],{cursor:'pointer',zIndex:200});
	DragZoomUtil.style([backButtonDiv],G.options.backButtonStartingStyle);
	DragZoomUtil.style([backButtonDiv],G.options.backButtonStyle);
	buttonContainerDiv.appendChild(backButtonDiv);
	return backButtonDiv
};

DragZoomControl.prototype.setButtonMode_=function(mode){
	var G=this.globals;
	if(mode=='zooming'){
		G.buttonDiv.innerHTML=G.options.buttonZoomingHTML;
		DragZoomUtil.style([G.buttonDiv],G.options.buttonStartingStyle);
		DragZoomUtil.style([G.buttonDiv],G.options.buttonZoomingStyle)}
	else{G.buttonDiv.innerHTML=G.options.buttonHTML;
		DragZoomUtil.style([G.buttonDiv],G.options.buttonStartingStyle);
		DragZoomUtil.style([G.buttonDiv],G.options.buttonStyle)
	}
};
		
DragZoomControl.prototype.initialize=function(map){
	var G=this.globals;
	var me=this;var mapDiv=map.getContainer();
	var buttonContainerDiv=document.createElement("div");
	DragZoomUtil.style([buttonContainerDiv],{cursor:'pointer',zIndex:150});
	var buttonDiv=this.initButton_(buttonContainerDiv);
	var backButtonDiv=this.initBackButton_(buttonContainerDiv);
	mapDiv.appendChild(buttonContainerDiv);
	var zoomDiv=document.createElement("div");
	var DIVS_TO_CREATE=['outlineDiv','cornerTopDiv','cornerLeftDiv','cornerRightDiv','cornerBottomDiv'];
		for(var i=0;i<DIVS_TO_CREATE.length;i++){
			var id=DIVS_TO_CREATE[i];
			var div=document.createElement("div");
			DragZoomUtil.style([div],{position:'absolute',display:'none'});
			zoomDiv.appendChild(div);
			G[id]=div
		}
			
	DragZoomUtil.style([zoomDiv],{position:'absolute',display:'none',overflow:'hidden',cursor:'crosshair',zIndex:101});
	mapDiv.appendChild(zoomDiv);GEvent.addDomListener(buttonDiv,'click',function(e){me.buttonclick_(e)});
	GEvent.addDomListener(backButtonDiv,'click',function(e){me.backbuttonclick_(e)});
	GEvent.addDomListener(zoomDiv,'mousedown',function(e){me.coverMousedown_(e)});
	GEvent.addDomListener(document,'mousemove',function(e){me.drag_(e)});
	GEvent.addDomListener(document,'mouseup',function(e){me.mouseup_(e)});
	G.mapPosition=DragZoomUtil.getElementPosition(mapDiv);
	G.buttonDiv=buttonDiv;
	G.backButtonDiv=backButtonDiv;
	G.mapCover=zoomDiv;
	G.map=map;
	G.borderCorrection=G.style.outlineWidth*2;this.setDimensions_();
	this.initStyles_();
	G.mapCover.onselectstart=function(){return false};
	return buttonContainerDiv
};

DragZoomControl.prototype.getDefaultPosition=function(){
	return new GControlPosition(G_ANCHOR_TOP_RIGHT,new GSize(zoomRight,zoomTop))
};

DragZoomControl.prototype.coverMousedown_=function(e){
	var G=this.globals;
	var pos=this.getRelPos_(e);
	G.startX=pos.left;G.startY=pos.top;
	if(e.which){
		var rightMouse=(e.which!=1)
	}else if(e.button){
		var rightMouse=(e.button!=1)}G.draggingRightMouse=rightMouse;
		DragZoomUtil.style([G.mapCover],{background:'transparent',opacity:1,filter:'alpha(opacity=100)'});
		DragZoomUtil.style([G.outlineDiv],{left:G.startX+'px',top:G.startY+'px',display:'block',width:'1px',height:'1px'});
		G.draggingOn=true;
		G.cornerTopDiv.style.top=(G.startY-G.mapHeight)+'px';
		G.cornerTopDiv.style.display='block';
		G.cornerLeftDiv.style.left=(G.startX-G.mapWidth)+'px';
		G.cornerLeftDiv.style.top=G.startY+'px';
		G.cornerLeftDiv.style.display='block';
		G.cornerRightDiv.style.left=G.startX+'px';
		G.cornerRightDiv.style.top=G.startY+'px';
		G.cornerRightDiv.style.display='block';
		G.cornerBottomDiv.style.left=G.startX+'px';
		G.cornerBottomDiv.style.top=G.startY+'px';
		G.cornerBottomDiv.style.width='0px';
		G.cornerBottomDiv.style.display='block';
		if(G.callbacks.dragstart!=null){
			G.callbacks.dragstart(G.startX,G.startY)
		}return false
};
		
DragZoomControl.prototype.drag_=function(e){
	var G=this.globals;if(G.draggingOn){var pos=this.getRelPos_(e);
	var rect=this.getRectangle_(G.startX,G.startY,pos,G.mapRatio);
	if(rect.left){addX=-rect.width}else{addX=0}
	if(rect.top){
		addY=-rect.height
	}else{
		addY=0
	}
	DragZoomUtil.style([G.outlineDiv],{left:G.startX+addX+'px',top:G.startY+addY+'px',display:'block',width:'1px',height:'1px'});
	G.outlineDiv.style.width=rect.width+"px";
	G.outlineDiv.style.height=rect.height+"px";
	G.cornerTopDiv.style.height=((G.startY+addY)-(G.startY-G.mapHeight))+'px';
	G.cornerLeftDiv.style.top=(G.startY+addY)+'px';
	G.cornerLeftDiv.style.width=((G.startX+addX)-(G.startX-G.mapWidth))+'px';
	G.cornerRightDiv.style.top=G.cornerLeftDiv.style.top;
	G.cornerRightDiv.style.left=(G.startX+addX+rect.width+G.borderCorrection)+'px';
	G.cornerBottomDiv.style.top=(G.startY+addY+rect.height+G.borderCorrection)+'px';
	G.cornerBottomDiv.style.left=(G.startX-G.mapWidth+((G.startX+addX)-(G.startX-G.mapWidth)))+'px';
	G.cornerBottomDiv.style.width=(rect.width+G.borderCorrection)+'px';
	if(G.callbacks.dragging!=null){
		G.callbacks.dragging(G.startX,G.startY,rect.endX,rect.endY)
	}return false}};
	
DragZoomControl.prototype.mouseup_=function(e){var G=this.globals;
if(G.draggingOn){var pos=this.getRelPos_(e);
G.draggingOn=false;
var rect=this.getRectangle_(G.startX,G.startY,pos,G.mapRatio);
if(rect.left)rect.endX=rect.startX-rect.width;
if(rect.top)rect.endY=rect.startY-rect.height;
this.resetDragZoom_();
if(rect.width>=G.options.minDragSize&&rect.height>=G.options.minDragSize){var nwpx=new GPoint(rect.startX,rect.startY);
var nepx=new GPoint(rect.endX,rect.startY);
var sepx=new GPoint(rect.endX,rect.endY);
var swpx=new GPoint(rect.startX,rect.endY);
var nw=G.map.fromContainerPixelToLatLng(nwpx);
var ne=G.map.fromContainerPixelToLatLng(nepx);
var se=G.map.fromContainerPixelToLatLng(sepx);
var sw=G.map.fromContainerPixelToLatLng(swpx);
var zoomAreaPoly=new GPolyline([nw,ne,se,sw,nw],G.style.outlineColor,G.style.outlineWidth+1,.4);
try{G.map.addOverlay(zoomAreaPoly);
setTimeout(function(){G.map.removeOverlay(zoomAreaPoly)},G.options.overlayRemoveTime)}catch(e){}var polyBounds=zoomAreaPoly.getBounds();
var ne=polyBounds.getNorthEast();
var sw=polyBounds.getSouthWest();
var se=new GLatLng(sw.lat(),ne.lng());
var nw=new GLatLng(ne.lat(),sw.lng());
if(G.options.rightMouseZoomOutEnabled&&G.draggingRightMouse){var mapSpan=G.map.getBounds().toSpan();
var polySpan=polyBounds.toSpan();
var dSize=Math.max(mapSpan.lat()/polySpan.lat(),mapSpan.lng()/polySpan.lng());
var zoomLevel=G.map.getZoom()-Math.ceil(Math.log(dSize,2))}else{var zoomLevel=G.map.getBoundsZoomLevel(polyBounds)}var center=polyBounds.getCenter();
G.map.setCenter(center,zoomLevel);
if(G.callbacks.dragend!=null){G.callbacks.dragend(nw,ne,se,sw,nwpx,nepx,sepx,swpx)}}if(G.options.stickyZoomEnabled){this.initCover_();
if(G.options.backButtonEnabled)this.saveBackContext_(G.options.backButtonHTML,false);
G.backButtonDiv.style.display='none'}}};


DragZoomControl.prototype.setDimensions_=function(){var G=this.globals;
var mapSize=G.map.getSize();
G.mapWidth=mapSize.width;
G.mapHeight=mapSize.height;
G.mapRatio=G.mapHeight/G.mapWidth;
DragZoomUtil.style([G.mapCover,G.cornerTopDiv,G.cornerRightDiv,G.cornerBottomDiv,G.cornerLeftDiv],{top:'0px',left:'0px',width:G.mapWidth+'px',height:G.mapHeight+'px'})};


DragZoomControl.prototype.initStyles_=function(){var G=this.globals;
DragZoomUtil.style([G.mapCover,G.cornerTopDiv,G.cornerRightDiv,G.cornerBottomDiv,G.cornerLeftDiv],{filter:G.style.alphaIE,opacity:G.style.opacity,background:G.style.fillColor});
G.outlineDiv.style.border=G.style.border};


DragZoomControl.prototype.buttonclick_=function(){var G=this.globals;
G.backButtonDiv.style.display='none';
if(G.mapCover.style.display=='block'){this.resetDragZoom_();
if(G.options.backButtonEnabled){this.restoreBackContext_();
if(G.backStack.length==0)G.backButtonDiv.style.display='none'}}else{this.initCover_();
if(G.options.backButtonEnabled)this.saveBackContext_(G.options.backButtonHTML,false)}};


DragZoomControl.prototype.backbuttonclick_=function(){var G=this.globals;
if(G.options.backButtonEnabled&&G.backStack.length>0){this.restoreBackContext_();
if(G.callbacks['backbuttonclick']!=null){G.callbacks.backbuttonclick(G.methodCall)}}};


DragZoomControl.prototype.saveBackContext_=function(text,methodCall){var G=this.globals;
var backFrame={};
backFrame["center"]=G.map.getCenter();backFrame["zoom"]=G.map.getZoom();
backFrame["maptype"]=G.map.getCurrentMapType();
backFrame["text"]=G.backButtonDiv.innerHTML;backFrame["methodCall"]=methodCall;G.backStack.push(backFrame);
G.backButtonDiv.innerHTML=text};

DragZoomControl.prototype.restoreBackContext_=function(){var G=this.globals;var backFrame=G.backStack.pop();
G.map.setCenter(backFrame["center"],backFrame["zoom"],backFrame["maptype"]);G.backButtonDiv.innerHTML=backFrame["text"];
G.methodCall=backFrame["methodCall"];
if(G.backStack.length==0)G.backButtonDiv.style.display='none'};
DragZoomControl.prototype.initCover_=function(){var G=this.globals;G.mapPosition=DragZoomUtil.getElementPosition(G.map.getContainer());
this.setDimensions_();this.setButtonMode_('zooming');DragZoomUtil.style([G.mapCover],{display:'block',background:G.style.fillColor});
DragZoomUtil.style([G.outlineDiv],{width:'0px',height:'0px'});if(G.callbacks['buttonclick']!=null){G.callbacks.buttonclick()}};
DragZoomControl.prototype.getRelPos_=function(e){var pos=DragZoomUtil.getMousePosition(e);
var G=this.globals;return{top:(pos.top-G.mapPosition.top),left:(pos.left-G.mapPosition.left)}};
DragZoomControl.prototype.getRectangle_=function(startX,startY,pos,ratio){var left=false;var top=false;var dX=pos.left-startX;var dY=pos.top-startY;
if(dX<0){dX=dX*-1;left=true}if(dY<0){dY=dY*-1;top=true}delta=dX>dY?dX:dY;return{startX:startX,startY:startY,endX:startX+delta,endY:startY+parseInt(delta*ratio),width:delta,height:parseInt(delta*ratio),left:left,top:top}};
DragZoomControl.prototype.resetDragZoom_=function(){var G=this.globals;DragZoomUtil.style([G.mapCover,G.cornerTopDiv,G.cornerRightDiv,G.cornerBottomDiv,G.cornerLeftDiv],{display:'none',opacity:G.style.opacity,filter:G.style.alphaIE});
G.outlineDiv.style.display='none';this.setButtonMode_('normal');if(G.options.backButtonEnabled&&(G.backStack.length>0))G.backButtonDiv.style.display='block'};
var DragZoomUtil={};DragZoomUtil.gE=function(sId){return document.getElementById(sId)};
DragZoomUtil.getMousePosition=function(e){var posX=0;
var posY=0;if(!e)var e=window.event;
if(e.pageX||e.pageY){posX=e.pageX;posY=e.pageY}else if(e.clientX||e.clientY){posX=e.clientX+(document.documentElement.scrollLeft?document.documentElement.scrollLeft:document.body.scrollLeft);
posY=e.clientY+(document.documentElement.scrollTop?document.documentElement.scrollTop:document.body.scrollTop)}return{left:posX,top:posY}};
DragZoomUtil.getElementPosition=function(element){var leftPos=element.offsetLeft;
var topPos=element.offsetTop;
var parElement=element.offsetParent;
while(parElement!=null){leftPos+=parElement.offsetLeft;
topPos+=parElement.offsetTop;
parElement=parElement.offsetParent}return{left:leftPos,top:topPos}};
DragZoomUtil.style=function(elements,styles){if(typeof(elements)=='string'){elements=DragZoomUtil.getManyElements(elements)}for(var i=0;
i<elements.length;
i++){for(var s in styles){elements[i].style[s]=styles[s]}}};
DragZoomUtil.getManyElements=function(idsString){var idsArray=idsString.split(',');
var elements=[];for(var i=0;
i<idsArray.length;i++){elements[elements.length]=DragZoomUtil.gE(idsArray[i])};return elements};

