#!/usr/bin/perl -w
# NAME: test-findap.pl
# AIM: Just a TEST module
use strict;
use warnings;
use POSIX qw(ceil floor);
use File::Basename;  # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] )
use Time::HiRes qw( gettimeofday tv_interval );
use Cwd;
my $os = $^O;
my $perl_dir = '/home/geoff/bin';
my $PATH_SEP = '/';
my $temp_dir = '/tmp';
if ($os =~ /win/i) {
    $perl_dir = 'C:\GTools\perl';
    $temp_dir = $perl_dir;
    $PATH_SEP = "\\";
}
unshift(@INC, $perl_dir);
require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl' Check paths in \@INC...\n";
require 'fg_wsg84.pl' or die "Unable to load fg_wsg84.pl ...\n";
# log file stuff
our ($LF);
my $pgmname = $0;
if ($pgmname =~ /(\\|\/)/) {
    my @tmpsp = split(/(\\|\/)/,$pgmname);
    $pgmname = $tmpsp[-1];
}
my $outfile = $temp_dir.$PATH_SEP."temp.$pgmname.txt";
open_log($outfile);

# user variables
my $VERS = "0.0.2 2014-01-13";
my $load_log = 0;
my $in_file = '';
my $verbosity = 1;
my $out_file = '';

my $FGROOT = 'X:/fgdata';
my $APTFILE = "$FGROOT/Airports/apt.dat.gz";  # le fichier contenant les aéroports
my $KM2FEET = 3280.84;
my $done_all = 0;

my @all_airports = ();

# ### DEBUG ###
my $debug_on = 0;
my $def_file = 'def_file';

### program variables
my @warnings = ();
my $cwd = cwd();

sub VERB1() { return $verbosity >= 1; }
sub VERB2() { return $verbosity >= 2; }
sub VERB5() { return $verbosity >= 5; }
sub VERB9() { return $verbosity >= 9; }

sub show_warnings($) {
    my ($val) = @_;
    if (@warnings) {
        prt( "\nGot ".scalar @warnings." WARNINGS...\n" );
        foreach my $itm (@warnings) {
           prt("$itm\n");
        }
        prt("\n");
    } else {
        prt( "\nNo warnings issued.\n\n" ) if (VERB9());
    }
}

sub pgm_exit($$) {
    my ($val,$msg) = @_;
    if (length($msg)) {
        $msg .= "\n" if (!($msg =~ /\n$/));
        prt($msg);
    }
    show_warnings($val);
    close_log($outfile,$load_log);
    exit($val);
}


sub prtw($) {
   my ($tx) = shift;
   $tx =~ s/\n$//;
   prt("$tx\n");
   push(@warnings,$tx);
}

sub round($) {
    my $i = shift;
    my $m = (shift or 1);
    $i /= $m;
    $i = $i - &floor($i) >= 0.5 ? &ceil($i) : &floor($i);
    $i *= $m;
    return $i;
}

sub process_in_file($) {
    my ($inf) = @_;
    if (! open INF, "<$inf") {
        pgm_exit(1,"ERROR: Unable to open file [$inf]\n"); 
    }
    my @lines = <INF>;
    close INF;
    my $lncnt = scalar @lines;
    prt("Processing $lncnt lines, from [$inf]...\n");
    my ($line,$inc,$lnn);
    $lnn = 0;
    foreach $line (@lines) {
        chomp $line;
        $lnn++;
        if ($line =~ /\s*#\s*include\s+(.+)$/) {
            $inc = $1;
            prt("$lnn: $inc\n");
        }
    }
}

# Airport Line. eg '1 5355 1 0 KABQ Albuquerque Intl Sunport'
# 0 1    - this as an airport header line. 16 is a seaplane/floatplane base, 17 a heliport.
# 1 5355 - Airport elevation (in feet above MSL).  
# 2 1    - Airport has a control tower (1=yes, 0=no).
# 3 0   - Display X-Plane’s default airport buildings (1=yes, 0=no).
# 4 KABQ   - Identifying code for the airport (the ICAO code, if one exists).
# 5+Albuquerque Intl Sunport - Airport name.

