#!/usr/bin/perl -w
# NAME: geo_metar02.pl
# AIM: Get the METAR for a particular ICAO
use strict;
use warnings;
use File::Basename;  # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] )
use Cwd;
use Socket;
use LWP::Simple;
use Geo::METAR;
use Data::Dumper;

my $perl_dir = 'C:\GTools\perl';
unshift(@INC, $perl_dir);
require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl ...\n";
# log file stuff
our ($LF);
my $pgmname = $0;
if ($pgmname =~ /(\\|\/)/) {
    my @tmpsp = split(/(\\|\/)/,$pgmname);
    $pgmname = $tmpsp[-1];
}
my $outfile = $perl_dir."\\temp.$pgmname.txt";
open_log($outfile);

# user variables
my $vers = "0.0.1 2011-07-22";
my $load_log = 1;
my $in_file = '';
my $TAFBASE  = 'http://weather.noaa.gov/pub/data/forecasts/taf/stations/';
my $METARBASE = 'http://weather.noaa.gov/pub/data/observations/metar/stations/';
# 1 hPa = 0.0 295 300 586 467 inHg (0.02953)
my $HP2INCHES = 0.0295300586467;
# 1 Knot = 1.15077845 Miles Per Hour.
my $KNOT2MPH = 1.15077845;
# 1 Miles Per Hour = 0.86897699264 Knot.
my $MPH2KNOT = 0.86897699264;

my $debug_on = 1;
my $def_file = 'YSDU';

my @geo_metar = qw( pressure visibility slp DATE HOURLY_TEMP_C date_time 
    modifier VISIBILITY DEW_F windvar TEMP_F debug HOURLY_DEW_C SITE 
    SKY WIND_VAR_1 WIND_DIR_ENG WIND_GUST_KTS REMARKS RUNWAY HOURLY_PRECIP
    runway type WIND_VAR_2 WIND_VAR WIND_DIR_ABB HOURLY_DEW_F WIND_MPH
    wind WIND_KTS unknown weather windtype remarks WEATHER_LOG TEMP_C
    WIND_GUST_MPH DEW_C WIND_DIR_DEG sky HOURLY_TEMP_F SLP alt TIME
    tokens MOD TYPE WEATHER METAR site temp_dew VERSION UNKNOWN ALT );
my %geo_arrays = (
    'SKY' => 1,
    'RUNWAY' => 1,
    'unknown' => 1,
    'weather' => 1,
    'remarks' => 1,
    'WEATHER_LOG' => 1,
    'sky' => 1,
    'tokens' => 1,
    'WEATHER' => 1,
    'UNKNOWN' => 1 );

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

my @ICAO_LIST = ();

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" );
    }
}

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);
}

# 9.C = 5.F - 160
sub celcius_to_fahrenheight($) {
    my ($dc) = shift;
    my $df = (($dc * 9) + 160) / 5;
    return $df;
}
sub fahrenheight_to_celcius($) {
    my ($df) = @_;
    my $dc = (($df - 32) * 100) / 180;
    return $dc;
}

sub trim_metar_txt($) {
    my $met = shift;
	$met =~ s/\n/ /gm;
	$met =~ s/\r/ /gm;
	$met =~ s/\t/ /gm;
	$met = trim_all($met);
    return $met;
}

sub fetch_url {	# see gettaf01.pl
	my ($url) = shift;
	prt( "Fetching: $url\n" );
	my $txt = get($url);
    my $met = '';
	if ($txt && length($txt)) {
        $met = trim_all($txt);
        if (length($met)) {
    		prt( "$met\n" );
        } else {
    		prt( "FAILED to get URL $url ...\n" );
        }
	} else {
		prt( "FAILED to get URL $url ...\n" );
	}
    return $met;
}

