#!/usr/bin/perl

use strict;
use Math::Trig;

my $r = 6371000.785;
my $maptype = "satellite";
my $weight = 3;
my $zoom = 14;
my $size = "600x600";
my $sensor = "false";
my $url = "https://maps.googleapis.com/maps/api/staticmap";
my $known_flarms = {
	"4B0CF5" => "Robin HB-EXP",
	"4B1307" => "Bravo HB-HFJ"
};
my $step_time = 3;
my $timeout = 45;

my ($from, $until, $before, $now) = (undef, undef, undef, undef);
my ($own_lat, $own_long);
my $flarm = undef;
my $seen;

sub fstr {
  my ($value,$precision) = @_;
  $precision ||= 5;
  my $s = sprintf("%.${precision}f", $value);
  $s =~ s/\.?0*$//;
  return $s;
}


sub parse_GPGGA {
	my ($line) = @_;
	my ($msg,$time,$lat,$northsouth,$long,$eastwest,$quality,$satelites,$dhop,$alt) = split(/,/, $line);
	my ($g_lat, $g_long) = nmeaToGoogle($lat,$northsouth,$long,$eastwest);
        print "nmea: " . $lat . $northsouth . "," . $long . $eastwest . "\n";
        print "google: " . $g_lat . "," . $g_long . "\n";
	$now = $time;
	$own_lat = $g_lat;
	$own_long = $g_long;
}

sub parse_PFLAA {
	my ($line) = @_;
	my ($msg,$alarm,$rel_north,$rel_east,$rel_vert,$id_type,$id,$track,$turnrate,$groundspeed,$climb,$type) = split(/,/, $line);
	return unless (defined($now));
	return if (defined($from) && $now < $from);
	return if (defined($until) && $now > $until);
	return if (defined($flarm) && $id ne $flarm);
	return unless (defined($own_lat));
	return unless (defined($own_long));
	return unless ($groundspeed > 10 || $rel_vert > 20);
	
	print $now . ": " . $line . " " . ($own_lat+distToLat($rel_north)) . "," . ($own_long+distToLong($rel_east)) . "\n";
	store($now, $id, $own_lat + distToLat($rel_north), $own_long + distToLong($rel_east));
}

sub store {
	my ($time, $id, $g_lat, $g_long) = @_;
	
	if (!exists($seen->{$id})) {
		$seen->{$id} = ();
	}
	if (!defined($before) || $now  >= $before+$step_time) {
		$before = $now;
		push(@{$seen->{$id}}, [$time, $g_lat, $g_long]);
	}	
}

sub distToLat {
	my ($dist) = @_;
	return 180*$dist/($r*pi);
}

sub distToLong {
	my ($dist) = @_;
	return 180*$dist/(cos($own_lat*pi/180)*$r*pi);
}

sub nmeaToGoogle {
	my ($lat,$northsouth,$long,$eastwest) = @_;
	my $lat_sign = ($northsouth =~ /N/) ? 1 : -1;
	$lat =~ /^(\d{2})(\d{2})\.(\d{5})$/;
	my $g_lat = ($1 + ($2 + $3*1e-5)/60) * $lat_sign;
	
	my $long_sign = ($eastwest =~ /E/) ? 1 : -1;
	$long =~ /^(\d{3})(\d{2})\.(\d{5})$/;
	my $g_long = ($1 + ($2 + $3*1e-5)/60) * $long_sign;
	return ($g_lat, $g_long);	
}

while (my $line = <>) {
	chomp($line);
	($line =~ /^\$GPGGA/) && parse_GPGGA($line);
	($line =~ /^\$PFLAA/) && parse_PFLAA($line);
}

foreach my $flarm_id (keys(%{$seen})) {
	my $plane = exists($known_flarms->{$flarm_id}) ? $known_flarms->{$flarm_id} : "???";
	print "==== Flarm-ID: $flarm_id ($plane) ====\n";

	my $last_record;
	foreach my $record (@{$seen->{$flarm_id}}) {
 		my ($time, $g_lat, $g_long) = @{$record};
 		
 		if (!defined($last_record) || $time >= $last_record + $timeout) {
 			print "\n";
 			print $url 
	  			. "?maptype=" . $maptype 
	  			. "&zoom=" . $zoom
	  			. "&size=" . $size
	  			. "&sensor=" . $sensor
	  			. "&center=" . fstr($own_lat, 5) . "," . fstr($own_long, 5)
	  			. "&path=color:red|weight:3";
 		}
 		$last_record = $time;
 		print "|".fstr($g_lat,5) . "," . fstr($g_long, 5);
	}
	$last_record = undef;
	print "\n\n";
}


