if (!window.navsys) { 
    window.navsys = {};
}

if (!navsys.gui) { 
    navsys.gui = {};
}

navsys.gui.GUserLocator = function() {
	this.demo = false;
	this.refresh_interval = 5;
	this.time_for_old_markers = 60*60*24;
	this.group_id = null;
	this.map = null;
	this.users = {};
	this.locations = {};
	this.tracks = {};
	this.tracksCache = {};
	this.latlng_bounds=null;

	this.selected_user_id = null;
	this.selected_user_id_info = null;
	this.selected_user_last_time = null;
	this.selectedPolylineStyle = {
		'color': '#ff0000',
		'weight': 8,
		'opacity': 0.7
	};
	this.commonPolylineStyle = {
			'color': '#aa0077',
			'weight': 5, 
			'opacity': 0.3
		};	
	this.enable_watching = true;
	this.block_disabling_of_watching = false;
	this.mapBoundsInProgress = false;
	
	this.watchingButton = {};
	this.locatorUsersList = new navsys.gui.LocatorUserList();
	this.previousLocations = {};
	this.currentLocations = {};
	
	// Settings
	this.buildChronologicalTimeLineOfPoints = false;
	this.numberOfPointsInCacheLine = 25; //25
	this.maxNumberOfCacheLines = 10; //10

	// lang
	this.lang={};
	this.lang.enable_watching = 'Вернуться в режим слежения';
	this.lang.cant_find_address = 'Не удалось установить адрес';
}


navsys.gui.GUserLocator.prototype.buildLayout = function() {
	middleLayout = $('div.outer-center').layout({
    	center__paneSelector: ".middle-center",
    	west__paneSelector: ".middle-west",
    	west__size: 370,
    	west__minSize: 150,
    	west__maxSize: 650,
    	spacing_open: 8,
    	spacing_closed: 12
        });
}


navsys.gui.GUserLocator.prototype.startDemoMode = function() {
	this.demo = true;
}

navsys.gui.GUserLocator.prototype.startAutoRefresh = function( refresh_interval ) {
	if (refresh_interval) {
		this.refresh_interval = refresh_interval;
	}
	setTimeout('locator.refresh()', 1000*this.refresh_interval);
}

navsys.gui.GUserLocator.prototype.refresh = function() {
	this.loadLocations();
	setTimeout('locator.refresh()', 1000*this.refresh_interval);	
}

navsys.gui.GUserLocator.prototype.refreshTracksOnMap = function() {
	for (var user_id in this.tracks) {
		this.removeTrack(user_id);
	}
	
	for (var user_id in this.users) {
		this.rebuildTrack(user_id);
	}
	
	this.mapBounds();
}

navsys.gui.GUserLocator.prototype.setGroupId = function(id) {
	this.group_id = id;
}

navsys.gui.GUserLocator.prototype.getGroupId = function() {
	return this.group_id;
}

navsys.gui.GUserLocator.prototype.clearUsers = function() {
	this.users = {};
}

navsys.gui.GUserLocator.prototype.setUsers = function(users) {
	this.users = users;
	this.refreshTracksOnMap();
}

navsys.gui.GUserLocator.prototype.addUser = function(id, user) {
	this.users[id] = user;
}

navsys.gui.GUserLocator.prototype.getUserById = function(id) {
	if (this.users[id]) {
		return this.users[id];
	} else {
		return null;
	}	
}

navsys.gui.GUserLocator.prototype.clearLocations = function() {
	this.locations = {};
	this.tracks = {};
	this.latlng_bounds=null;
}

navsys.gui.GUserLocator.prototype.removeTrack = function(user_id) {
	if (this.tracks[user_id]) {
		var track = this.tracks[user_id];
		if (track.polyline) {
			this.map.removeOverlay(track.polyline);
		}
		if (track.marker) {
			this.map.removeOverlay(track.marker);
		}
		delete this.tracks[user_id];
	}
	this.removeTrackCacheLinesFromMap(user_id);
}