sub process_in_list() {
    my ($inf,$url,$met,$file,@arr,$key,$val);
    my ($min,$len,$cnt,$lckey,$uckey);
    my ($line,$msg,$tmp);
    my $m = new Geo::METAR;
    my %dupes = ();
    my %list = ();
    foreach $inf (@ICAO_LIST) {
        $file = $perl_dir."\\temp.$inf.TXT";
        $url = $METARBASE.$inf.".TXT";
        $met = '';
        if (-f $file) {
            if (open FIL, "<$file") {
                @arr = <FIL>;
                close FIL;
                $met = join(" ",@arr);
                $met = trim_all($met);
                if (length($met)) {
                    prt("Loaded metar from [$file]\n");
                }
            }
        } else {
            $met = fetch_url($url);
            if (length($met)) {
                $met = trim_metar_txt($met);
                if (length($met)) {
                    write2file($met,$file);
                    prt("Metar written to [$file]\n");
                }
            }
        }
        if (length($met)) {
        	prt( "METAR: [$met]\n" );
            $m->metar($met);
            #prt( $m->dump );
            #prt(Dumper($m));
            @arr = sort keys(%{$m});
            $line = '';
            $msg = 'Keys: ';
            #prt("Keys: ".join(" ",@arr)."\n");
            foreach $key (@arr) {
                $line .= ' ' if (length($line));
                $line .= $key;
                if (length($line) > 80) {
                    $msg .= "$line\n";
                    $line = '';
                }
            }
            $msg .= $line if (length($line));
            prt("$msg\n");
            $min = 0;
            $cnt = 0;
            foreach $key (sort @geo_metar) {
                next if ($key eq 'VERSION');
                $uckey = uc($key);
                $lckey = lc($key);
                if (defined ${$m}{$key}) {
                    $val = ${$m}{$key};
                    if (defined $geo_arrays{$key}) {
                        # we have an array ref
                    } else {
                        $val = trim_all($val);
                        if (length($val)) {
                            if (!defined $dupes{$uckey} && !defined $dupes{$lckey}) {
                                $len = length($key);
                                $min = $len if ($len > $min);
                                $dupes{$uckey} = 1;
                                $dupes{$lckey} = 1;
                                $list{$key} = $val;
                                $cnt++;
                            }
                        }
                    }
                }
            }
            prt("\nGot $cnt different items...\n");
            foreach $key (sort keys %list) {
               $val = ${$m}{$key};
               $key .= ' ' while (length($key) < $min);
               if ($key =~ /^pressure/) {
                   $tmp = $val * $HP2INCHES;
                   $tmp = int(($tmp * 100) + 0.5) / 100;
                   prt("$key = $val hPa $tmp inHg\n");
               } elsif ($key =~ /^TEMP_C\s*/) {
                   $tmp = celcius_to_fahrenheight($val);
                   prt("$key = $val C $tmp F\n");
               } elsif ($key =~ /^TEMP_F\s*/) {
                   $tmp = fahrenheight_to_celcius($val);
                   prt("$key = $val F $tmp C\n");
               } elsif ($key =~ /^WIND_KTS\b/) {
                   $tmp = $val * $KNOT2MPH;
                   $tmp = int(($tmp * 10) + 0.5) / 10;
                   prt("$key = $val kt $tmp mph\n");
               } elsif ($key =~ /^WIND_MPH\b/) {
                   $tmp = $val * $MPH2KNOT;
                   $tmp = int(($tmp * 10) + 0.5) / 10;
                   prt("$key = $val mph $tmp kt\n");
               } else {
                   prt("$key = $val\n");
               }
            }
        }
    }
}

#########################################
### MAIN ###
parse_args(@ARGV);
process_in_list();
pgm_exit(0,"");
########################################
sub give_help {
    prt("$pgmname: version $vers\n");
    prt("Usage: $pgmname [options] ICAO [ICAO2 [ICAO3]]\n");
    prt("Options:\n");
    prt(" --help (-h or -?) = This help, and exit 0.\n");
}
sub need_arg {
    my ($arg,@av) = @_;
    pgm_exit(1,"ERROR: [$arg] must have following argument!\n") if (!@av);
}

sub parse_args {
    my (@av) = @_;
    my ($arg,$sarg);
    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)");
            } else {
                pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n");
            }
        } else {
            $in_file = uc($arg);
            push(@ICAO_LIST,$in_file);
            prt("Set input to [$in_file]\n");
        }
        shift @av;
    }

    if ((length($in_file) ==  0) && $debug_on) {
        $in_file = uc($def_file);
        push(@ICAO_LIST,$in_file);
        prt("Set DEFAULT input to [$in_file]\n");
    }
    if (length($in_file) ==  0) {
        pgm_exit(1,"ERROR: No ICAO found in command!\n");
    }
}

# eof - geo_metar.pl