sub load_airports() {
    my ($ver,$line,$type,$autre_bout);
    my $t1 = [gettimeofday];
    if ( -e $APTFILE ) {
        open (APT, "gzip -d -c $APTFILE|") or die "je ne peux pas ouvrir $APTFILE\n" ;
        while (<APT>) {
            if (/^(\d+)\s+Version\s+/) {
                $ver = $1;
                last;
            }
        }
    } else {
        prt("fichier $APTFILE introuvable\n");
        prt("veuillez vérifier \$FGROOT\n");
        prt("ou utilisez l'option --fg-root=répertoire\n");
        prt("ou encore modifiez le script ver ligne 80\n");
        exit 1;
    }
    if ($ver) {
        prt("Loading file $APTFILE, version $ver... moment...\n") if (VERB1());
    } else {
        close APT;
        prt("Failed to find version in $APTFILE!\n");
        exit 1;
    }
    my $aptcnt = 0;
    my $rwycnt = 0;
    my $comcnt = 0;
    while ($line = <APT>) {
        chomp $line;
        next if ($line =~ /^\s*$/);
        $line = trim_all($line);
        my @header = split(/\s+/, $line);
        $type = $header[0];
        last if ($type == 99);
        if ($type == 1) {
            # 0 1       2   3   4    5+
            # # elev_ft twr bld icao name
            push(@all_airports, \@header);
            $aptcnt++;
        } elsif ($type == 10) {
            if ($header[3] ne 'xxx') {
                # 0   1          2          3   4       5    6         7         8   9       0 1 2 3    4 5
                # 10  36.962213  127.031071 14x 131.52  8208 1595.0620 0000.0000 150 321321  1 0 3 0.25 0 0300.0300
                # 10  36.969145  127.020106 xxx 221.51   329 0.0       0.0        75 161161  1 0 0 0.25 0 
                $header[3] =~ /(..)(.)/;
                $autre_bout = ($1 > 18)? $1 - 18 : $1 + 18;
                $autre_bout = '0'.$autre_bout if ($autre_bout < 10);
                $autre_bout .= 'L' if ($2 eq 'R');
                $autre_bout .= 'R' if ($2 eq 'L');
                $autre_bout .= 'C' if ($2 eq 'C');
                if ($2 eq 'x') {
                    $header[3]   = $1.' ';
                    $autre_bout .= ' ';
                }
                $header[3] = $header[3].'/'.$autre_bout;
                push(@all_airports,\@header);
                $rwycnt++;
            }
        } elsif ($type == 100) {
            # See version 1000 specs
            # 0   1     2 3 4    5 6 7 8  9           10           11   12   13 14 15 16 17 18          19           20   21   22 23 24 25
            # 100 29.87 3 0 0.00 1 2 1 16 43.91080605 004.90321905 0.00 0.00 2  0  0  0  34 43.90662331 004.90428974 0.00 0.00 2  0  0  0
            my $rwy = $header[8];
            $autre_bout = $header[17];
            $rwy = '0'.$rwy if (length($rwy) < 2);
            $autre_bout = '0'.$autre_bout if (length($autre_bout) < 2);
            my $rwynm = $rwy.'/'.$autre_bout;
            my $rlat1 = $header[9];  # $of_lat1
            my $rlon1 = $header[10]; # $of_lon1
            my $rlat2 = $header[18]; # $of_lat2
            my $rlon2 = $header[19]; # $of_lon2
            my $rlat = ($rlat1 + $rlat2) / 2;
            my $rlon = ($rlon1 + $rlon2) / 2;
            my ($dist,$az1,$az2,$res,$s);
            #if ($use_sg_math) {
                $res = fg_geo_inverse_wgs_84($rlat1, $rlon1, $rlat2, $rlon2, \$az1, \$az2, \$s);
                $dist = int(($s / 1000) * $KM2FEET );    # runway length, in feet
            #} else {
            #    $dist = distance_( [$rlat1, $rlon1, $rlat2, $rlon2] );
            #    $dist = int( $dist * $KM2FEET );    # runway length, in feet
            #    $az1  = llll2dir_( [$rlat1, $rlon1, $rlat2, $rlon2] );
            #}
            $az1 = round($az1);
            my @a = ();
            #push(@a,[10, $rlat, $rlon, $rwynm, $az1, $dist, 0.0, 0.0, 75, 161161, 1, 0, 0, 0.25, 0, 0]); 
            @a = (10, $rlat, $rlon, $rwynm, $az1, $dist, 0.0, 0.0, 75, 161161, 1, 0, 0, 0.25, 0, 0);
            push(@all_airports, \@a);
            prt("10 $rlat $rlon $rwynm $az1 $dist\n") if (VERB9());
            $rwycnt++;
            ### pgm_exit(1,"TEMP") if ($cnt > 10);
        } elsif (($type >= 50)&&($type <= 59)) {
            # on garde aussi les fréquences COM...
            push(@all_airports,\@header);
            $comcnt++;
        }
    }
    $done_all = scalar @all_airports;
    $type = $aptcnt + $rwycnt + $comcnt;
    my $elap = secs_HHMMSS( tv_interval( $t1, [gettimeofday] ) );
    prt("Loaded $aptcnt airports, $rwycnt runways, $comcnt coms. total $done_all ($type)...in $elap...\n") if (VERB1());
    $done_all = 1;
}