navsys.gui.GUserLocator.prototype.setCurrentUser = function(id, login) {
	var user = {
			id: id,
			username: login
		};
	this.locatorUsersList.currentUser = user;
}

navsys.gui.GUserLocator.prototype.getMap = function() {
	return this.map;
}

navsys.gui.GUserLocator.prototype.init = function() {
	this.initMap();
	this.fillUserLocationList();
		
	if (this.group_id != null) {
		$("#userLocationShowInGroup").change(function () {
			var options = {
					g: this.value,
					a: this.checked ? "e" : "d"
			};
			$.post("/group/show-location", options, function (response) {
				// do nothing
			});
		});
	}

	$("#userLocationNameSubmit").click(function () {
		var name = $("[name=userLocationUserName]", $(this.form)).val();
		locator.fillUserLocationList({
			name_like: name
		});
	});	
}

navsys.gui.GUserLocator.prototype.initMap = function() {
	this.map = new GMap2($("#userLocationMap").get(0));
	this.map.enableScrollWheelZoom();
	this.map.enableContinuousZoom();
	this.map.addControl(new GMapTypeControl());
	this.map.addControl(new GLargeMapControl());
	this.map.enableContinuousZoom();
	
	this.initWatchingButton();
	this.addWatchingEvents();
}

navsys.gui.GUserLocator.prototype.initWatchingButton = function() {
    NavsysCustomControl = function(){
    }

    NavsysCustomControl.prototype = new GControl();
    NavsysCustomControl.prototype.initialize = function(map){
	var container = document.createElement("div");
	container.className='googleCustomButtonContainer';

	var navsysAddNewControlDiv = document.createElement("div");
	navsysAddNewControlDiv.className='googleCustomButton';
	navsysAddNewControlDiv.id='switchWatching';

	container.appendChild(navsysAddNewControlDiv);
	//navsysAddNewControlDiv.appendChild(document.createTextNode(locator.lang.disable_watching));
	
	GEvent.addDomListener(navsysAddNewControlDiv, "click", function(){
	    locator.switchWatching();
	});

	map.getContainer().appendChild(container);
	return container;
    }

    NavsysCustomControl.prototype.getDefaultPosition = function(){
    	return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(20, 30));
    }

    this.watchingButton = new NavsysCustomControl();
}

 
navsys.gui.GUserLocator.prototype.addWatchingEvents = function() {
	GEvent.addListener(this.map, "load", function() {locator.enableWatching()} );
	GEvent.addListener(this.map, "moveend", function() {locator.moveend()} );
	GEvent.addListener(this.map, "zoomend", locator.zoomend );
}


navsys.gui.GUserLocator.prototype.selectUser = function (user_id) {
	if (this.selected_user_id != user_id) {
		var previous_user_id = this.selected_user_id;
		this.selected_user_id = user_id;
		this.selected_user_id_info = user_id;

	
		$('.uid__'+user_id).addClass('active');
		$('.uid__'+previous_user_id).removeClass('active');
		
		this.setStyleForUserTrackLine(this.selected_user_id, this.selectedPolylineStyle);
		this.setStyleForUserTrackLine(previous_user_id, this.commonPolylineStyle);
	} else {
		this.setStyleForUserTrackLine(this.selected_user_id, this.commonPolylineStyle);
		this.selected_user_id = null;
		this.selected_user_id_info = null;
		$('.uid__'+user_id).removeClass('active');
	}
	
	this.rebuildTrack(user_id);
	this.rebuildTrack(previous_user_id);	
}

navsys.gui.GUserLocator.prototype.setStyleForUserTrackLine = function (userId, style) {
	if (this.tracksCache[userId]) {
		for (var i in this.tracksCache[userId]) {
			var trackCacheLine = this.tracksCache[userId][i];
			trackCacheLine.setStrokeStyle(style);
		}		
	}
}

