/******************************************************************
 * Store-locator. Helper functions.
 * Oct 30 2007
 ******************************************************************/
var control;
var control2;
var introControl;
var shapeControl; 

/**
 * Various global constants.
 * =========================
 */
var SLConst = new _SLConst();
function _SLConst() {

    /**
     * Tab names.
     */
    this.DirectionsTabName = "directions";
    this.ResultsTabName = "results";
    this.HowToTabName = "howto";

    /**
     * VE map size.
     */
	this.MapX = 473;
	this.MapY = 390;
	
	/**
	 * Size of the store bubble.
	 */
	this.StoreBubbleX = 221;
	this.StoreBubbleY = 125;
	
	/**
	 * These types are from the database.
	 * (except for the pin type)
	 */
	this.BellType = 30;
    this.OtherType = 20;
    this.PinType = 999; // define a type for the pin (is not is db)
	
	this.BellLayerZIndex = 1000;
	this.OtherLayerZIndex = 900;
}
//remove minimap
//var _minimapShown = true;
var _minimapShown = false;

/**
 * @return state of minimap
 */
function IsMiniMapShown() {
   return _minimapShown;
}

function ShowMiniMap()
 {
    if (SLMap.GetMap().GetMapMode() == VEMapMode.Mode3D)
    {
       SLMap.GetMap().SetMapMode(VEMapMode.Mode2D);
    }

	//document.getElementById("myMiniMapControl").style.top="330px";
	//document.getElementById("myMiniMapControl").style.left="630px";
	
    SLMap.GetMap().ShowMiniMap(354, 0);  
    SLMap.GetMap().HideControl(control2);
	SLMap.GetMap().ShowControl(control);
	
	_minimapShown = true;
 }

 function HideMiniMap()
 {		

    SLMap.GetMap().HideMiniMap(control);
    SLMap.GetMap().HideControl(control);
	SLMap.GetMap().ShowControl(control2);
    _minimapShown = false;

 }
 
 /**
  * Call this function when opening the "Plus d'info" screen.
  */
 function HideMiniArrows()
 {		
    SLMap.GetMap().HideControl(control);
	SLMap.GetMap().HideControl(control2);

 }
 
/**
 * Call this function during these times:
 *  1. When closing the "Plus d'info" page.
 *  2. Showing the route.
 */