my %airport_icao = ();

sub get_apt_pos($) {
    my $ara = shift;
    my $max = scalar @{$ara};
    my ($i,$typ,$ra);
    my $lat = 0;
    my $lon = 0;
    my $cnt = 0;
    for ($i = 0; $i < $max; $i++) {
        $ra = ${$ara}[$i];
        $typ = ${$ra}[0];
        if ($typ == 10) {
            $lat += ${$ra}[1];
            $lon += ${$ra}[2];
            $cnt++;
        }
    }
    if ($cnt > 0) {
        $lat /= $cnt;
        $lon /= $cnt;
    }
    return ($lat,$lon);
}

sub find_leg_ap($$$$) {
    my ($leg,$pos,$rap,$fudge) = @_;
    my ($lat1,$lon1,$lat2,$lon2,$lat,$lon);
    my ($i,$max,$ra,$typ,$icao,$ind,$fnd);
    $lat1 = ${$leg}[0];
    $lon1 = ${$leg}[1];
    $lat2 = ${$leg}[2];
    $lon2 = ${$leg}[3];
    if ($lat1 > $lat2) {
        $lat = $lat1;
        $lat1 = $lat2;
        $lat2 = $lat;
    }
    if ($lon1 > $lon2) {
        $lon = $lon1;
        $lon1 = $lon2;
        $lon2 = $lon;
    }
    $lat1 -= $fudge;
    $lat1 += 180 if ($lat1 < -180);
    $lat1 -= 180 if ($lat1 > 180);
    $lat2 += $fudge;
    $lat2 -= 180 if ($lat2 > 180);
    $lat2 += 180 if ($lat2 < -180);
    $lon1 -= $fudge;
    $lon1 += 360 if ($lon1 < -180);
    $lon1 -= 360 if ($lon1 > 180);
    $lon2 += $fudge;
    $lon2 += 360 if ($lon2 < -180);
    $lon2 -= 360 if ($lon2 > 180);
    #$lat = ($lat1 + $lat2) / 2;
    #$lon = ($lon1 + $lon2) / 2;
    $max = scalar @all_airports;  # load ALL airports
    my @apts = ();
    for ($i = 0; $ i < $max; $i++) {
        $ra = $all_airports[$i];
        $typ = ${$ra}[0];
        if ($typ == 1) {
            # 0 1       2   3   4    5+
            # # elev_ft twr bld icao name
            my @apt = ();
            $fnd = 0;
            $ind = $i;
            $icao = ${$ra}[4]; # set icao
            next if (defined $airport_icao{$icao});
            push(@apt,$ra);
            $i++;
            for (; $i < $max; $i++) {
                $ra = $all_airports[$i];
                $typ = ${$ra}[0];
                if ($typ == 1) {
                    $i--;
                    last;
                }
                push(@apt,$ra);
                if ($typ == 10) {
                    #         0   1      2      3       4     5
                    #push(@a,[10, $rlat, $rlon, $rwynm, $az1, $dist, 0.0, 0.0, 75, 161161, 1, 0, 0, 0.25, 0, 0]); 
                    $lat = ${$ra}[1];
                    $lon = ${$ra}[2];
                    if (($lat >= $lat1)&&
                        ($lat <= $lat2)&&
                        ($lon >= $lon1)&&
                        ($lon <= $lon2)) {
                        $fnd++;
                    }
                }
            }
            if ($fnd > 0) {
                $typ = scalar @apt;
                prt("Adding ref to $typ apt components ($fnd)\n");
                push(@apts,\@apt);
            }
        }
    }
    $max = scalar @apts;
    prt("Found $max airports in box $lat1,$lon1,$lat2,$lon2, fudge=$fudge  ");
    if ($max > 0) {
        $ind = 0;
        if ($max > 1) {
            # TODO: Select the ONE closest the TRACK, or ON some other criteria
            # maybe closest to this point
            $lat = ${$pos}[0];
            $lon = ${$pos}[1];
            my ($az1,$az2,$s,$dist);
            for ($i = 0; $i < $max; $i++) {
                $ra = $apts[$i];
                my ($alat,$alon) = get_apt_pos($ra);
                my $res = fg_geo_inverse_wgs_84($lat, $lon, $alat, $alon, \$az1, \$az2, \$s);
                if ($i == 0) {
                    $dist = $s;
                    $ind = $i;
                } elsif ($s < $dist) {
                    $dist = $s;
                    $ind = $i;
                }
            }
        }
        # push(@{$rap},$apts[0]);
        ${$rap} = $apts[$ind];
        prt($ind);
    }
    prt("\n");
    return $max;
}

