#! /usr/bin/perl -w
use strict;
use Getopt::Long;           # options
use File::Basename;
use POSIX;
use File::Copy;
use date_conv qw ( date_conv );
$Getopt::Long::ignorecase=0;
#---/----1----/----2----/----3----/----4----/----5----/----6----/----7----/----8----/----9----/----0
# ... notes
#---/----1----/----2----/----3----/----4----/----5----/----6----/----7----/----8----/----9----/----0
#:1001.25,  JG, begin development
#---/----1----/----2----/----3----/----4----/----5----/----6----/----7----/----8----/----9----/----0

if ( @ARGV != 2 ) {
  print "\n";
  print "Usage: perl snx2ant.pl <atx> <snx>\n";
  print "\n";
  print "This script builds an ant.info file from the SITE/ID and SITE/ANTENNA blocks of\n";
  print "a SINEX file. The input ANTEX file (e.g., igs08.atx) is used to verify whether\n";
  print "the antennas recorded in the SINEX/ANTENNA block have been calibrated.\n";
  print "\n";
  print "The ant.info records are written to standard output in the following format:\n";
  print "\n";
  print " ALGO  A   281.929   45.956  AOAD/M_B        NONE  1991:019:00000  1994:047:69180\n";
  print " ALGO  A   281.929   45.956  AOAD/M_T        NONE  1994:047:69180  0000:000:00000\n";
  print "\n";
  print "\n";
  print "Example: perl snx2ant.pl igs08.atx igs05-atx.SNX > ant.info 2> log\n";
  print "\n";
  print "In the Korn shell environment, the above execution will write the standard output\n";
  print "to ant.info, which can be passed to a subsequent script, comp_corr.pl. The file\n";
  print "log1 captures STDERR, which contains information about uncalibrated antenna(+radome).\n";
  print "\n";
  exit;
}

# ... define modules to be used
#     -------------------------
use date_conv qw ( date_conv );
  

# ... initialize variables
#     --------------------
my $atx = $ARGV[0];
my $snx = $ARGV[1];
my $A_ant=();
my $A_dome=();
my $A_val_f=();
my $A_val_t=();
my $ant=();
my $ant_dome=();
my $cnt=();
my $code=();
my $code_pt=();
my $ddd=();
my $dfrac=();
my $dome=();
my $flg=();
my $f_date=();
my $f_yyyyddd=();
my $f_yyyy=();
my $f_ddd=();
my $f_sod=();
my $i=();
my $lat=();
my $lon=();
my $lon_lat=();
my $pt=();
my $numAkeys=();
my $sssss=();
my $sn=();
my $t_yyyyddd=();
my $t_yyyy=();
my $t_ddd=();
my $t_sod=();
my $old_ant=();
my $old_ant_dome=();
my $old_dome=();
my $old_v_mjd=();
my $v_mjd=();
my $v_f_int=();
my $v_f_dfrac=();
my $v_t_int=();
my $v_t_dfrac=();
my $val_f=();
my $val_t=();
my $tmp1=();
my $tmp2=();
my $tmp3=();
my $yyyy=();
my $yy=();
my $yyddd=();
my @TMP=();
my @Akeys=();
my %H_cal_ant = ();
my %H_cal_ant_dome = ();
my %H_lat = ();
my %H_lon = ();
my %H_ant =();
my %HoH_ant =();
my %tmp_HoH_ant =();
my %HoH_dome =();
my %tmp_HoH_dome =();

# ... store list of calibrated antenna+radome
#     ---------------------------------------
open (ATX, "<$atx") ||
      die "\n***** ERROR: via open (r) of file $atx !\n             $!\n\n";
while (<ATX>) {
  next if ( (substr $_,60,6) ne 'TYPE /' );

  # ... read antenna and radome names
  ($ant,$dome)=split ' ', $_;
  $ant_dome=sprintf("%-15s %4s",$ant,$dome); 
  $H_cal_ant{$ant} = 1;
  print STDERR "ANT: $ant\n";
  $H_cal_ant_dome{$ant_dome} = 1;
  print STDERR "DOME: $dome\n";
  print STDERR "ANTENNA        DOME: $ant_dome\n\n";
}
close ATX;