function RestoreMiniMap() {
	HideMiniArrows();
	AddMyControl(); // add minimap
	if (IsMiniMapShown()) {
		ShowMiniMap();
	} else {
		HideMiniMap();
	}
}

 
// Function to hide the instruction message in middle of map after a person starts a search
 function HideIntroControl()
 {
   	SLMap.GetMap().HideControl(introControl);
 }


 /**
  * Object to display & hide the store bubble.
  */
 var SLBub = new _SLBub();
 
 function _SLBub() {
	  /**
	   * Add the shape bubble.
	   * Done on mouseover of a shape.
	   */
	  this.AddBub = function(shape) {
		   if(myControl=document.getElementById("StoreShapeControl"))
		  {
			 SLMap.GetMap().DeleteControl(myControl);
		  }
			
	
		   shapeControl = document.createElement("div"); 
	       shapeControl.id = "StoreShapeControl";
	
	       var xy = SLMap.GetMap().LatLongToPixel(shape.GetIconAnchor());
	       
	       _FixShapeControlPosition(shapeControl, xy.x, xy.y);
	       
	       //SLUtil.debug("AddShape at " + xy.x + "@" + xy.y);

	       var contentstr = null;
	       // depending on type of shape
	       if (shape.IsCenterPin) {
	    	   contentstr = SLShape.ComposeSearchPinText();
	       } else if (shape.IsRoutePin) {
	    	   contentstr = SLShape.ComposeRoutePinText();
	       } else {
	    	   contentstr = SLShape.ComposeStoreShapeText(shape.Store, shape.StoreId);
	       }
		   shapeControl.innerHTML = contentstr;
		   
		   SLMap.GetMap().AddControl(shapeControl, SLConst.BellLayerZIndex + 100); // make it top layer
	  }
	  
	  
	  /**
	   * @param pX Store bubble anchor point x
	   * @param Py Store bubble anchor point y
	   * @return position for the bubble. We position the bubble so that it will not display outside the map.
	   *         We avoid X 
	   *         Note: The new position is set in the ctl.style.top & left. 
 	   */
	  function _FixShapeControlPosition(ctl, pX, pY) {
		  
		  // offset of bubble top-left w/r to the icon anchor
		  var delX = 20;
		  var delY = 22;
		  
		  var max
		  
		  pX += delX;
		  pY += delY;

		  /**
		   * Compute position 
		   * [NOTE: (0,0) is top left on the map]
		   */
		  // Fix offset X 
		  var rightMost = pX + SLConst.StoreBubbleX;
		  var tooAtRight = (rightMost > SLConst.MapX);
		  var x = (tooAtRight ? SLConst.MapX - SLConst.StoreBubbleX : pX);		  
		  if (x < 0) x = 0;
		  
		  var offY = 14;
		  
		  // offset Y: either put it under shape (normal case), 
		  //           or on top of shape (if shape is too low)
		  var lowestY = pY + SLConst.StoreBubbleY; 
		  var isLow = (lowestY > SLConst.MapY);
		  var delY = (isLow ? (SLConst.StoreBubbleY + offY) : 0);
		  var y = pY - delY; // 20 = height of store pushpin		  
          y = Math.max(0, y);// limit to 0
          y = Math.min(y, SLConst.MapY - SLConst.StoreBubbleY - offY);// limit to going too low
		  
		  //SLUtil.debug("[delX=" + delX + "] [isLow ? " + isLow + " - lowestY=" + lowestY + "]");
		  		  
		  ctl.style.left = x;
		  ctl.style.top = y;
	  }
	
	  // Function to add the 2 arrows for minimap
	  // (Not used anymore)
	  this.storeBubbleMouseOut = function(ev) {
	 	 
	 	  // TN: ev != null: is never true!!
	 	  if (ev == null || (ev.relatedTarget && ev.relatedTarget.tagName && ev.relatedTarget.tagName != "svg")) {
	 		  // ev.relatedTarget is element
	 		  //SLUtil.debug(ev.relatedTarget.tagName);
	 		  return;
	 	  }
	 	  //SLUtil.debug("storeBubbleMouseOut: deleting bubble" + ev);
	 	  
	 	  if (true) {
	 		  return;
	 	  }
	 	  	 	
	 	  SLBub.DeleteBub(ev);	  
	  }
	  
	  /**
	   * @return true if the store bubble is shown.
	   */
	  this.IsBubShown = function() {
		  return document.getElementById("StoreShapeControl");
	  }

	  /**
	   * Fct to delete a shape bubble.
	   * Invoked from 2 places:
	   *   1. from mouseout of a shape (ev == null)
	   *   2. from mouseout of bubble div itself.
	   * @param ev This is the mouseout event that triggered this fct.
	   */
	  this.DeleteBub = function(ev) {
		  var myControl=document.getElementById("StoreShapeControl");
	
		  if (myControl) {
			  SLMap.GetMap().DeleteControl(myControl);
		  }
	  }
 }
  
  
  function AddMyControl()
 { 
   // if (control == null)
   // {
        
       control = document.createElement("div"); 
       control.id = "myMiniMapControl";
       control.style.top ="102px"; 
       control.style.left = "362px"; 
	  

	   if (BrowserDetect.browser == "Safari" && BrowserDetect.version < 3)
		{
			 control.style.top ="-224px"; 
			control.style.left = "609px"; 
		}
       //remove minimap    
       //control.innerHTML = '<div  onclick=HideMiniMap();><input style="margin-bottom:0px;" name="imageField" onclick="HideMiniMap();" src="/web/common/all_languages/all_regions/images/buttons/minimapHide.PNG" width="14" height="14"  type="image" title="'+ SLMesg.MSVE_minimap_HideTitle  +  '"></div>';  


	   control2 = document.createElement("div"); 
       control2.id = "myMiniMapControl2";
       control2.style.top ="8px"; 
       control2.style.left = "454px"; 
	   

	    if (BrowserDetect.browser == "Safari" && BrowserDetect.version < 3)
		{
			 control2.style.top ="-322px"; 
			control2.style.left = "710px"; 
		}
       //remove minimap    
       //control2.innerHTML = '<div  onclick=ShowMiniMap();><input style="margin-bottom:0px;" name="imageField" onclick="ShowMiniMap();" src="/web/common/all_languages/all_regions/images/buttons/minimapShow.PNG" width="14" height="14"  type="image"  title="'+ SLMesg.MSVE_minimap_ShowTitle  +  '"></div>';  



       SLMap.GetMap().AddControl(control);
	   SLMap.GetMap().AddControl(control2);
	   SLMap.GetMap().HideControl(control2);

		

  //  }
 }