navsys.gui.GUserLocator.prototype.fillUserLocationList = function (options) {
	var options = {};	
	var urlForGetUsers;
	
	if (this.group_id != null) {
		urlForGetUsers = "/group/"+this.group_id+"/members/list.json";
	} else {		
		if (this.demo) {
			urlForGetUsers = "/locator/get-list-of-users-demo";
		} else {
			urlForGetUsers = "/locator/get-list-of-users";
		}
	}
	
	$.get(urlForGetUsers, options, function (response){
		var list = eval(response);
		
		locator.locatorUsersList.loadAllUsers(list);
		
		locator.loadLocations();
	});
}


navsys.gui.GUserLocator.prototype.loadLocations = function () {
	var options = {};
	var urlForGetLocationOfUsers;
	
	if (this.group_id != null) {
		urlForGetLocationOfUsers = "/user-location/group/"+this.group_id+"/data";
	} else {		
		if (this.demo) {
			urlForGetLocationOfUsers = "/locator/get-location-of-users-demo";
		} else {
			urlForGetLocationOfUsers = "/locator/get-location-of-users";
		}
	}
	
	stop_ajax_start = true;
	$.get(urlForGetLocationOfUsers, options, function(responce) {
		var data = eval(responce);
		
		locator.parseLocationsAndSaveLikeCurrentLocations(data);
		locator.parseLocations(data);
		locator.buildTracks();
		locator.mapBounds();
		stop_ajax_start = false;
	});
}

navsys.gui.GUserLocator.prototype.parseLocations = function (data) {
	for (var key in data) {
		var item = data[key];
		var user_id=item.user_id;
		var time=item.utime;

		if (!this.locations[user_id]) {
			this.locations[user_id] = {};
		}

		if (!this.locations[user_id][time]) {
			if (this.previousLocations && this.previousLocations[user_id]) {
				var previousLocationOfUser = this.previousLocations[user_id];
				var previousLat = previousLocationOfUser.latitude;
				var previousLng = previousLocationOfUser.longitude;
			} else {
				var previousLat = -1;
				var previousLng = -1;
			}
			
			if (previousLat == item.latitude && previousLng ==  item.longitude) {
				var previousTime = previousLocationOfUser.utime;
				delete this.locations[user_id][previousTime];
			} else {
				this.removeTrack(user_id);
				this.latlng_bounds=null;
			}
			
			this.locations[user_id][time] = item;
		}
	}
}

navsys.gui.GUserLocator.prototype.parseLocationsAndSaveLikeCurrentLocations = function (data) {
	this.previousLocations = this.currentLocations;
	this.currentLocations = {};
	for (var key in data) {
		var item = data[key];
		var userId=item.user_id;		
		this.currentLocations[userId] = item;
	}
}

navsys.gui.GUserLocator.prototype.trackBounds = function ( user_id ) {
	if (this.tracks[user_id] && this.tracks[user_id].polyline) {
		if (this.tracks[user_id] && this.tracks[user_id].polyline) {
			var bounds = this.tracks[user_id].polyline.getBounds();
			if (bounds) {
				var zoom = this.map.getBoundsZoomLevel(bounds);
				this.map.setCenter(bounds.getCenter(), zoom);
			}
		}
	}
}