sub test_findap() {
    load_airports();
    ###$load_log = 1;
    # leg: 51.37083300,006.39500000,50.70111100,005.54916700 pos: 50.932615943539,5.83791943554026 s 34 nm on 219
    my $leg = [51.370833,6.395,50.701111,5.549167];
    my $pos = [50.932615943539,5.83791943554026];
    my $fudge = -0.5;
    my $az1 = 0;
    my ($ap);
    while (!find_leg_ap($leg,$pos,\$ap,$fudge)) {
        $fudge += 0.1;
    }
    my $max = scalar @{$ap};
    my ($i,$ra,$ra2);
    for ($i = 0; $i < $max; $i++) {
        $ra = ${$ap}[$i];
        prt(join(" ",@{$ra})."\n");
        ##$ra2 = ${$ra}[0];
        ##prt(join(" ",@{$ra2})."\n");
    }
}

#########################################
### MAIN ###
##parse_args(@ARGV);
##process_in_file($in_file);
test_findap();
pgm_exit(0,"");
########################################

sub need_arg {
    my ($arg,@av) = @_;
    pgm_exit(1,"ERROR: [$arg] must have a following argument!\n") if (!@av);
}

sub parse_args {
    my (@av) = @_;
    my ($arg,$sarg);
    my $verb = VERB2();
    while (@av) {
        $arg = $av[0];
        if ($arg =~ /^-/) {
            $sarg = substr($arg,1);
            $sarg = substr($sarg,1) while ($sarg =~ /^-/);
            if (($sarg =~ /^h/i)||($sarg eq '?')) {
                give_help();
                pgm_exit(0,"Help exit(0)");
            } elsif ($sarg =~ /^v/) {
                if ($sarg =~ /^v.*(\d+)$/) {
                    $verbosity = $1;
                } else {
                    while ($sarg =~ /^v/) {
                        $verbosity++;
                        $sarg = substr($sarg,1);
                    }
                }
                $verb = VERB2();
                prt("Verbosity = $verbosity\n") if ($verb);
            } elsif ($sarg =~ /^l/) {
                if ($sarg =~ /^ll/) {
                    $load_log = 2;
                } else {
                    $load_log = 1;
                }
                prt("Set to load log at end. ($load_log)\n") if ($verb);
            } elsif ($sarg =~ /^o/) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $out_file = $sarg;
                prt("Set out file to [$out_file].\n") if ($verb);
            } else {
                pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n");
            }
        } else {
            $in_file = $arg;
            prt("Set input to [$in_file]\n") if ($verb);
        }
        shift @av;
    }

    if ($debug_on) {
        prtw("WARNING: DEBUG is ON!\n");
        if (length($in_file) ==  0) {
            $in_file = $def_file;
            prt("Set DEFAULT input to [$in_file]\n");
        }
    }
    if (length($in_file) ==  0) {
        pgm_exit(1,"ERROR: No input files found in command!\n");
    }
    if (! -f $in_file) {
        pgm_exit(1,"ERROR: Unable to find in file [$in_file]! Check name, location...\n");
    }
}

sub give_help {
    prt("$pgmname: version $VERS\n");
    prt("Usage: $pgmname [options] in-file\n");
    prt("Options:\n");
    prt(" --help  (-h or -?) = This help, and exit 0.\n");
    prt(" --verb[n]     (-v) = Bump [or set] verbosity. def=$verbosity\n");
    prt(" --load        (-l) = Load LOG at end. ($outfile)\n");
    prt(" --out <file>  (-o) = Write output to this file.\n");
}

# eof - template.pl
