if ("https:" == document.location.protocol) {
 var WR = 'https://wizi.com/wr/02';
 var HOST = 'https://wizi.com';
} else {
 var WR = 'http://wizi.com/wr/02';
 var HOST = 'http://wizi.com';
}

var timerid = 0;		// global timer
var eventids = [];		// ids of async WR operations
var eventargs = [];
var token;

var map;			// google map
var panorama;		// google street view
var streetview = new google.maps.StreetViewService();
var pin;			// pin marker
var infowindow;		// pin info window
var initialcenter = new google.maps.LatLng(38.725, -9.152);

//
// Initialize
//

function initialize()
{
	// check geolocation support
	if(navigator.geolocation)
	{
		debug('We have geolocation support!');
		$('#tokenpanel .find-me').css('display', 'inline-block');
		$('#footer .find-route').css('display', 'inline-block');
		$('#footer .google').css('display', 'none');
	}
	else
	{
		debug('No geolocation support...');
	}

	// process token
	debug('Token: ' + gettokeninurl());
	processtokeninurl(gettokeninurl());
}

function processtokeninurl(tok)
{
	if(tok != null)
	{
		loadlocation({ token: tok, action: 'load', show: true });
	}
}

function loadlocation(args)
{
	$.getJSON(WR + '/' + args.token + '?id=' + getid('load', { action: args.action, show: args.show }) + '&jscb=?', function(data) {
		processwrevents(data);
	});	
}

function attachevents()
{
	$('#map-alert a').click(function() {
		$(this).parent().fadeOut(500, function() {
			$(this).css('top', '-500px');
		});

		return false;
	});
	
	// find pin
	$('#tokenpanel a.find-pin').click(function() {
		return findpin();
	});

	// find me
	$('#tokenpanel a.find-me').click(function() {
		return findme();
	});

	// view street
	$('#tokenpanel a.view-street').click(function() {
		return viewstreet();
	});

	// find route
	$('#footer a.find-route').click(function() {
		return findroute();
	});

}

//
// WR ping
//

function startping()
{
	timerid = window.setInterval('ping()', 5000);
}

function stopping()
{
	window.clearInterval(timerid);
}

function ping()
{
	debug("ping...");
	
	// TODO: if we have a live or a me token request update from WR else just ping:
	if(token)
	{
		if(token['t'] == 'me' || token['t'] == 'fr' || token['t'] == 'lpl')
		{
			debug('going to track pin location');
			loadlocation({ token: token['url'], action: 'refresh', show: true });
		}
	}
	else
	{
		$.getJSON(WR + '/_?op=ping&id=0&jscb=?', function(data) {
			processwrevents(data);
		});
	}
}

//
// WR events
//

function processwrevents(data)
{
	for(i = 0; i < data.length; i ++)
	{
		if(data[i]['ev'] == 'setopt')
		{
			handlesetopt(data[i]);
		}
		else if(data[i]['ev'] == 'upd')
		{
			handleupdate(data[i]);
		}
		
		// responses to async requests
		if(data[i]['ref'])
		{
			var id = parseInt(data[i]['ref']);

			if(id == 0)
			{
				continue;
			}

			switch(eventids[id])
			{
				case 'load':
					handleloadlocation(data[i], eventargs[id]);
					break;

				default:
					debug('API error!');
					break;
			}
		}
	}
}

function handlesetopt(data)
{
	debug('WR setopt');

	if(data['wrurl'])
	{
		debug('New WR url: ' + data['wrurl']);
		// WR = data['wrurl'];
	}
}

function handleloadlocation(data, args)
{
	switch(data['err'])
	{
		case 'NA':
			openmapalert('The requested location was not found.');
			return;
					
		case 'NP':
			openmapalert('The requested location has expired.');
			return;

		default:
			if(args.action == 'load')
			{
				token = data;
				setpin();
			}
			else if(args.action == 'refresh')
			{
				refreshpin(data['lat'], data['lon'], data['locupdts']);
				token = data;
			}
			return;
	}
}

function handleupdate(data)
{
	debug('WR upd');
	// TODO: handle live location...
}

//
// Map
//