navsys.gui.GUserLocator.prototype.mapBounds = function () {
	if (this.users && this.getCount(this.users)<1) {
		this.map.setCenter(new GLatLng(60, 80), 3);
		return;
	}
	
	if (this.enable_watching && !this.mapBoundsInProgress) {
		this.mapBoundsInProgress = true;
		
		var zoom = this.map.getZoom();
		var center = this.map.getCenter();
		
		this.latlng_bounds=new GLatLngBounds();
		
		var watchingUsers = this.getUsersForWatching();
		var countOfWatchingUsers = this.getCount(watchingUsers);
		
		if (countOfWatchingUsers == 0 && center && !(center.lat()==0 && center.lng()==180)) {
			this.mapBoundsInProgress = false;
			return;
		}
		
		if (countOfWatchingUsers != 1) {
			var users = (countOfWatchingUsers == 0) ? this.users : watchingUsers;

			for (var user_id in users) {
				if (this.currentLocations[user_id]) {
					var point = this.currentLocations[user_id];
					var latlng = new GLatLng(point.latitude, point.longitude);
					this.latlng_bounds.extend(latlng);
				}
			}
			
			zoom = this.map.getBoundsZoomLevel(this.latlng_bounds);
			center = this.latlng_bounds.getCenter();
		} else {
			
			for (var user_id in watchingUsers) {
				break;
			}
			if ((watchingUsers[user_id]).allow=='t' && this.currentLocations[user_id]) {
				var point = this.currentLocations[user_id];
				var latlng = new GLatLng(point.latitude, point.longitude);
				this.latlng_bounds.extend(latlng);
				center = this.latlng_bounds.getCenter();
				if (zoom == null || zoom == 'NaN' || !zoom) {
					zoom = this.map.getBoundsZoomLevel(this.latlng_bounds);
				}
			}
			
		}

		if (center && center!=null && zoom && zoom!='NaN') {
			this.block_disabling_of_watching = true;
			this.map.setCenter(center, zoom);
		}
		
		this.mapBoundsInProgress = false;
	}
}

navsys.gui.GUserLocator.prototype.getUsersForWatching = function () {
	var tempUsers = this.locatorUsersList.usersByLabel[2];
	var users = {};
	for (var key in tempUsers) {
		var user = tempUsers[key];
		if (user && user.allow=='t') {
			users[user.id] = user;
		}
	}
	return users;
}

navsys.gui.GUserLocator.prototype.getCount = function(item) {
	var count = 0;
	for (var key in item) {
		count ++;		
	}
	return count;
}

navsys.gui.GUserLocator.prototype.getMaxKey = function(item) {
	var maxKey = 0;
	for (var key in item) {
		keyInt = parseInt(key);
		if (maxKey < keyInt) {
			maxKey = keyInt;
		}
	}
	return maxKey;
}


navsys.gui.GUserLocator.prototype.getMinKey = function(item) {
	var minKey = parseInt(999999);
	for (var key in item) {
		keyInt = parseInt(key);
		if (minKey > keyInt) {
			minKey = keyInt;
		}
	}
	return minKey;
}


navsys.gui.GUserLocator.prototype.buildTracks = function () {
	for (var user_id in this.locations) {
		if (!this.tracks[user_id]) {
			this.rebuildTrack(user_id);
		}
	}	
}

navsys.gui.GUserLocator.prototype.rebuildTrack = function ( user_id ) {
	this.removeTrack(user_id);	
	var track = this.buildTrack(user_id);
	this.tracks[user_id] = track;
	
	if (this.users[user_id]) {
		if (track.polyline) {
			this.map.addOverlay(track.polyline);
		}
		if (track.marker) {
			this.map.addOverlay(track.marker);
		}

		this.showTrackCacheLinesOnMap(user_id);
	}
}

navsys.gui.GUserLocator.prototype.removeTrackCacheLinesFromMap = function(userId) {
	if (this.tracksCache[userId]) {
		for (var key in this.tracksCache[userId]) {
			var cacheLine = this.tracksCache[userId][key];
			this.map.removeOverlay(cacheLine);
		}
	}
}

navsys.gui.GUserLocator.prototype.showTrackCacheLinesOnMap = function(userId) {
	if (this.tracksCache[userId]) {
		for (var key in this.tracksCache[userId]) {
			var cacheLine = this.tracksCache[userId][key];
			this.map.addOverlay(cacheLine);
		}
	}
}

navsys.gui.GUserLocator.prototype.buildTrack = function (user_id) {
	if (this.buildChronologicalTimeLineOfPoints) {
		var time_line = this.buildChronologicalTimeLine(user_id);
		var way = this.buildChronologicalWayOfPoints(user_id, time_line);
	} else {
		var way = this.buildWayOfPoints(user_id);
	}
	
	if (way.length > this.numberOfPointsInCacheLine+1) {
		way = this.buildCacheOfLines(user_id, way);
	}
	
	var polyline = this.buildPolyline(user_id, way);
	var marker = this.buildMarker(user_id);
	
	var track = {};
	track.polyline = polyline;
	track.marker = marker;
	
	return track;
}

