// base definition and inheritance


function GZoomControl(oBoxStyle,oOptions,oCallbacks) {
	//box style options
  GZoomControl.G.style = {
    nOpacity:0.0,
    sColor:"#000",
    sBorder:"2px solid blue"
  };
  var style=GZoomControl.G.style;
  for (var s in oBoxStyle) {style[s]=oBoxStyle[s]};
  var aStyle=style.sBorder.split(' ');
  style.nOutlineWidth=parseInt(aStyle[0].replace(/\D/g,''));
  style.sOutlineColor=aStyle[2];
  style.sIEAlpha='alpha(opacity='+(style.nOpacity*100)+')';
	
	// Other options
	GZoomControl.G.options={
		bForceCheckResize:false,
		sButtonHTML:'<img src=../images/icons/select_tool.gif /><span style="FONT-SIZE: 14px; COLOR: blue; TEXT-DECORATION: underline">Selection Tool</span>',
		oButtonStartingStyle:{width:'150px',border:'0px',padding:'0px 0px 0px 0px'},
		oButtonStyle:{},//background:'#FFF'},
		sButtonZoomingHTML:'<img src=../images/icons/select_tool_inset.gif /><span style="FONT-SIZE: 14px; COLOR: blue; TEXT-DECORATION: underline">Selection Tool</span>',
		oButtonZoomingStyle:{},//background:'#FFF'},
		nOverlayRemoveMS:6000,
		bStickyZoom:false
	};
	
	for (var s in oOptions) {GZoomControl.G.options[s]=oOptions[s]};
	
	// callbacks: buttonClick, dragStart,dragging, dragEnd
	if (oCallbacks == null) {oCallbacks={}};
	GZoomControl.G.callbacks=oCallbacks;
	

}



GZoomControl.prototype = new GControl();

//class globals
GZoomControl.G={
  bDragging:false,
  mct:null,
  mcr:null,
  mcb:null,
  mcl:null,
  mci:null,
  mcu:null,
	oMapPos:null,
	oOutline:null,
	nMapWidth:0,
	nMapHeight:0,
	nMapRatio:0,
	nStartX:0,
	nStartY:0,
	nBorderCorrect:0
};

GZoomControl.prototype.initButton_=function(oMapContainer) {
	var G=GZoomControl.G;
	var oButton = document.createElement('div');
	oButton.innerHTML=G.options.sButtonHTML;
	oButton.id='gzoom-control';
	acl.style([oButton],{cursor:'pointer',zIndex:200});
	acl.style([oButton],G.options.oButtonStartingStyle);
	acl.style([oButton],G.options.oButtonStyle);
	oMapContainer.appendChild(oButton);
	return oButton;
};

GZoomControl.prototype.setButtonMode_=function(sMode){
	var G=GZoomControl.G;
	if (sMode=='zooming') {
		G.oButton.innerHTML=G.options.sButtonZoomingHTML;
		acl.style([G.oButton],G.options.oButtonZoomingStyle);
	} else {
		G.oButton.innerHTML=G.options.sButtonHTML;
		acl.style([G.oButton],G.options.oButtonStyle);
	}
};