function loadmap()
{
	// build map
	var options = {
			zoom: 9,
			center: initialcenter,
			mapTypeId: google.maps.MapTypeId.ROADMAP
	};
	map = new google.maps.Map(document.getElementById("mapcanvas"), options);
	
	// zooming
	/*
	GEvent.addListener(window.gmap, "zoomend", function(ol, nl) {
		handlezoomchange(nl);
	});
	
	GEvent.addListener(window.gmap, "maptypechanged", function() {
		handlemaptypechange(window.gmap.getCurrentMapType().getUrlArg());
	});
	*/

	// add live panel
	map.controls[google.maps.ControlPosition.RIGHT].push(document.getElementById("tokenpanel"));
}

function setpin()
{
	// lat/lon
	var latlng = map.getCenter();
	if(token['lat'] && token['lon'])
		latlng = new google.maps.LatLng(token['lat'], token['lon']);

	// icon
	var avatar = HOST + '/map/imgs/pin_red_32x32.png';
	if(token['avatar'])
	{
		if(token['avatar'].indexOf('http') == 0)
		{
			avatar = token['avatar'];
		}
		else
		{
			debug('Avatar: ' + token['avatar'] + ' [' + token['url'] + ']');
			avatar = HOST + '/map/avatars/' + token['avatar'].replace('#', '') + '.png';
		}
	}
	var icon = new google.maps.MarkerImage(avatar);
	debug(avatar);
	
	// set pin
	if(! pin)
	{
		// build new pin
		debug('building new pin');
		pin = new google.maps.Marker({
			position: latlng,
			map: map,
			icon: icon
		});
	}
	else
	{
		// update existing pin
		pin.setPosition(latlng);
		pin.setIcon(icon);
	}

	// photo
	var photo = null;
	var tokenlink = tokengetlink(token, 'photo');
	if(tokenlink)
		photo = tokenlink['url'];
	debug(photo);
	if(photo)
		setinfowindow(photo);

	// GEvent.clearListeners(window.gmap, "zoomend");

	// add street view option if available at this location
	setstreetview();
	
	// refresh map
	map.panTo(latlng);
	refreshmap();
	
	// panel and footer
	refreshpanel();
	refreshfooter();

	/*
	GEvent.addListener(window.gmap, "zoomend", function(ol, nl) {
		handlezoomchange(nl);
	});
	*/
}

function refreshpin(lat, lon, locupdts)
{
	if(token['lat'] != lat || token['lon'] != lon)
	{
		token['lat'] = lat;
		token['lon'] = lon;
		token['locupdts'] = locupdts;
		
		// lat/lon
		latlng = new google.maps.LatLng(lat, lon);
		
		// pan map
		map.panTo(latlng);

		// update existing pin
		pin.setPosition(latlng);
		
		// show/hide street view option
		setstreetview();
		
		// panel and footer
		refreshpanel();
		refreshfooter();
	}
}

function setinfowindow(photo)
{
	var content = '';
	content = content + '<div><a id="thumb1" href="javascript:" class="highslide" onclick="return hs.expand(this)">';
	content = content + '<img src="' + HOST + '/map/getphoto.php?url=' + photo + '&w=100" alt="Photo" title="Click to enlarge" height="120" width="107" />';
	content = content + '</a></div>';
	
	// build info window if it does not exist
	if(! infowindow)
	{
		infowindow = new google.maps.InfoWindow({ maxWidth: 100});
		google.maps.event.addListener(pin, 'click', function() {
			infowindow.open(map, pin);
		});	
	}

    hs.src = PHOTOSVPATH + '/' + photo;

	infowindow.setContent(content);
	infowindow.open(map, pin);
}

function refreshmap()
{
	// maptype
	var maptype = map.getMapTypeId();
	if(token['maptype'])
		if(token['maptype'] == 'h' || token['maptype'] == 's')
			maptype = google.maps.MapTypeId.HYBRID;
	
	// zoom
	var zoom = map.getZoom();
	if(token['zoom'])
	{
		var spans = [ 172983, 135783, 79962, 41444, 20872, 10454, 5228, 2615, 1307, 653, 326, 163, 81, 40, 20, 10, 5, 2, 1, 0, 0 ];
		var zoom = 0;

		$.each(spans, function(index, value) {
			if(token['zoom'] >= value) {
				zoom = index;
				return false;
			}
		});

		debug('WR zoom: ' + token['zoom']);
		debug('GMap zoom: ' + --zoom);
	}

	map.setZoom(zoom);
	map.setMapTypeId(maptype);
}

