// Copyright (c) 2005 Just Objects B.V. <just@justobjects.nl>
// Distributable under LGPL license. See terms of license at gnu.org.

/*
 * GeoTracing app.
 *
 * PURPOSE
 * Library representing the app. All starts here.
 *
 * Author: Just van den Broecke
 * $Id: gtapp.js,v 1.59 2006-04-26 08:49:40 just Exp $
 */

// Pushlet Data Event Callback from Server
function onData(event) {
	GTAPP.onLiveData(event);
}

// The GeoTracing application functions
var GTAPP = {
	map: null,
	mapSpecs: [],
	statusId: null,
	mode: 'none',
	menu: null,
	userSelector: null,
	trackSelector: null,
	SIG: '<a style="background-color:red; border: 1px solid #eeeeee; font:10px verdana;text-decoration:none;padding:2px;color:#eeeeee;" href="http://www.geotracing.com" target="_new">Powered by GeoTracing</a>',
	initialized: false,

	init: function() {
		if (GTAPP.initialized == true) {
			return;
		}

		// Init server.js
		SRV.init();

		DH.hide(DH.getObject('help'));

		GTAPP.showStatus('Initializing...');

		// Creates Google Map object
		GTAPP.createMap();

		// Add GT signature
		GTAPP.addSig();

		// Init gtwidget.js
		GTW.init(GTAPP.map);

		GTAPP.createMenu();

		GTAPP.showStatus('init OK');

		GTAPP.doPageCommand();

		GTAPP.initialized = true;
	},

/** Add GT signature to map. */
	addSig: function() {
		var id = 'gtsig';
		if (!DH.getObject(id)) {
			var b = document.createElement('div');
			b.id = id;
			b.style.position = 'absolute';
			b.style.left = '30%';
			b.style.bottom = '5px';
			b.style.zIndex = 25600;
			b.innerHTML = GTAPP.SIG;
			document.body.appendChild(b);
			DH.setOpacity(b, 0.7);
		}
	},

	addMapSpec: function(name, spec) {
		GTAPP.mapSpecs[name] = spec;
	},

	/** Create Google Map object. */
	createGMap: function(div) {
		// GMap expects normal (non-associative array)
		var mapSpecs = new Array();
		for (var i in GTAPP.mapSpecs) {
			mapSpecs.push(GTAPP.mapSpecs[i]);
		}
		GTAPP.map = new GMap(DH.getObject(div), mapSpecs);
		return GTAPP.map;
	},

	createMap: function() {
		alert('createMap needs to be defined in your app');
	},

// Setup callbacks in CSS drop-down menu
	createMenu: function() {
		GTAPP.menu = new Menu('mainmenu');
	},

// Optional command passed as query string to the page
	doPageCommand: function() {
		var cmd = DH.getPageParameter('cmd', null);
		if (cmd == null) {
			// nop
			return;
		}

		if (cmd == 'showtrack') {
			var id = DH.getPageParameter('id', null);
			var tracerName = DH.getPageParameter('user', null);
			if (id == null || tracerName == null) {
				alert('need track id (id) and user name (user)');
				return;
			}

			GTAPP.showStatus('Drawing track for user ' + tracerName);

			GTAPP.onTrackSelect(id, null, tracerName);
			GTW.displayTrackPlayer();

			GTAPP.showStatus('Track drawn for user ' + tracerName);

			return true;
		} else if (cmd == 'autoplay') {
			// No menu visible
			if (GTAPP.menu != null) {
				GTAPP.menu.hide();
			}
			GTAPP.mAutoPlay();
		} else {
			return false;
		}
	},

// Query active tracks callback
	onQueryActiveUsers: function(records) {
		GTAPP.showStatus(records.length + ' active users');

		GTAPP.userSelector = new Selector('Select a User', 'usersel', GTAPP.onTrackSelect);
		GTAPP.userSelector.hide();

		// Create a Tracer for each active track
		for (i = 0; i < records.length; i++) {
			trackId = records[i].getField('id');
			trackName = records[i].getField('name');
			tracerName = records[i].getField('loginname');
			GTAPP.userSelector.addOption(trackId, tracerName + ' - ' + trackName, tracerName);

			tracer = GTW.createTracer(records[i].getField('loginname'),
					records[i].getField('lon'), records[i].getField('lat'));
			tracer.hide();
		}

		// Listen to Pushlet events from server (see onData)
		GTAPP.mode = 'live';

		p_join_listen('/gt');

		// Hide status div
		GTAPP.userSelector.setXY(300, 10);
		GTAPP.userSelector.show();

		GTAPP.showStatus('Live Mode - ' + records.length + ' users');
	},

	onQueryAllTracks: function (records) {
		GTAPP.trackSelector = new Selector('Select a Track', 'tracksel', GTAPP.onTrackSelect);
		GTAPP.trackSelector.hide();
		var trackId, trackName, tracerName;
		for (var i = 0; i < records.length; i++) {
			trackId = records[i].getField('id');
			trackName = records[i].getField('name');
			tracerName = records[i].getField('loginname');
			GTAPP.trackSelector.addOption(trackId, tracerName + ' - ' + trackName, tracerName);
		}
		GTAPP.trackSelector.setXY(300, 10);
		GTAPP.trackSelector.show();
		GTAPP.showStatus('Archive Mode - ' + records.length + ' tracks');
	},

	onQueryAllUsers: function (records) {
		GTAPP.showStatus('Got ' + records.length + ' users');

		GTAPP.userSelector = new Selector('Select a User', 'usersel', GTAPP.onUserSelect);
		GTAPP.userSelector.hide();

		var userId, userName;
		for (var i = 0; i < records.length; i++) {
			userId = records[i].getField('id');
			userName = records[i].getField('loginname');
			GTAPP.userSelector.addOption(userId, userName, userName);
		}

		GTAPP.userSelector.setWidth(10);
		GTAPP.userSelector.setXY(300, 10);
		GTAPP.userSelector.show();
		GTAPP.showStatus('Archive Mode - ' + records.length + ' users');
	},

	onQueryUserTracks: function (records) {
		GTAPP.trackSelector = new Selector('Select a Track', 'tracksel', GTAPP.onTrackSelect);
		GTAPP.trackSelector.hide();

		var trackId, trackName, userName;
		for (var i = 0; i < records.length; i++) {
			trackId = records[i].getField('id');
			trackName = records[i].getField('name');
			userName = records[i].getField('loginname');
			GTAPP.trackSelector.addOption(trackId, trackName, userName);
		}

		GTAPP.trackSelector.setXY(430, 10);
		GTAPP.trackSelector.show();
		GTAPP.showStatus('Archive - user has ' + records.length + ' tracks');
	},

	onQueryMediaInBbox: function (records) {
		GTAPP.showStatus('Found ' + records.length + ' media, displaying...');
		GTW.displayMedia(records);
		GTAPP.showStatus('Displaying ' + records.length + ' media');
	},

	onQueryPOIsInBbox: function (records) {
		GTAPP.showStatus('Found ' + records.length + ' POIs, displaying...');
		GTW.displayPOIs(records);
		GTAPP.showStatus('Displaying ' + records.length + ' POIs');
	},


	clearMap: function () {
		GTW.clearMap();
	},


	hideStatus: function() {
		DH.hide('status');
		if (GTAPP.statusId != null) {
			clearInterval(GTAPP.statusId);
			GTAPP.statusId = null;
		}

	},

	blinkStatus: function(txt) {
		GTAPP.hideStatus();
		DH.setHTML('status', txt);
		GTAPP.statusId = setInterval(function() {
			DH.toggleVisibility('status')
		}, 400);
	},

	showStatus: function(txt) {
		GTAPP.hideStatus();
		DH.setHTML('status', txt);
		DH.show('status');
	},

	showLiveStatus: function (tracerName, txt) {
		GTAPP.showStatus(tracerName + ' ' + txt);
	},

	_deleteSelectors: function() {
		if (GTAPP.trackSelector != null) {
			GTAPP.trackSelector.hide();
			GTAPP.trackSelector.clear();
			delete GTAPP.trackSelector;
			GTAPP.trackSelector = null;
		}

		if (GTAPP.userSelector != null) {
			GTAPP.userSelector.hide();
			GTAPP.userSelector.clear();
			delete GTAPP.userSelector;
			GTAPP.userSelector = null;
		}

	},

//
// SELECTOR CALLBACK FUNCTIONS
//

// Track selected e.g. in combo box
	onTrackSelect: function(trackId, trackName, tracerName) {
		// alert('select track: id=' + trackId + ' tracer=' + tracerName + ' trkName=' + trackName);
		// GTAPP.clearMap();
		if (GTAPP.mode == 'archive') {
			GTW.displayTrackPlayer();
		}


		var tracer = GTW.createTracer(tracerName);
		tracer.readTrack(trackId, trackName, true);
		tracer.show();
	},

// User selected
	onUserSelect: function(userId, loginName) {
		// alert('u=' + userId + ' l=' + loginName);
		if (GTAPP.trackSelector != null) {
			GTAPP.trackSelector.hide();
			GTAPP.trackSelector.clear();
			delete GTAPP.trackSelector;
			GTAPP.trackSelector = null;
		}
		GTAPP.blinkStatus('Getting tracks for ' + loginName + "...");
		SRV.get('q-tracks-by-user', GTAPP.onQueryUserTracks, 'user', loginName);
	},

//
// MENU CALLBACK FUNCTIONS
//
	mAutoPlay: function() {
		if (GTAPP.mode == 'autoplay') {
			return;
		}

		GTAPP.showStatus('autoplay');
		if (GTAPP.mode == 'live') {
			p_leave();
		}
		GTAPP.mode = 'autoplay';
		GTAPP.clearMap();
		GTAPP._deleteSelectors();
		GTW.startAutoPlay();
	},

	mArchive: function() {
		if (GTAPP.mode == 'archive') {
			return;
		}

		if (GTAPP.mode == 'live') {
			p_leave();
		}

		GTAPP.mode = 'archive';
		GTAPP.clearMap();
		GTAPP._deleteSelectors();
		GTAPP.blinkStatus('Getting all users...');
		SRV.get('q-all-users', GTAPP.onQueryAllUsers);
	},

	mLive: function(e) {

		if (GTAPP.mode == 'live') {
			return;
		}

		// Get all active tracks
		GTAPP.clearMap();
		GTAPP._deleteSelectors();

		GTAPP.blinkStatus('Getting active users...');
		SRV.get('q-active-tracks', GTAPP.onQueryActiveUsers);

	},

	mShowMediaInBbox: function(e) {
		if (GTAPP.mode == 'live') {
			p_leave();
		}

		GTAPP.mode = 'media';

		// Get all active tracks
		GTW.clearTracers();
		GTW.clearTrackPlayer();
		GTAPP._deleteSelectors();
		GTW.stopAutoPlay();

		GTAPP.blinkStatus('Getting media...');
		var bounds = GTAPP.map.getBoundsLatLng();
		var bbox = bounds.minX + ',' + bounds.minY + ',' + bounds.maxX + ',' + bounds.maxY;
		SRV.get('q-media-in-bbox', GTAPP.onQueryMediaInBbox, 'bbox', bbox);
	},

	mShowPOIsInBbox: function(e) {
		if (GTAPP.mode == 'live') {
			p_leave();
		}

		GTAPP.mode = 'poi';

		// Get all active tracks
		GTW.clearTrackPlayer();
		GTW.clearTracers();
		GTAPP._deleteSelectors();
		GTW.stopAutoPlay();

		GTAPP.blinkStatus('Getting POIs...');
		var bounds = GTAPP.map.getBoundsLatLng();
		var bbox = bounds.minX + ',' + bounds.minY + ',' + bounds.maxX + ',' + bounds.maxY;
		var records = SRV.get('q-pois-in-bbox', null, 'bbox', bbox);
		GTAPP.showStatus('Found ' + records.length + ' POIs, displaying...');
		GTW.displayPOIs(records);
		GTAPP.showStatus('Displaying ' + records.length + ' POIs');

	},

	mShowHelp: function(url) {
		var helpPanel = new Panel('HELP', 'red', 'white');
		helpPanel.setXY(100, 100);
		helpPanel.setDimension(500, 500);
		helpPanel.loadContent(url);
	},

// Switch background map type
	mSetMap: function(type) {
		GTAPP.map.setMapType(GTAPP.mapSpecs[type]);
	},


// Pushlet Data Event Callback from Server
// These are events sent by tracing users (e.g. from mobile phone)
	onLiveData: function (event) {
		// See EventPublisher.java for Event types/fields
		// Event types and attributes:
		// "user-hb" : id, username, time, [trackname]
		// "user-move": id, username, time, trackid, trackname, lon, lat
		// "medium-add": id, name, kind, mime, time, userid, username, trackid, trackname, lon, lat, ele
		// "poi-add": id, name, type, state, time, userid, username, trackid, trackname, lon, lat, ele
		// "poi-delete": id, userid, username, trackid, trackname
		// "poi-hit": id, name, type, state, time, userid, username, ownerid, ownername, trackid, trackname, lon, lat, ele
		//" track-create": id, name, userid, username
		// "track-delete": id, name, userid, username
		// "track-suspend": id, name, userid, username
		// "track-resume": id, name, userid, username
		if (GTAPP.mode != 'live') {
			return;
		}

		var eventType = event.get('event');

		var tracerName = event.get('username');
		var tracer = GTW.getTracer(tracerName);
		if (!tracer) {
			// create new Tracer object, most events have lon/lat
			tracer = GTW.createTracer(tracerName, event.get('lon'), event.get('lat'));
		}

		var statusText = 'unknown';
		if (eventType == 'user-move') {
			// User sends location
			// Set indicator
			tracer.setLive();
			if (tracer.activeTrack == null) {
				tracer.show();
				// tracer.readTrack(event.get('trackid'), event.get('trackname'), true);
			}

			tracer.move(event.get('lon'), event.get('lat'));
			statusText = 'moves to (' + event.get('lon') + ',' + event.get('lat') + ')';
		} else if (eventType == 'user-hb') {
			// User sends heartbeat
			statusText = 'sends heartbeat';

		} else if (eventType == 'medium-add') {
			// User submits medium
			var medium = new Medium(event.get('id'),
					event.get('name'),
					event.get('kind'),
					event.get('mime'),
					event.get('time'),
					tracer.panel,
					event.get('lon'),
					event.get('lat'));

			tracer.addMedium(medium);
			medium.display();
			statusText = 'adds ' + event.get('kind');
		} else if (eventType == 'poi-add') {
			// User adds Point of Interest

			var poi = new POI(event.get('id'),
					event.get('name'),
					event.get('type'),
					event.get('time'),
					tracer.panel,
					event.get('lon'),
					event.get('lat'));

			tracer.addPOI(poi);
			poi.display();
			statusText = 'adds POI ' + event.get('name');
		} else if (eventType == 'poi-delete') {
		} else if (eventType == 'poi-hit') {
			// Only POI supported is BOMB
			//tracerName = event.get('username');
			// Get Tracer
			//var tracer = GTW.getTracer(tracerName);
			//if (!tracer) {
			//  return;
			//}

			// Let tracer redraw active track with less points
			//if (tracer.activeTrack != null) {
			//   var trackId = tracer.activeTrack.id;
			//   tracer.deleteTrack(trackId);
			//   tracer.drawTrack(trackId);
			//   alert('BOMBED: victim=' + event.get('username') + ' owner=' + event.get('ownername') + ' id=' + event.get('id'));
			// }
		} else if (eventType == 'track-create') {
			// User creates new track
			tracer.newTrack(event.get('id'), event.get('name'));
			statusText = 'creates track ' + event.get('name');
		} else if (eventType == 'track-delete') {
			tracer.deleteTrack(event.get('id'), event.get('name'));
			statusText = 'deletes track ' + event.get('name');
		} else if (eventType == 'track-suspend') {
			tracer.suspendTrack();
			statusText = 'suspends track';
		} else if (eventType == 'track-resume') {
			tracer.resumeTrack();
			statusText = 'resumes track';
		} else {
		}

		GTAPP.showLiveStatus(tracerName, statusText);
	}


}

// Starts it all
DH.addEvent(window, 'load', GTAPP.init, false);