// ******************************************************************************************
// Methods required by Google maps -- initialize and getDefaultPosition
// ******************************************************************************************
GZoomControl.prototype.initialize = function(oMap) {
  var G=GZoomControl.G;
	var oMC=oMap.getContainer();
  //DOM:button
	var oButton=this.initButton_(oMC);

	//DOM:map covers
	var o = document.createElement("div");
  o.id='gzoom-map-cover';
	o.innerHTML='<div id="gzoom-outline" style="position:absolute;display:none;"></div><div id="gzoom-mct" style="position:absolute;display:none;"></div><div id="gzoom-mcl" style="position:absolute;display:none;"></div><div id="gzoom-mcr" style="position:absolute;display:none;"></div><div id="gzoom-mcb" style="position:absolute;display:none;"></div><div id="gzoom-mci" style="position:absolute;display:none;"></div><div id="gzoom-mcu" style="position:absolute;display:none;"></div>';
	acl.style([o],{position:'absolute',display:'none',overflow:'hidden',cursor:'crosshair',zIndex:101});
	oMC.appendChild(o);

  // add event listeners
	GEvent.addDomListener(oButton, 'click', GZoomControl.prototype.buttonClick_);
	GEvent.addDomListener(o, 'mousedown', GZoomControl.prototype.coverMousedown_);
	GEvent.addDomListener(document, 'mousemove', GZoomControl.prototype.drag_);
	GEvent.addDomListener(document, 'mouseup', GZoomControl.prototype.mouseup_);
	



  // get globals
	G.oMapPos=acl.getElementPosition(oMap.getContainer());
	G.oOutline=$id("gzoom-outline");	
	G.oButton=$id("gzoom-control");
	G.mc=$id("gzoom-map-cover");
	G.mct=$id("gzoom-mct");
	G.mcr=$id("gzoom-mcr");
	G.mcb=$id("gzoom-mcb");
	G.mcl=$id("gzoom-mcl");
	G.mci=$id("gzoom-mci");
	G.mcu=$id("gzoom-mcu");
	G.oMap = oMap;

	G.nBorderCorrect = G.style.nOutlineWidth*2;	
  this.setDimensions_();
  //this.initCover_();
  //styles
  this.initStyles_();







  debug("Finished Initializing gzoom control");  
  return oButton;
};


function clearBoxOverlays()
{
  var G=GZoomControl.G;
	G.oOutline.style.display='none';
}


// Default location for the control
GZoomControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(425, -48));
};

// ******************************************************************************************
// Private methods
// ******************************************************************************************
GZoomControl.prototype.coverMousedown_ = function(e){
  var G=GZoomControl.G;
  var oPos = GZoomControl.prototype.getRelPos_(e);
  debug("Mouse down at "+oPos.left+", "+oPos.top);
  G.nStartX=oPos.left;
  G.nStartY=oPos.top;
  
	acl.style([G.mc],{background:'transparent',opacity:1,filter:'alpha(opacity=100)'});
  
  G.bDragging=true;

  G.mcl.style.display='block';
  G.mct.style.display='block';
  G.mcr.style.display='block';
  G.mcb.style.display='block';
  G.mci.style.display='block';
  G.mcu.style.display='block';
  


	// invoke the callback if provided
	if (G.callbacks.dragStart !=null){G.callbacks.dragStart(G.nStartX,G.nStartY)};

  debug("mouse down done");
  return false;
};



GZoomControl.prototype.drag_=function(e){
  
  
  
  var G=GZoomControl.G;
  if(G.bDragging) {
    var oPos=GZoomControl.prototype.getRelPos_(e);
    oRec = GZoomControl.prototype.getRectangle_(G.nStartX,G.nStartY,oPos,G.nMapRatio);
   
   acl.style([G.oOutline],{left:oRec.nStartX+'px',top:oRec.nStartY+'px',display:'block'});
   
    G.oOutline.style.width=oRec.nWidth+"px";
    G.oOutline.style.height=oRec.nHeight+"px";
    
    
    G.mct.style.top='0px';
    G.mct.style.left='65px';
    G.mct.style.width='485px';
    G.mct.style.height=(oRec.nStartY);
   
	var mclWidth = oRec.nStartX-65 < 0 ? 0 :  oRec.nStartX-65;
   
	G.mcl.style.left  ='65px';
	G.mcl.style.top   =oRec.nStartY + 'px';
	G.mcl.style.height=oRec.nHeight + 'px';
	G.mcl.style.width =mclWidth + 'px';
    
    G.mcr.style.left=(oRec.nEndX)+'px';
	G.mcr.style.top=(oRec.nStartY)+'px';
	

	G.mcb.style.left ='65px';
	G.mcb.style.top  =oRec.nEndY + 'px';    
    G.mcb.style.width=oRec.nEndX + 'px';
    
    var mciHeight = oRec.nHeight-4 < 0 ? 0 :  oRec.nHeight-4;
    var mciWidth = oRec.nWidth-4 < 0 ? 0 :  oRec.nWidth-4;
   
    G.mci.style.left = oRec.nStartX+2 + 'px';
    G.mci.style.top = oRec.nStartY+2 + 'px';
    G.mci.style.height = mciHeight + 'px';
    G.mci.style.width = mciWidth + 'px';
    
    
    
    var mcuWidth = oRec.nStartX < 65 ? oRec.nStartX :  65;
    
    G.mcu.style.left='0px';
    G.mcu.style.top='265px';
    G.mcu.style.width=mcuWidth + 'px';
    
    
		
		// invoke callback if provided
		if (G.callbacks.dragging !=null){G.callbacks.dragging(G.nStartX,G.nStartY,oRec.nEndX,oRec.nEndY)};
		
    return false;
  }  
};