function refreshpanel()
{
	// avatar
	var avatar = HOST + '/map/imgs/pin_red_24x24.png';
	if(token['avatar'])
		avatar = HOST + '/map/avatars/' + token['avatar'].replace('#', '') + '_24x24.png';
	$('#tokenpanel .panel-avatar').attr('src', avatar);
	
	// live
	if(token['t'] == 'me' || token['t'] == 'fr' || token['t'] == 'lpl')
		$('#tokenpanel .live').html('LIVE');
	else
		$('#tokenpanel .live').html('');

	// updated
	$('#tokenpanel .updated').html(formatupdatetime(token['locupdts'], false));
}

function refreshfooter()
{
	var url = encodeURIComponent('http://wizi.com/' + token['url']);
	
	// SMS
	$('#footer #share .sms').attr('href', 'http://wizi.com/' + token['url'] + "?sendsms=1");

	// Facebook
	$('#footer #share .facebook').attr('href', 'http://facebook.com/sharer.php?u=' + url + '&t=' + encodeURIComponent('Location Map'));

	// Twitter
	$('#footer #share .twitter').attr('href', 'http://twitter.com/home?status=' + url);

	// Google Maps
	$('#footer #share .google').attr('href', 'http://maps.google.com/?q=' + token['lat'] + ',' + token['lon']);
	
	// Find Route
	$('#footer #share .find-route').attr('href', 'http://twitter.com/home?status=' + url);
}

function handlezoomchange(level)
{
	debug('New zoom level: ' + level);
	// TODO: save on cookie to allow refreshing with context
}

function handlemaptypechange(type)
{
	debug('New map type: ' + type);
	// TODO: save on cookie to allow refreshing with context
}

function setstreetview()
{
	streetview.getPanoramaByLocation(new google.maps.LatLng(token['lat'], token['lon']), 50, processStreetViewData);
}

function processStreetViewData(data, status)
{
	if (status == google.maps.StreetViewStatus.OK)
	{
		// show view street button
		$('#tokenpanel .view-street').css('display', 'inline-block');

	    panorama = map.getStreetView();
	    panorama.setPosition(new google.maps.LatLng(token['lat'], token['lon']));
	    panorama.setPov({
	        heading: 265,
	        zoom:1,
	        pitch:0}
	    );
	}
	else
	{
		// hide view street button
		$('#tokenpanel .view-street').css('display', 'none');
	}
}

function findpin()
{
	map.panTo(pin.getPosition());
	return false;
}

function viewstreet()
{
    var toggle = panorama.getVisible();
    if (toggle == false) {
      panorama.setVisible(true);
    } else {
      panorama.setVisible(false);
    }
    
    return false;
}

function openmapalert(message)
{
	var $map = $('#mapcanvas');
	var $box = $('#map-alert').find('span').text(message).end();

	var top = $map.offset().top + ($map.height() - $box.height()) / 2;
	var left = $map.offset().left + ($map.width() - $box.width()) / 2;

	// center progress box over the map
	$box.css('top', top + 'px').css('left', left + 'px').fadeIn(1000, null);
}

//
// Geolocation
//

function findme()
{
	window.cancelgeolocation = 0;

	// calculate position for progress notification
	var $map = $('#mapcanvas');
	var $box = $('#map-progress');
	
	var top = $map.offset().top + ($map.height() - $box.height()) / 2;
	var left = $map.offset().left + ($map.width() - $box.width()) / 2;
	
	// center progress box over the map
	$box.css('top', top + 'px').css('left', left + 'px').fadeIn(1000, null);

	navigator.geolocation.getCurrentPosition(processfindme, geolocationerror, { enableHighAccuracy: true });
	return false; // stop event
}

function processfindme(position)
{
	if(window.cancelgeolocation++ == 0)
	{
		$('#map-progress').fadeOut(1000, null);
		map.panTo(new google.maps.LatLng(position.coords.latitude, position.coords.longitude));
		map.setZoom(17);
	}
	else
	{
		debug('Geolocation replica!');
	}
}

