/* 
---------------------------------------------------------

qlblog.js: QiblaLocator.com direction algorithm.
Copyright (C) 2005-2010 QiblaLocator.com


Copyright 2005-2010, QiblaLocator.com 
All rights reserved. 

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions 
are met: 

1. Redistributions of source code must retain the above copyright 
notice, this list of conditions, and the following disclaimer. 

2. A link to qiblalocator.com must be clearly visible on the website 
and/or application that this code is used on. 

3. Redistributions in binary form must reproduce the above copyright 
notice, this list of conditions, and the following disclaimer in the 
documentation and/or other materials provided with the distribution. 

4. The name of the author may not be used to endorse or promote products 
DERIVED from this software without specific prior written permission. 

5. You may not use this code in any manner that is primarily intended for 
or directed toward commercial advantage or private monetary compensation. 


THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 


--------------------------- Globals -----------------------------
*/

var qiblaLat = 21.42252;
var qiblaLng = 39.82621; 

//Const normal = G_NORMAL_MAP;
//Const hybrid = G_HYBRID_MAP;
//Const satellite = G_SATELLITE_MAP;
//Const physical = G_PHYSICAL_MAP;

var addrEmptyMsg = 'Enter address, zipcode, country or lat,lon';
var map, geocoder, centerMarker;


//--------------------------- Initialize -----------------------------


// initialization function
function init(startAddr, startLat, startLng, startZoom, startMapType)
{
	if (!GBrowserIsCompatible())
		return;

	
       startLng = parseFloat(geoip_longitude());
       startLat = parseFloat(geoip_latitude());

	if (!startAddr) startAddr = '';
	if (!startLat) startLat = 30.6186;
	if (!startLng) startLng = -96.3361;
	if (!startZoom) startZoom = 12;
	
	var params = {};
	try 
	{
		var paramsArr = String(document.location).split('?')[1].split('&');
		for (var i = 0; i < paramsArr.length; ++i) {
			var p = paramsArr[i].split('=');
			params[p[0]] = p[1];
		}
	}
	catch (e) {}	
	
					
	startLat = (params['latitude'] ? parseFloat(params['latitude']) : startLat);
	startLng = (params['longitude'] ? parseFloat(params['longitude']) : startLng);
	startZoom = (params['zoom'] ? parseInt(params['zoom']) : startZoom);
	startAddr = (params['address'] ? params['address'] : startAddr);
	startMapType = (params['type'] ? params['type'] : startMapType);

	map = new GMap2(document.getElementById('map'));
	switch(startMapType) {
	case 'n': map.setMapType(G_NORMAL_MAP); break;
	case 's': map.setMapType(G_SATELLITE_MAP); break; 
	case 'h': map.setMapType(G_HYBRID_MAP); break; 
	case 'p': map.setMapType(G_PHYSICAL_MAP); break;
	case '3': map.setMapType(G_SATELLITE_3D_MAP); break; 
	default: map.setMapType(G_PHYSICAL_MAP);
	}
	geocoder = new GClientGeocoder();
	var home = new GLatLng(startLat, startLng);

	map.addControl(new GLargeMapControl());
	map.addControl(new GMenuMapTypeControl());
       map.addMapType(G_PHYSICAL_MAP); 
       map.addMapType(G_SATELLITE_3D_MAP);
	map.addControl(new GScaleControl());
	map.setCenter(home, startZoom);

	var icon = new GIcon(null, 'http://www.qiblalocator.com/qibla/images/crosshair.gif');
	icon.iconSize = new GSize(17, 17);
	icon.iconAnchor = new GPoint(8, 8);
	centerMarker = new GMarker(home, {icon: icon, clickable: false});

	GEvent.addListener(map, 'move', mapDraw);
	document.getElementById('roundRect').value = startAddr;
	leaveAddressBar();
	mapDraw();
	
}


//------------------------- Map Functions -----------------------------


// update map 
function mapDraw()
{
	var center = map.getCenter();
	var lng = center.lng();
	var lat = center.lat();
	
	var qiblaDir = -getDirection(lat, lng, qiblaLat, qiblaLng);

	map.clearOverlays();
	centerMarker.setPoint(center);
	map.addOverlay(centerMarker);

	var line = getLine(lat, lng, qiblaDir);
	map.addOverlay(line);	
	writeData(center, qiblaDir);
}

// generate share-able link
function shareLink()
{
	var center = map.getCenter();
	var lng = center.lng().toFixed(4);
	var lat = center.lat().toFixed(4);
	var zoom = map.getZoom();

	var link = document.getElementById('sharelink');
	link.value = 'http://www.qiblalocator.com/?latitude=' + lat + '&longitude=' + lng + '&zoom=' + zoom;
}