GZoomControl.prototype.mouseup_=function(e){
  var G=GZoomControl.G;
  if (G.bDragging) {
    var oPos = GZoomControl.prototype.getRelPos_(e);
    G.bDragging=false;
    
    var oRec = GZoomControl.prototype.getRectangle_(G.nStartX,G.nStartY,oPos,G.nMapRatio);
    debug("mouse up at "+oRec.nEndX+", "+oRec.nEndY+". Height/width="+oRec.nWidth+","+oRec.nHeight); 

 //   GZoomControl.prototype.resetDragZoom_();
 
 
		var nwpx=new GPoint(oRec.nStartX,oRec.nStartY);
		var nepx=new GPoint(oRec.nEndX,oRec.nStartY);
		var sepx=new GPoint(oRec.nEndX,oRec.nEndY);
		var swpx=new GPoint(oRec.nStartX,oRec.nEndY);
		
	var nw = G.oMap.fromContainerPixelToLatLng(nwpx); 
    var ne = G.oMap.fromContainerPixelToLatLng(nepx); 
    var se = G.oMap.fromContainerPixelToLatLng(sepx); 
    var sw = G.oMap.fromContainerPixelToLatLng(swpx); 
    
    $id('latStart').value = se.y;
    $id('latEnd').value = nw.y;
    $id('lngStart').value = nw.x;    
    $id('lngEnd').value = se.x;
    

		// invoke callback if provided
		if (G.callbacks.dragEnd !=null){G.callbacks.dragEnd(nw,ne,se,sw,nwpx,nepx,sepx,swpx)};
		
		//re-init if sticky
		if (G.options.bStickyZoom) {GZoomControl.prototype.initCover_()};		
  }
};

// set the cover sizes according to the size of the map
GZoomControl.prototype.setDimensions_=function() {
  var G=GZoomControl.G;
	if (G.options.bForceCheckResize){G.oMap.checkResize()};
  var oSize = G.oMap.getSize();
  G.nMapWidth  = oSize.width;
  G.nMapHeight = oSize.height;
  G.nMapRatio  = G.nMapHeight/G.nMapWidth;
	acl.style([G.mc,G.mct,G.mcr,G.mcb,G.mcl,G.mci,G.mcu],{width:G.nMapWidth+'px', height:G.nMapHeight+'px'});
};

GZoomControl.prototype.initStyles_=function(){
  var G=GZoomControl.G;
	acl.style([G.mc,G.mct,G.mcr,G.mcb,G.mcl,G.mci,G.mcu],{filter:G.style.sIEAlpha,opacity:G.style.nOpacity,background:G.style.sColor});
  G.oOutline.style.border=G.style.sBorder;  
  debug("done initStyles_");	
};

// The zoom button's click handler.
GZoomControl.prototype.buttonClick_=function(){
  if (GZoomControl.G.mc.style.display=='block'){ // reset if clicked before dragging
    GZoomControl.prototype.resetDragZoom_();
  } else {
		GZoomControl.prototype.initCover_();
	}
};