navsys.gui.GUserLocator.prototype.buildCacheOfLines = function (userId, way) {
	var wayForCache = new Array();
	var newWay = new Array();
	var j = 0;
	for (var i=0; i<way.length; i++) {
		if (i<this.numberOfPointsInCacheLine) {
			wayForCache[i] = way[i];
			if ((i+1) == this.numberOfPointsInCacheLine) {
				newWay[j] = way[i];
				j++;
			}
		} else {
			newWay[j] = way[i];
			j++;
		}
	}
	// Delete old points
	i = 1;
	for (var time in this.locations[userId]) {
		delete this.locations[userId][time];		
		if (i >= this.numberOfPointsInCacheLine-1) {
			break;
		}
		i++;
	}
	
	// Save cache
	if (!this.tracksCache[userId]) {
		this.tracksCache[userId] = {};
	}
	var cacheNumber = parseInt(this.getMaxKey(this.tracksCache[userId]))+1;
	this.tracksCache[userId][cacheNumber] = this.buildPolyline(userId, wayForCache);
	
	// Delete old cache lines
	if (this.getCount(this.tracksCache[userId])-1 > this.maxNumberOfCacheLines) {
		if (this.tracksCache[userId]) {
			var key = this.getMinKey(this.tracksCache[userId]);
			delete this.tracksCache[userId][key];
			
			this.removeTrackCacheLinesFromMap(userId);
			if (this.users[userId]) {
				this.showTrackCacheLinesOnMap(userId);
			}
		}
	}
	
	return newWay;
}

navsys.gui.GUserLocator.prototype.buildPolyline = function (user_id, way) {
	if (user_id == this.selected_user_id) {
		var polyline = new GPolyline(way, this.selectedPolylineStyle.color, this.selectedPolylineStyle.weight, this.selectedPolylineStyle.opacity);
	} else {
		var polyline = new GPolyline(way, this.commonPolylineStyle.color, this.commonPolylineStyle.weight, this.commonPolylineStyle.opacity);
	}
	
	return polyline;
}

navsys.gui.GUserLocator.prototype.buildChronologicalTimeLine = function (user_id) {
	var locations = this.locations[user_id];	
	var time_line = new Array();
	var i=0;
	for (var time in locations) {
		time_line[i]=time;
		i++;
	}
	time_line.sort();
	return time_line;
}

navsys.gui.GUserLocator.prototype.buildChronologicalWayOfPoints = function (user_id, time_line) {
	var locations = this.locations[user_id];
	var way = new Array();
	for (i=0; i<time_line.length; i++) {
		var point = locations[time_line[i]];
		way[i] = new GLatLng(point.latitude, point.longitude);
	}
	return way;
}

navsys.gui.GUserLocator.prototype.buildWayOfPoints = function (user_id) {
	var locations = this.locations[user_id];
	var way = new Array();
	i=0;
	for (var time in locations) {
		var point = locations[time];
		way[i] = new GLatLng(point.latitude, point.longitude);
		i++;
	}

	return way;
}

navsys.gui.GUserLocator.prototype.buildImageOfMarker = function (user_id) {
	this.updateLastTimeOfUserInList(user_id);
	
	var icon = new GIcon(G_DEFAULT_ICON);	
	var data = new Date();
	var current_time = Math.ceil(data.getTime()/1000);
	var last_time = (this.currentLocations[user_id]).utime;
	
	if (last_time < current_time - this.time_for_old_markers) {
		icon.image = "http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";
	}

	return icon;
}

navsys.gui.GUserLocator.prototype.updateLastTimeOfUsersInList = function () {
	for (var userId in this.currentLocations) {
		this.updateLastTimeOfUserInList(userId);		
	}	
}

