angular.module('appControllers').controller('TrafficCtrl', TrafficCtrl); // get the main module contollers set
TrafficCtrl.$inject = ['$rootScope', '$scope', '$state', '$http', '$interval']; // Inject my dependencies

// create our controller function with all necessary logic
function TrafficCtrl($rootScope, $scope, $state, $http, $interval) {

	$scope.$parent.helppage = 'plates/traffic-help.html';
	$scope.data_list = [];
	$scope.data_list_invalid = [];
	
	function utcTimeString(epoc) {
		var time = "";
		var val;
		var d = new Date(epoc);
		val = d.getUTCHours();
		time += (val < 10 ? "0" + val : "" + val);
		val = d.getUTCMinutes();
		time += ":" + (val < 10 ? "0" + val : "" + val);
		val = d.getUTCSeconds();
		time += ":" + (val < 10 ? "0" + val : "" + val);
		time += "Z";
		return time;
	}
/*

	function dmsString(val) {
		return [0 | val,
				'° ',
				0 | (val < 0 ? val = -val : val) % 1 * 60,
				"' ",
				0 | val * 60 % 1 * 60,
				'"'].join('');
	}
*/

// chop off seconds for space
	function dmsString(val) {
		var deg;
		var min;
		deg = 0 | val;
		min = 0 | (val < 0 ? val = -val : val) % 1 * 60;
		
		return [deg*deg < 100 ? "0" + deg : deg,
				'° ',
				min < 10 ? "0" + min : min,
				"' "].join('');
	}
	
	function setAircraft(obj, new_traffic) {
		new_traffic.icao_int = obj.Icao_addr;
		new_traffic.targettype = obj.TargetType;
		new_traffic.signal = obj.SignalLevel;
		new_traffic.addr_symb ='\u2708';
		if (new_traffic.targettype > 3) {
			new_traffic.addr_symb ='\ud83d\udce1';
		}
		new_traffic.icao = obj.Icao_addr.toString(16).toUpperCase();
		new_traffic.tail = obj.Tail;
		new_traffic.reg = obj.Reg;
		if (obj.Squawk == 0) {
			new_traffic.squawk = "----";
		} else {
			new_traffic.squawk = obj.Squawk;
		}
		new_traffic.addr_type = obj.Addr_type;
		new_traffic.lat = dmsString(obj.Lat);
		new_traffic.lon = dmsString(obj.Lng);
		var n = Math.round(obj.Alt / 25) * 25;
		new_traffic.alt = n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		var s = Math.round(obj.Speed / 5) * 5;
		if (obj.Speed_valid) {
			new_traffic.speed = s.toString();
			new_traffic.heading = Math.round(obj.Track / 5) * 5;
		} else {
			new_traffic.speed = "---";
			new_traffic.heading = "---";
		}
		new_traffic.vspeed = Math.round(obj.Vvel / 100) * 100
		var timestamp = Date.parse(obj.Timestamp);
		new_traffic.time = utcTimeString(timestamp);
		new_traffic.age = obj.Age;
		new_traffic.ageLastAlt = obj.AgeLastAlt;
		new_traffic.src = obj.Last_source; // 1=ES, 2=UAT
		new_traffic.bearing = Math.round(obj.Bearing); // degrees true 
		new_traffic.dist = (obj.Distance/1852); // nautical miles
		// return new_aircraft;
	}


	function connect($scope) {
		if (($scope === undefined) || ($scope === null))
			return; // we are getting called once after clicking away from the status page

		if (($scope.socket === undefined) || ($scope.socket === null)) {
			socket = new WebSocket(URL_TRAFFIC_WS);
			$scope.socket = socket; // store socket in scope for enter/exit usage
		}

		$scope.ConnectState = "Disconnected";

		socket.onopen = function (msg) {
			// $scope.ConnectStyle = "label-success";
			$scope.ConnectState = "Connected";
		};

		socket.onclose = function (msg) {
			// $scope.ConnectStyle = "label-danger";
			$scope.ConnectState = "Disconnected";
			$scope.$apply();
			setTimeout(connect, 1000);
		};

		socket.onerror = function (msg) {
			// $scope.ConnectStyle = "label-danger";
			$scope.ConnectState = "Problem";
			$scope.$apply();
		};

		socket.onmessage = function (msg) {
			
			
			console.log('Received traffic update.')
			
			var message = JSON.parse(msg.data);
			$scope.raw_data = angular.toJson(msg.data, true);



				// we need to use an array so AngularJS can perform sorting; it also means we need to loop to find an aircraft in the traffic set
				var validIdx = -1;
				var invalidIdx = -1;
				for (var i = 0, len = $scope.data_list.length; i < len; i++) {
					if ($scope.data_list[i].icao_int === message.Icao_addr) {
						setAircraft(message, $scope.data_list[i]);
						validIdx = i;
						break;
					}
				}
				
				for (var i = 0, len = $scope.data_list_invalid.length; i < len; i++) {
					if ($scope.data_list_invalid[i].icao_int === message.Icao_addr) {
						setAircraft(message, $scope.data_list_invalid[i]);
						invalidIdx = i;
						break;
					}
				}
				
				if ((validIdx < 0) && (message.Position_valid)) {
					var new_traffic = {};
					setAircraft(message, new_traffic);
					$scope.data_list.unshift(new_traffic); // add to start of valid array.
				}

				if ((invalidIdx < 0) && (!message.Position_valid)) {
					var new_traffic = {};
					setAircraft(message, new_traffic);
					$scope.data_list_invalid.unshift(new_traffic); // add to start of invalid array.
				}

				// Handle the negative cases of those above - where an aircraft moves from "valid" to "invalid" or vice-versa.
				if ((validIdx >= 0) && !message.Position_valid) {
					// Position is not valid any more. Remove from "valid" table.
					$scope.data_list.splice(validIdx, 1);
				}

				if ((invalidIdx >= 0) && message.Position_valid) {
					// Position is now valid. Remove from "invalid" table.
					$scope.data_list_invalid.splice(invalidIdx, 1);
				}

				$scope.$apply();

		};
	}

	var getClock = $interval(function () {
		$http.get(URL_STATUS_GET).
		then(function (response) {
			globalStatus = angular.fromJson(response.data);
				
			var tempClock = new Date(Date.parse(globalStatus.Clock));
			var clockString = tempClock.toUTCString();
			$scope.Clock = clockString;

			var tempUptimeClock = new Date(Date.parse(globalStatus.UptimeClock));
			var uptimeClockString = tempUptimeClock.toUTCString();
			$scope.UptimeClock = uptimeClockString;

			var tempLocalClock = new Date;
			$scope.LocalClock = tempLocalClock.toUTCString();
			$scope.SecondsFast = (tempClock-tempLocalClock)/1000;
			
			$scope.GPS_connected = globalStatus.GPS_connected;
						
		}, function (response) {
			// nop
		});
	}, 500, 0, false);
		




	// perform cleanup every 10 seconds
	var clearStaleTraffic = $interval(function () {
		// remove stale aircraft = anything more than 59 seconds without a position update
		var cutoff = 59;

		// Clean up "valid position" table.
		for (var i = $scope.data_list.length; i > 0; i--) {
			if ($scope.data_list[i - 1].age >= cutoff) {
				$scope.data_list.splice(i - 1, 1);
			}
		}

		// Clean up "invalid position" table.
		for (var i = $scope.data_list_invalid.length; i > 0; i--) {
			if (($scope.data_list_invalid[i - 1].age >= cutoff) || ($scope.data_list_invalid[i - 1].ageLastAlt >= cutoff)) {
				$scope.data_list_invalid.splice(i - 1, 1);
			}
		}
	}, (1000 * 10), 0, false);


	$state.get('traffic').onEnter = function () {
		// everything gets handled correctly by the controller
	};

	$state.get('traffic').onExit = function () {
		// disconnect from the socket
		if (($scope.socket !== undefined) && ($scope.socket !== null)) {
			$scope.socket.close();
			$scope.socket = null;
		}
		// stop stale traffic cleanup
		$interval.cancel(clearStaleTraffic);
	};

	// Traffic Controller tasks
	connect($scope); // connect - opens a socket and listens for messages
};