// Shows the cover over the map
GZoomControl.prototype.initCover_=function(){
  var G=GZoomControl.G;
	G.oMapPos=acl.getElementPosition(G.oMap.getContainer());
	GZoomControl.prototype.setDimensions_();
	GZoomControl.prototype.setButtonMode_('zooming');
	acl.style([G.mc],{display:'block',background:G.style.sColor});
	acl.style([G.oOutline],{width:'0px',height:'0px'});
	//invoke callback if provided
	if(GZoomControl.G.callbacks['buttonClick'] !=null){GZoomControl.G.callbacks.buttonClick()};
	debug("done initCover_");
};

GZoomControl.prototype.getRelPos_=function(e) {
  var oPos=acl.getMousePosition (e);
  var G=GZoomControl.G;
  return {top:(oPos.top-G.oMapPos.top),left:(oPos.left-G.oMapPos.left)};
};

GZoomControl.prototype.getRectangle_=function(nStartX,nStartY,oPos,nRatio){
	
	var top = oPos.top < 0 ? 0 : oPos.top;
	var left = oPos.left < 0 ? 0 : oPos.left;
	var dX=left-nStartX;
	var dY=top-nStartY;
	
	if (dX <0) dX =dX*-1;
	if (dY <0) dY =dY*-1;
	
	nStartXOut = (nStartX > left) ? left : nStartX;
	nStartYOut = (nStartY > top)  ? top  : nStartY;
	
	nEndXOut = (nStartX > left) ? nStartX : left;
	nEndYOut = (nStartY > top)  ? nStartY : top;
	
  return {
    nStartX:nStartXOut,
    nStartY:nStartYOut,
    nEndX:nEndXOut,
    nEndY:nEndYOut,
    nWidth:dX,
    nHeight:dY
  }
};

GZoomControl.prototype.resetDragZoom_=function() {
	var G=GZoomControl.G;
	acl.style([G.mc,G.mct,G.mcr,G.mcb,G.mcl,G.mci,G.mcu],{display:'none',opacity:G.style.nOpacity,filter:G.style.sIEAlpha});
	G.oOutline.style.display='none';	
	GZoomControl.prototype.setButtonMode_('normal');
  debug("done with reset drag zoom");
};

/* alias get element by id */
function $id(sId) { return document.getElementById(sId); }
/* utility functions in acl namespace */
if (!window['acldefined']) {var acl={};window['acldefined']=true;}//only set the acl namespace once, then set a flag

/* A general-purpose function to get the absolute position of
the mouse */
acl.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};  
};

/*
To Use: 
	var pos = acl.getElementPosition(element);
	var left = pos.left;
	var top = pos.top;
*/
acl.getElementPosition=function(eElement) {
  var nLeftPos = eElement.offsetLeft;          // initialize var to store calculations
	var nTopPos = eElement.offsetTop;            // initialize var to store calculations
	var eParElement = eElement.offsetParent;     // identify first offset parent element  
	while (eParElement != null ) {                // move up through element hierarchy
		nLeftPos += eParElement.offsetLeft;      // appending left offset of each parent
		nTopPos += eParElement.offsetTop;  
		eParElement = eParElement.offsetParent;  // until no more offset parents exist
	}
	return {left:nLeftPos, top:nTopPos};
};
//elements is either a coma-delimited list of ids or an array of DOM objects. o is a hash of styles to be applied
//example: style('d1,d2',{color:'yellow'});  
acl.style=function(a,o){
	if (typeof(a)=='string') {a=acl.getManyElements(a);}
	for (var i=0;i<a.length;i++){
		for (var s in o) { a[i].style[s]=o[s];}
	}
};
acl.getManyElements=function(s){		
	t=s.split(',');
	a=[];
	for (var i=0;i<t.length;i++){a[a.length]=$id(t[i])};
	return a;
};
	
var jslog = {debug:function(){},info:function(){}, 
	warning:function(){}, error:function(){},
	text:function(){}}; var debug=function(){};
if (location.href.match(/enablejslog/)){
		document.write('<script type="text/javascript" src="http://earthcode.com/includes/scripts/jslog.js"></script>');};	