//write information
function writeData(center, qiblaDir)
{
	var kaba = new GLatLng(qiblaLat, qiblaLng);
	//checkunit();
	//var distance = center.distanceFrom(kaba)/ 1000; 
	if (qiblaDir < 0) qiblaDir += 360;
	writeItem('curLng', center.lng().toFixed(4));
	writeItem('curLat', center.lat().toFixed(4));				
	writeItem('direction', qiblaDir.toFixed(2)+ '&deg;&nbsp;N');	
	if (document.getElementById('units').checked)
	{
		var converter = 1609.344;   //miles
		var distance = center.distanceFrom(kaba)/ converter; 
		writeItem('distance', distance.toFixed(0)+ '&nbsp;mi');	
	}
	else {
		var converter = 1000;     //kilometers
		var distance = center.distanceFrom(kaba)/ converter; 
		writeItem('distance', distance.toFixed(0)+ '&nbsp;km');	
	}
}


//update a data item
function writeItem(itemID, value)
{
	document.getElementById(itemID).innerHTML = value;
}


// create a direction line
function getLine(lat, lng, angle)
{
	var factor = 8;
	var zoom = map.getZoom();
	var dLng = factor/ Math.pow(2, zoom- 7);
	if (zoom < 7) dLng = factor;

	dLng = dLng* Math.sin(dtr(angle));

	var from = new GPoint(lng, lat);
	var lat2 = getLat(lat, angle, dLng);
	var to = new GPoint(lng+ dLng, lat2);
	if (Math.abs(dLng) > Math.abs(lng- qiblaLng))
		to = new GPoint(qiblaLng, qiblaLat);

    var line = new GPolyline([ from, to ], '#00ccff', 5, .70);
	return line;
}



//-------------------------- Calculating Functions -----------------------

// definitions:
// point1 = (lat1, lng1), point2 = (lat2, lng2)
// dLng = lng1- lng2
// direction = angle of the line connecting point1 to point2 (CW from North)


// find the direction
function getDirection(lat1, lng1, lat2, lng2) 
{
	var dLng = lng1- lng2;
	return rtd(getDirectionRad(dtr(lat1), dtr(lat2), dtr(dLng)));
}

function getDirectionRad(lat1, lat2, dLng) 
{
	return Math.atan2(Math.sin(dLng), Math.cos(lat1)* Math.tan(lat2)- Math.sin(lat1)* Math.cos(dLng));
}


// find lat2 for a given direction
function getLat(lat1, angle, dLng) 
{
	return rtd(getLatRad(dtr(lat1), dtr(angle), dtr(dLng)));
}

function getLatRad(lat1, angle, dLng) 
{
	return Math.atan((Math.sin(dLng)+ Math.tan(angle)* Math.sin(lat1)* Math.cos(dLng))/ (Math.tan(angle)* Math.cos(lat1)));
}


//-------------------------- Angle Unit Conversion -----------------------


// degree to radian
function dtr(d)
{
    return (d* Math.PI)/ 180.0;
}

// radian to degree
function rtd(r)
{
    return (r* 180.0)/ Math.PI;
}


//-------------------------- Geocoder Functions -----------------------


// locate address
function locateAddress() 
{
	var address = document.getElementById('roundRect').value;
	if (address == '' || address == addrEmptyMsg)
	{
		alert(addrEmptyMsg);
		return;
	}
	geocoder.getLocations(address, showAddressOnMap);
}


// show address on map
function showAddressOnMap(response) 
{
	if (!response || response.Status.code != 200) 
		alert('Address not found');
	else 
	{
		place = response.Placemark[0];
		point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);
		map.setCenter(point, 8+ place.AddressDetails.Accuracy);
		marker = new GMarker(point);
		map.addOverlay(marker);
		marker.openInfoWindowHtml(place.address);
	}
}


//-------------------------- Misc Functions  -----------------------



// called when address bar is focused
function focusAddressBar()
{
	var address = document.getElementById('roundRect');

	address.style.color = '#000000';
	if (address.value == addrEmptyMsg)
		address.value = '';
}


// called when address bar lose focus
function leaveAddressBar()
{
	var address = document.getElementById('roundRect');

	if (address.value == '' || address.value == addrEmptyMsg)
	{
		address.style.color = '#999999';
		address.value = addrEmptyMsg;
	}
}

//distance mile/km selector

function  checkunit() {
   if (document.dUnit.unit[0].checked==true) converter = 1609.344;   //miles
   if (document.dUnit.unit[1].checked==true) converter = 1000;     //kilometers
}

// toggle hidden element
function toggle( targetId ) {
   if ( document.getElementById ) {
    target = document.getElementById( targetId );
    if ( target.style.display == "none" ) {
     target.style.display = "";
    } else {
     target.style.display = "none";
    }
   }
}