navsys.gui.GUserLocator.prototype.updateLastTimeOfUserInList = function (user_id) {
	var human_date = (this.currentLocations[user_id]).utime_formated;
	$('.uid__'+user_id).find('.timeLastPoint').text(' ('+human_date+')');
}

navsys.gui.GUserLocator.prototype.buildMarker = function (user_id) {
	var marker = null;
	if (this.currentLocations[user_id]) {
		var point = this.currentLocations[user_id];
		var marker_latlng = new GLatLng(point.latitude, point.longitude)
		var icon = this.buildImageOfMarker(user_id);
		
		var user = locator.getUserById(user_id);
		var userName = '';
		if (user) {
			userName = user.username;
			
			marker = new GMarker(marker_latlng, {		
				title: userName,
				draggable: false,
				icon: icon
			});

			GEvent.addListener(marker, "click", function(){				
				locator.selectUser(user.id);
			});

			setTimeout('locator.showInfo('+user.id+')', 10);
		}
	}
	return marker;
}

navsys.gui.GUserLocator.prototype.showInfo = function (userId) {
	var user = locator.getUserById(userId);
	var track = this.tracks[userId];
	if (user && track.marker) {
		this.showInfoDirect(track.marker, user);
	}
}

navsys.gui.GUserLocator.prototype.showInfoDirect = function (marker, user) {
	var user_id = user.id;
	
	if (this.selected_user_id_info != user_id) {
		marker.closeInfoWindow();
		return false;
	}
	
	var userName = user.username;
	var point = this.currentLocations[user_id];
	var address = '';
	var query=point.latitude+','+point.longitude;
	var geocoder = new GClientGeocoder();
	geocoder.getLocations(
			query,
			function(response) {
				if (!response || response.Status.code != 200) {
					address = locator.lang.cant_find_address;
				} else {
					var place = response.Placemark[0];
					address = place.address;			    	
				}
				
				var address_html = $("#htmlTemplates > .popupUserMarker > div.infoAddress").clone();
				address_html.find(".address").text(address);
				
				$('#addressOf'+user_id).html(address_html);
			}
	);
	
	var container = $("#htmlTemplates > .popupUserMarker > div.infoMain").clone();
	
	container.find(".userName").text(userName);
	container.find(".timeLastPoint").text(point.utime_formated);
	container.find(".speed").text(point.speed);
	container.find(".coordinates").text(point.latitude + ', ' + point.longitude);
	container.find(".address").attr('id', 'addressOf'+user_id);
	
	marker.openInfoWindowHtml('<div class="popupUserMarker">' + container.html() + '</div>');
	var img = $('.popupUserMarker').parent().parent().parent().find('img').click(function(){locator.selected_user_id_info=null});
}

navsys.gui.GUserLocator.prototype.enableWatching = function () {
	this.enable_watching = true;
	this.map.removeControl(this.watchingButton);
	//$('#switcher_of_watching').text(this.lang.disable_watching);
	this.mapBounds();
}

navsys.gui.GUserLocator.prototype.disableWatching = function () {
	if (!this.block_disabling_of_watching) {
		this.enable_watching = false;
		this.map.addControl(this.watchingButton);
		$('#switchWatching').text(this.lang.enable_watching);
		//this.mapBounds();
	} else {
		this.block_disabling_of_watching = false;
	}
}

navsys.gui.GUserLocator.prototype.switchWatching = function () {
	if (this.enable_watching) {
		this.disableWatching();
	} else {
		this.enableWatching();
	}
}

navsys.gui.GUserLocator.prototype.zoomend = function (oldLevel, newLevel) {
	var countOfWatchingUsers = locator.getCount(locator.getUsersForWatching());
	if (countOfWatchingUsers == 1) {
		locator.enableWatching();
	}
}

navsys.gui.GUserLocator.prototype.moveend = function () {
	var countOfWatchingUsers = locator.getCount(locator.getUsersForWatching());
	if (countOfWatchingUsers !=0 ) {
		locator.disableWatching();
	}
}