# ... get SITE/ANTENNA block and print ant.info to stdout
#     ---------------------------------------------------
$flg=0;
open (SNX, "<$snx") ||
      die "\n***** ERROR: via open (r) of file $snx !\n             $!\n\n";
while (<SNX>) {
  print STDERR $_;
  if ( (substr $_, 0, 8) eq '+SITE/ID' ) {
    $flg=1;
  } elsif ( (substr $_, 0, 13) eq '+SITE/ANTENNA' ) {
    $flg=2;
  } elsif ( (substr $_, 0, 13) eq '-SITE/ANTENNA' || (substr $_, 0, 8) eq '-SITE/ID' ) {
    $flg=0;
  }

  # ... SITE/ID (for lat/lon)
  if ( $flg == 1 ) {

    next if ( ! m/^ / );

    # ... store lat lon for all sites
    $code = substr $_,1,4;
    $pt = substr $_,6,2;
    $code_pt=sprintf("%4s%1s",$code,$pt);

    $tmp1 = substr $_,44,3;
    $tmp2 = substr $_,48,2;
    $tmp3 = substr $_,51,4;
    if ( $tmp1 < 0 ) {
      $H_lon{$code_pt} = $tmp1 - $tmp2/60 - $tmp3/3600;
    } else {
      $H_lon{$code_pt} = $tmp1 + $tmp2/60 + $tmp3/3600;
    }
    $tmp1 = substr $_,56,3;
    $tmp2 = substr $_,60,2;
    $tmp3 = substr $_,63,4;
    if ( $tmp1 < 0 ) {
      $H_lat{$code_pt} = $tmp1 - $tmp2/60 - $tmp3/3600;
    } else {
      $H_lat{$code_pt} = $tmp1 + $tmp2/60 + $tmp3/3600;
    }
  }

  # ... SITE/ANTENNA
  if ( $flg == 2 ) {

    next if ( ! m/^ / );

    # ... get antenna info from record
    $code = substr $_,1,4;
    $pt = substr $_,6,2;
    $code_pt=sprintf("%4s%1s",$code,$pt);

    $ant_dome = substr $_,42,20;
    ($ant,$dome)=split ' ', $ant_dome;
    if ( ! defined $dome ) { 
      $dome = 'NONE';
    }
    if ( $dome eq "    " ) {                   # if, $dome is blank, replace with NONE
      print STDERR "WARNING: radome name is blank.\n";
      print STDERR "WARNING: replacing radome with NONE.\n";
      $dome="NONE";
      print STDERR "DOME: $dome\n";
    }

    # ... get "valid From" MJD
    $f_date = substr $_,16,12;
    ($yy,$ddd,$sssss)=split ':', $f_date;
    $yyddd=sprintf("%02d%03d",$yy,$ddd);
    $v_mjd = ( &date_conv( 'yyddd', $yyddd ) )[0];
    $v_mjd = sprintf("%d.%05d",$v_mjd,$sssss);

    # ... check if $ant+$dome are calibrated
    if ( defined $H_cal_ant{$ant} ) {
      $ant_dome = sprintf("%-15s %4s",$ant,$dome);
      print STDERR "$ant_dome\n";
      if ( ! defined $H_cal_ant_dome{$ant_dome} ) {
        print STDERR "changed DOME name\n";
        $dome="NONE";
      }
    } else {
      $dome="NONE";
      $ant_dome = sprintf("%-15s %4s",$ant,$dome);
      print STDERR "WARNING: UNCALIBRATED ANT+DOME $ant_dome at $code\n";
    }
    $ant_dome = sprintf("%-15s %4s",$ant,$dome);
    print STDERR "$ant_dome: $v_mjd\n";

    # ... store record
    $HoH_ant{$code_pt}{$v_mjd} = $ant;
    $HoH_dome{$code_pt}{$v_mjd} = $dome;
  }
}
close SNX;