function findroute()
{
	window.cancelgeolocation = 0;

	// calculate position for progress notification
	var $map = $('#mapcanvas');
	var $box = $('#map-progress');
	
	var top = $map.offset().top + ($map.height() - $box.height()) / 2;
	var left = $map.offset().left + ($map.width() - $box.width()) / 2;
	
	// center progress box over the map
	$box.css('top', top + 'px').css('left', left + 'px').fadeIn(1000, null);

	navigator.geolocation.getCurrentPosition(processfindroute, geolocationerror, { enableHighAccuracy: true });
	return false; // stop event
}

function processfindroute(position)
{
	if(window.cancelgeolocation++ == 0)
	{
		$('#map-progress').fadeOut(1000, null);
		var lat = position.coords.latitude;
		var lon = position.coords.longitude;
		window.location.href = 'http://maps.google.com/?saddr=' + lat + ',' + lon + '&daddr=' + token['lat'] + ',' + token['lon'];
	}
	else
	{
		debug('Geolocation replica!');
	}
}

function geolocationerror(error)
{
	if(window.cancelgeolocation++ == 0)
	{
		$('#map-progress').fadeOut(500, function() {
			var geolocationerrors = [ 'Ooopsss! Something went wrong. Please try again later.',
			                          'Wizi does not have permission to use your location.',
			                          'Ooopsss! Couldn\'t find your location.',
			                          'Ooopsss! Couldn\'t find your location.' ];
	
			openmapalert(geolocationerrors[error.code]);
		});
	}
}



//
// Utilities
//

function gettokeninurl(url)
{
	//var regex = new RegExp('^https?\:\/\/([a-z0-9]+\.)?wizi\.com\/([a-zA-Z0-9\/]+)$');
	var regex = new RegExp('.*wizi\.com\/([a-zA-Z0-9]+)', 'i');

	var match = regex.exec(url ? url : window.location.href);
	if(match == null)
	{
		// check if we are in debug mode
		//regex = RegExp('^(.*)\?tok=([a-zA-Z0-9\/]+)(\\??.*)$');
		regex = new RegExp('.*wizi\.com\/.*?tok=([a-zA-Z0-9]+)', 'i');
		match = regex.exec(url ? url : window.location.href);
	}

	//return match != null ? match[2] : null;
	return match != null ? match[1] : null;
}

function getid(op, args)
{
	var id = Math.floor(Math.random() * 10000000);
	eventids[id] = op;
	eventargs[id] = args;

	return id;
}

function tokengetlink(token, cn)
{
	if(! token['links'])
		return null;

	// decode links json
	var links = eval('(' + decodebase64(token['links']) + ')');
	
	var link = null;
	$.each(links, function(index, value) {
		if(value['cn'] == cn)
		{
			link = value;
			return false;
		}
	});

	return link;
}

function formatupdatetime(ts, future)
{
    var date = new Date(ts * 1000);
    var now = new Date();
    var nowts = now.getTime() / 1000;
    var minute = 60;
    var hour = 60 * minute;
    var day = 24 * hour;
    var month = 30 * day;
    
    var diff = (future ? ts - nowts : nowts - ts);
    if(diff < minute)
        return NOW_STRING;
    if(diff < hour)
        return parseInt(diff / 60) + ' ' + (parseInt(diff / 60) != 1 ? MINUTES_STRING : MINUTE_STRING) + ' ' + AGO_STRING;
    else if(diff < day)
        return parseInt(diff / hour) + ' ' + (parseInt(diff / hour) != 1 ? HOURS_STRING : HOUR_STRING) + ' ' + AGO_STRING;
    else if(diff < 30 * day)
        return parseInt(diff / day) + ' ' + (parseInt(diff / day) != 1 ? DAYS_STRING : DAY_STRING) + ' ' + AGO_STRING;
    else if(diff < 12 * month)
        return parseInt(diff / month) + ' ' + (parseInt(diff / month) != 1 ? MONTHS_STRING : MONTH_STRING) + ' ' + AGO_STRING;
    else
        return date.toDateString();
}

function encodebase64(string)
{
	var base64 = new G_Base64();
    var array = base64.arrayifyString(string);
    return base64.encodeByteArray(array, true);
}

function decodebase64(string)
{
	var base64 = new G_Base64();
	var array = base64.decodeString(string.replace(/-/g,'+').replace(/_/g,'/').replace(/\./g,'='), true);
	return base64.stringifyArray(array);
}

function debug(message)
{
//	console.log(message);
}