/**
*	This function adds the introductory bubble control on the map when the user first connects to storelocator
*
 */

function AddIntroBubbleControl() 
{
	  var controlText;
	   introControl = document.createElement("div"); 
       introControl.id = "IntroControl";
       introControl.style.top ="200px"; 
	  
       introControl.style.left = "150px"; 
        

		if (BrowserDetect.browser == "Safari" && BrowserDetect.version < 3)
		{
			 introControl.style.top ="-160px"; 
			introControl.style.left = "370px"; 
		}
		  
		controlText='<div id="bubble_on_map" class="little">';
		controlText +='<div class="message">';
		controlText +='<div class="top">&nbsp;</div>';
		controlText +='<div class="details">';
		controlText +=SLMesg.InitialBubbleInMiddleMap;
		controlText +='</div>';
		controlText +='<div class="bottom">&nbsp;</div>';
		controlText +='</div>';
		controlText +='</div>';

        introControl.innerHTML = controlText;  

        SLMap.GetMap().AddControl(introControl);


}


/**
 * @return zoom level given the distance in km.
 * When needed ? We zoom to a 'confortable' level depending
 * on distance from search center to farthest match. 
 * @param {Object} dist
 */
function getZoomLevel(dist) {		
	
    if (dist < 1.5) return 14; 
    else if (dist < 3.0) return 13; 
    else if (dist < 6.0) return 12; 
    else if (dist < 12.0) return 11; 
    else if (dist < 24.0) return 10; // from now on down, double distance
    else if (dist < 50.0) return 9; 
    else if (dist < 100.0) return 8; 
    else if (dist < 200.0) return 7; 
    else if (dist < 400.0) return 4; 
    else if (dist < 800.0) return 3; 
    else if (dist < 1600.0) return 2; 
    else if (dist < 3000.0) return 1;
    else return 1; 
}

/**
 * Distance from 2 points using Law of cosines formula.
 * http://www.movable-type.co.uk/scripts/latlong.html
 */
function kmByLawOfCosines(lat1, lon1, lat2, lon2) {
	var R = 6371; // km
	var d = Math.acos(Math.sin(lat1)*Math.sin(lat2) + 
	                  Math.cos(lat1)*Math.cos(lat2) *
	                  Math.cos(lon2-lon1)) * R;
	return d;
}

/**
 * Distance from 2 points using Haversine formula. More accurate than law of cosines.
 * http://www.movable-type.co.uk/scripts/latlong.html
 */
function kmByHaversine(lat1, lon1, lat2, lon2) {
	var R = 6371; // km
	var dLat = (lat2-lat1).toRad();
	var dLon = (lon2-lon1).toRad(); 
	var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
	        Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * 
	        Math.sin(dLon/2) * Math.sin(dLon/2); 
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
	var d = R * c;
	return d;
}

//extend Number object with methods for converting degrees/radians

Number.prototype.toRad = function() {  // convert degrees to radians
  return this * Math.PI / 180;
}

Number.prototype.toDeg = function() {  // convert radians to degrees (signed)
  return this * 180 / Math.PI;
}

Number.prototype.toBrng = function() {  // convert radians to degrees (as bearing: 0...360)
  return (this.toDeg()+360) % 360;
}



// Check for alphanumeric in string client side script
function alphanumeric(alphane)
{
	var numaric = alphane;
	for(var j=0; j<numaric.length; j++)
		{
		  var alphaa = numaric.charAt(j);
		  var hh = alphaa.charCodeAt(0);
		  if((hh > 47 && hh<59) || (hh > 64 && hh<91) || (hh > 96 && hh<123))
		  {
		  }
		else	{
			 return false;
		  }
		}
 return true;
}

// browser detection script

var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)|| this.searchVersion(navigator.appVersion)|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "An unknown OS";	
	},
	
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
	  		{
	  			string: navigator.platform,
	  			subString: "Win",
	  			identity: "Windows"
	  		},
	  		{
	  			string: navigator.platform,
	  			subString: "Mac",
	  			identity: "Mac"
	  		},
	  		{
	  			string: navigator.platform,
	  			subString: "Linux",
	  			identity: "Linux"
	  		}
	  	]


};
BrowserDetect.init();