# ... validate sequences of antenna+radome strings against "valid date"
#     --------------------------------------------------------
foreach $code_pt ( sort (keys %HoH_ant) ) {
  $code = substr $code_pt,0,4;
  $pt = substr $code_pt,4,2;
  $ant=(); $dome=(); $old_ant=(); $old_dome=();
  $cnt=0;
  print STDERR "SITE: $code $pt ($code_pt):\n";
  foreach $v_mjd ( sort (keys %{$HoH_ant{$code_pt}}) ) {
    $ant=$HoH_ant{$code_pt}{$v_mjd};
    $dome=$HoH_dome{$code_pt}{$v_mjd};
    $ant_dome=sprintf("%-15s %4s",$ant,$dome);
    print STDERR "     BEFORE  $ant_dome\n";
    if ( $cnt==0 ) {
      $old_ant_dome = $ant_dome;
      $old_v_mjd = $v_mjd;
    }
    if ( $old_ant_dome eq $ant_dome ) {
      $cnt = $cnt + 1;
    } else {
      $old_ant_dome = $ant_dome;
      $old_v_mjd = $v_mjd;
      $cnt = 1;
    }
    print STDERR "     AFTER   $ant_dome\n";
    $tmp_HoH_ant{$code_pt}{$old_v_mjd}=$ant;
    $tmp_HoH_dome{$code_pt}{$old_v_mjd}=$dome;
  }
  print STDERR "\n";
}
%HoH_ant = %tmp_HoH_ant;
%HoH_dome = %tmp_HoH_dome;

# ...  put together the records and write ant.info
#     --------------------------------------------
$cnt=0;
print "#CODE PT  LON_____ LAT_____  ANTENNA________ DOME  FROM__________ TO_____________\n";
foreach $code_pt ( sort (keys %HoH_ant) ) {
  $i=-1;
  $code = substr $code_pt,0,4;
  $pt = substr $code_pt,4,2;
  %H_ant = %{$HoH_ant{$code_pt}};
  @Akeys=sort(keys(%H_ant));
  $numAkeys=keys %H_ant;
  foreach $A_val_f ( sort(keys(%H_ant)) ) {
    $i++;
    if ($i == 0) {
      $val_f = -99999;
    } else {
      $val_f = $A_val_f;
    }
    if ($i < $numAkeys-1) {
      $val_t = $Akeys[$i+1];
    } else {
      $val_t = 99999;
    }

    # ... extract the valid date intervals for antenna 
    if ( defined $A_val_f && defined $H_lon{$code_pt} ) {
      $cnt++;

      # ... antenna information
      $A_ant = $HoH_ant{$code_pt}{$A_val_f};
      $A_dome = $HoH_dome{$code_pt}{$A_val_f};

      # ... format the "valid from" date
      if ( $val_f == -99999 ) {
        $f_yyyy=0000;
        $f_ddd=000;
        $f_sod=00000;
      } else {
        ($v_f_int,$v_f_dfrac)=split '\.', $val_f;
        print STDERR "valid from: $val_f\n";
        print STDERR "integer part: $v_f_int\n";
        print STDERR "fractional part: $v_f_dfrac\n\n";
        $f_yyyy=( &date_conv( 'mjd', $v_f_int ) )[1];
        $f_ddd=( &date_conv( 'mjd', $v_f_int ) )[2];
        $f_sod = sprintf("%5d",$v_f_dfrac);
      }

      # ... format the "valid to" date
      if ( $val_t == 99999 ) {
        $t_yyyy=0000;
        $t_ddd=000;
        $t_sod=00000;
      } else {
        ($v_t_int,$v_t_dfrac)=split '\.', $val_t;
        print STDERR "valid from: $val_t\n";
        print STDERR "integer part: $v_t_int\n";
        print STDERR "fractional part: $v_t_dfrac\n\n";
        $t_yyyy=( &date_conv( 'mjd', $v_t_int ) )[1];
        $t_ddd=( &date_conv( 'mjd', $v_t_int ) )[2];
        $t_sod = sprintf("%5d",$v_t_dfrac);
      }

      printf(" %4s %2s  %8.3f %8.3f  %-15s %-4s  %04d:%03d:%05d  %04d:%03d:%05d\n",uc $code,uc $pt,$H_lon{$code_pt},$H_lat{$code_pt},$A_ant,$A_dome,$f_yyyy,$f_ddd,$f_sod,$t_yyyy,$t_ddd,$t_sod);
    }
  }
}
