#!/opt/perl/bin/perl
use strict;
use Getopt::Long;
use Carp;
use File::Basename;
use GOA::StaRcvr;
use GOA::StaSvec;
use GOA::StaPos;
use GOA::StaId;
use GPS::DATES;
#use GPS::Coords;
use GOA::StaLoc;
use GPS::Defaults;
use Cwd;
my $progname=basename($0);
my $usage =<<EOT;
   $progname [-dir outdir] [-nopos]
                           [-nosvec]
                           [-norcvr] 
                           [-nocoords]
                           [-id ] 
                           [-help]
  Make metadata info. 
  Options :
       dir : dir for output 
       no[pos,svec,rcvr,coords,id] : don't write that tmp file
  Input: stdin
  
  Output: (default)
      outdir/sta_pos.tmp   
      outdir/sta_svec.tmp   
      outdir/sta_id.tmp   
      outdir/sta_rcvr.tmp   
      outdir/coords.tmp   
  
EOT
my $here = cwd;
my $outdir =  cwd();
my %par = get_defaults();
my  ($do_pos,$do_id,$do_svec,$do_rcvr,$do_coords)=(1)x5;
my $help = '';
GetOptions(  'dir:s'    => \$outdir,
             'nopos'     => sub { $do_pos=0},
             'noid'      => sub { $do_id =0},
             'nosvec'    => sub { $do_svec=0},
             'norcvr'    => sub { $do_rcvr=0},
             'nocoords'  => sub { $do_coords=0},
	      ) || croak "error in options";
          
if ( $help ) { print $usage; exit; } 

#print "$do_pos $do_id $do_svec $do_rcvr $do_coords\n"; 
my $today = get_date("today","cal");

my $pos  = GOA::StaPos->new( );
my $svec = GOA::StaSvec->new( );
my $rcvr = GOA::StaRcvr->new(  );
my $id   = GOA::StaId->new( );
my $loc  = GOA::StaLoc->new( );
#our $coords = GPS::DataTable->new( file => '/home/gnet/processing/config/pbo/pbo-current.tmp', 
#our $coords = GPS::DataTable->new( data => $coord_data, 
#                                   fields_in => 'site,lon,lat,net,type',
#                                   fmt  => "a4,2x,f9.4,2x,f9.4,2x,a5,x1,a10"
#                                 );
#my $coords = GPS::Coords->new( data => [] );
#$coords->print();
our %kmap = (
     '4 CH ID'               => 'sta', # AC25 
     'Name'                  => 'name', #16 Ch id: King_Cove_AK2005
     'New Station Name'      => 'name',
     'Date'                  => 'date', # 01/01/2005
     'Date Established'      => 'site_sdate',
     'Ant Install Date'      => 'ant_sdate', #: 05-SEP-2005
     'Ant Model'             => 'ant_type',
     'Ant Height'            => 'ant_height',
     'Ant X'		         => 'loc_x',
     'Ant Y'		         => 'loc_y',
     'Ant Z'		         => 'loc_z',
     'Ant S/N'               => 'ant_sn', 
     'Radome S/N'            => 'ant_radome_sn',
     'Radome'                => 'ant_radome', 
     'New Antenna Height'    => 'ant_height',
     'New Antenna Date'      => 'ant_sdate', 
     'New Antenna Type'      => 'ant_type', 
     'New Antenna S/N'       => 'ant_sn',
     'New Radome'            => 'ant_radome',
     'New Radome Type'       => 'ant_radome',
     'New Radome S/N'        => 'ant_radome_sn', 
     'Rx S/N'                => 'rcvr_sn', 
     'Rx Model'              => 'rcvr_type', 
     'Receiver Removal Date' => 'rcvr_edate',
     'Rx Install Date'       => 'rcvr_sdate',
     'New Receiver Type'     => 'rcvr_type',
     'New Receiver Date'     => 'rcvr_sdate', #: 05-SEP-2005.
     'New Receiver S/N'      => 'rcvr_sn',  
     'New Receiver UVID'     => 'rcvr_unavco_id', 
     'New Receiver Firmware' => 'rcvr_firmware', #: 1.1-2.
     'Firmware'              => 'rcvr_firmware',
     'Elev Cutoff'           => 'rcvr_elev_cut_off',
     'IERS Domes'            => 'loc_iers_domes',
     'Latitude'              => 'loc_lat', 
     'Longitude'             => 'loc_lon',
     'Elevation'             => 'loc_elev',
     'Site Network'          => 'loc_site_net',
     'Network'               => 'loc_net',
     'Orig Network'          => 'loc_orig_net',
     'Status'                => 'loc_status',
     'City'                  => 'loc_city',
     'State'                 => 'loc_state',
     'Country'               => 'loc_country',
     'Tectonic Plate'        => 'loc_tec_plate',
     'comment'               => 'comment',
     'rinex comment'         => 'loc_rnx_comment'
);
#print "@$ant";

my %info;
my %p;
my $flag=0;

while ( <> ) {
   chomp;
   s/^\s+//;
   s/\s+$//;
   next unless length;
   $flag = (1 xor $flag)  if /^\*+$/;
   if ( $flag ) {	  
    s/^\*+//g; 
    next unless length;
    my ($key,$value) = split(/:/,$_);
    #($key = lc $key) =~ s/( |\/)/_/g;
    $key = trim($key);
    ($value = trim($value))  =~ s/\.+$//g;
    @p{$kmap{$key}}=trim($value) if exists $kmap{$key};  
  }else{
    next if ! exists $p{sta};
    $p{sta} = uc $p{sta};
    #   print "----$p{sta}----------\n";
    push @{$info{$p{sta}}},{ %p };  
    %p=();
  }

}	

my ( @ant_keys,@rcvr_keys,@id_keys);
foreach my $s ( sort keys %info ) {
    foreach my $p ( @{$info{$s}} ) {
       #next if ! exists $p->{sta};
       #print map { "$_ $p->{$_}\n" } sort keys %$p; 
       # Process antenna data
       if ( grep /ant_/, keys %$p   ) {
           next if  ! $p->{ant_sdate} 
                        &&
	            ! $p->{ant_type}
                        && 
	            ! ( $p->{ant_sdate} || $p->{date});
           #print "$p->{sta} : New Antenna info\n";	    
	  #print map { "$_ $p->{$_}\n" } sort grep /ant_/,keys %$p;
	 my %args = svec_args($p);  
	 $svec->add( %args );  
       }
       #Process receiver data
       if ( grep /rcvr_/, keys %$p   ) {
	   
           next if  ! $p->{rcvr_sdate} 
                        &&
	            ! $p->{rcvr_type}
                        && 
	            ! ( $p->{rcvr_sdate} || $p->{date});
		   #print "$p->{sta} : New Receiver info\n";	    
	       #print map { "$_ $p->{$_}\n" } sort grep /ant_/,keys %$p;
	       my %args = rcvr_args($p) ;  
	       $rcvr->add( %args );  
       }
       #Process id/location data
       if ( grep /loc_/, keys %$p   ) {
	   if ( $p->{sta} ) { #&& $p->{loc_x} && $p->{loc_y} && $p->{loc_z}) {
	       my %args = pos_args($p) ;  
	       $pos->add( %args ) if %args;  
	   #}
	   #if ( $p->{sta} && $p->{loc_lon} && $p->{loc_lat} ) {
		#   push @$coord_data, { site => $p->{sta} ,
		#	                lon  => $p->{loc_lon},
		#		        lat  => $p->{loc_lat},	
		#	                net => $p->{loc_site_net}|| $p->{loc_net}
		#		      };                       
	       %args = loc_args($p) ;  
	       $loc->add ( %args ) if %args ;                       
		   # print $p->{sta},"\n";
	   #}	   
           #if (  $p->{sta} ) { 
	       #print "$p->{sta} : new Id/Location info\n";	    
	       #print map { "$_ $p->{$_}\n" } sort grep /loc_/,keys %$p;
	       %args = id_args($p) ;  
	       $id->add( %args ) if %args;  
	   }
       }

       
              
    }    
}

$pos->print( file => "$outdir/sta_pos.tmp"    ) if $do_pos;
$svec->print( file => "$outdir/sta_svec.tmp"  ) if $do_svec;
$rcvr->print(  file => "$outdir/sta_rcvr.tmp" ) if $do_rcvr;
$id->print(  file => "$outdir/sta_id.tmp"     ) if $do_id;
$loc->print( file => "$outdir/sta_loc.tmp"  ) if $do_coords;
#$coords->print( file => "$outdir/coords.tmp"  ) if $do_coords;

sub loc_args {
   my $p = shift;
   if (  ! exists $p->{sta}  ) {
       warn "No station name\n";
       return 
   }
   if (  ! exists $p->{loc_site_net} && ! exists $p->{loc_net} ) {
       warn "No network info\n";
       return 
   }
   if (  ! exists $p->{loc_lon} ||  
         ! exists $p->{loc_lat} || 
         ! exists $p->{loc_elev}   ) {
       warn "No lat lon elev\n";
       return 
   }
   

   $p->{loc_lon} += 360 if $p->{loc_lon} < 0.0;
   $p->{loc_lon} -= 360 ;
   
   my $site    = uc $p->{sta};
   my $net = $p->{loc_site_net}|| $p->{loc_net};
   my $orig_net = '-'x10;
   my $group   = '';
   my $type    = 'CGPS';
   my $region = '';
   if ( $net =~ /nucleus/i ) {
     $net =~ s/nucleus//i;
     $type = 'Nucleus';
     $net = get_region( $p->{loc_state},$p->{loc_lon},$p->{loc_lat});
   }
   
   $net =~ s/PBO(-| )//;
   $net =~ s/NC/NCAL/;
   $net =~ s/SC/SCAL/;
   $net =~ s/PN/PNW/;
   $net =~ s/rio\s+grande\s+rift/RGR/i;
   $net =~ s/USArray Backbone/USAB/;
   $net = trim($net);
   
   $orig_net = exists $p->{loc_orig_net} ? $p->{loc_orig_net} :
               $net =~ /_([A-Z]+)$/      ? $1 : '-'x10 ;
   
   my $id16char = sprintf("%-16s",trim($p->{name})) || '-'x16;   
   my $loc = '';
   if ( exists $p->{loc_rnx_comment} ) { 
     $loc = $p->{loc_rnx_comment}; 
     $loc =~ s/_/ /g;
   }elsif (exists $p->{loc_city}  || 
           exists $p->{loc_state} ||
           exists $p->{loc_country} 
          ) 
   {
     $loc = sprintf("%-s %-s %-s",@{$p}{qw/loc_city loc_state loc_country/});
   }
#  StaLoc fields:
#  sta lon lat region
#  type id16char group
#  status orig_network location
#  Format:
#  A4,2(2X,F9.4),2X,A9,1X,
#  A10,1X,A16,1X,A11,1X,
#  A16,1X,A10,1X,A

   return ( sta    => $p->{sta} ,
	        lon    => $p->{loc_lon},
	        lat    => $p->{loc_lat},	
	        region => sprintf("%-9s",$net),
            type   => sprintf("%-11s",$type),
            id16char => $id16char,
            group    => $group,
            status   => sprintf("%-16s",'Built '.$p->{loc_status} ),
            orig_network => sprintf( "%-10s",$orig_net),
            location     => $loc
          )

#  return ( site => $p->{sta} ,
#        lon  => $p->{loc_lon},
#        lat  => $p->{loc_lat},	
#        net => sprintf("%-5s",trim($net) ),
#           type => 'CGPS'.' 'x20
#         )
    
}
sub get_region {
   my $state = uc pack 'a2', shift;
   my ($lon,$lat) = @_;
   my %region = (
      CS => 'SC',
      CN => 'NC',
      CA => 'CA',
      WA => 'PN',
      OR => 'PN',
      AK => 'AK',
      ID => 'BR',
      NV => 'BR',
      AZ => 'BR',
      NM => 'RM',
      CO => 'RM',
      WY => 'RM',
      MN => 'RM',
      KS => 'RM',
      OK => 'RM',
      TX => 'RM',
      LA => 'RM',
      NE => 'RM',
      SD => 'RM',
      ND => 'RM',
      WI => 'RM',
   );
   my $reg = $region{$state} || 'RM';
   $lon = $lon < 0 ? $lon+360 : $lon;
   #not quite true, but good enough.
   if ( $state eq 'CA' ) {
      $reg =  $lat >= 36 && $lon <= 240 ? 'NC' : 'SC';
   }
   return $reg
}
sub pos_args {
   my $p = shift;
   my $site    = $p->{sta};
   my ($m,$month,$d,$y);
    
   my $date = $p->{site_sdate} || $p->{ant_sdate} || $p->{date} || $today ;
   $date = get_date($date,"cal");
   if (  ! exists $p->{sta}  ) {
       warn "No station name\n";
       return ()
   }
   if (   ! exists $p->{loc_x} || 
          ! exists $p->{loc_y} ||
          ! exists $p->{loc_z}   ) {
      
       if (  ! exists $p->{loc_lon} ||  
             ! exists $p->{loc_lat} || 
             ! exists $p->{loc_elev}   ) {
              warn "No lat lon elev for $p->{sta}\n";
              return ()
       } else {
         my $xyz = `echo $p->{loc_lat} $p->{loc_lon} $p->{loc_elev} |gd2xyz -`;
         $xyz = join ' ', map { $_*1000} split(' ',$xyz);
         ($p->{loc_x},$p->{loc_y},$p->{loc_z}) =  split(' ',$xyz);
          warn "getting xyz from lat lon elev for $p->{sta} : $xyz\n";
       }
   }
   my $comment = sprintf(" |%s |Lon: %-9.4f|Lat: %-9.4f|%10s | %s",$site,
	                                                       $p->{loc_lon},
							       $p->{loc_lat},
							       $today,
						               $p->{comment});
   my %args= ( sta     => $site ,
	       date    => $date,
	       x       => $p->{loc_x},
	       y       => $p->{loc_y},
	       z       => $p->{loc_z},
	       comment => $comment
	  );
   return %args
}

sub id_args {
   my $p = shift;
   my $site    = $p->{sta};
   my ($m,$month,$d,$y);
    
   my $date = $p->{site_sdate} || $p->{ant_sdate} || $p->{date} || $today ;
   $date = get_date($date,'cal'); 
   
   my $id = sprintf '%6d',0;
# my $alias = sprintf("%-16s %-15s %-10s %-20s",$p->{name}||$site,
#	                                         $p->{loc_city},
#						 $p->{loc_state},
#						 $p->{loc_country});
   $p->{loc_country} =~ s/United States/USA/i;
   $p->{loc_country} =~ s/of america//;
#   my $alias = pack('A16 x1 A9 x1 A22 x1 A10 x1  A*',$p->{name}||$site,
#	                                         $p->{loc_iers_domes},
#						 "$p->{loc_city} $p->{loc_country}",
#					         $p->{loc_site_net} 
#						       ||
#						 $p->{loc_net}
#						       ||
#						 $p->{loc_state}
#					        );
#   $alias =~ s/\0/ /g;
   
   my $net = $p->{loc_site_net}|| $p->{loc_net};
   $net =~ s/PBO(-| )//;
   $net =~ s/NC/NCAL/;
   $net =~ s/SC/SCAL/;
   $net =~ s/PN/PNW/;
   $net =~ s/rio\s+grande\s+rift/RGR/i;
   $net =~ s/USArray Backbone/USAB/;
   my $source =    trim($p->{comment}) .' email report';
   my $comment = sprintf("|%10s|%s|", $today,$source);
   my %args= ( sta => $site ,
	           id  => $id,
               name => sprintf("%-16s",$p->{name} || $site),
               iers_domes => $p->{loc_iers_domes},
               location   => sprintf("%-22s","$p->{loc_city} $p->{loc_state} $p->{loc_country}"), 
               net_info => $net,
	    #   alias => $alias,
	       comment => $comment
	  );
   return %args
}



sub rcvr_args {
   my $p = shift;
   my $site    = $p->{sta};
   my ($m,$month,$d,$y);
   my $date = $p->{rcvr_sdate} || $p->{site_sdate} || $p->{date} || $today ;
   my $sdate = get_date($date,"cal") || '';
   $sdate||=$today;
   ($y,$m,$d) = split(/-/,$sdate);
   $date    = sprintf("%04d-%02d-%02d",$y,$m,$d); 
   my $rcvr_type = $p->{rcvr_type}; 
   my $rcvr_sn = $p->{rcvr_sn}; 
   my ($firmware) = split(' ',$p->{rcvr_firmware}); 
   my $source = $p->{comment} || 'email report';
   my $comment = sprintf(" |%10s | %s |", $today,$source);
   return ( sta => $site ,
	        date => $date,
            receiver => $rcvr_type,
            sn  => pack("A5",$rcvr_sn),
            firmware => pack("A11",$firmware),
	        comment => $comment
	  )
    
}

sub svec_args {
    my $p = shift;
    my $site    = $p->{sta};
    my ($m,$month,$d,$y);
    my $date = $p->{ant_sdate} || $p->{site_sdate} || $p->{date} || $today ;
    my $sdate = get_date($date,"cal") || '';
    ($y,$m,$d) = split(/-/,$sdate);
    $date    = sprintf("%04d-%02d-%02d",$y,$m,$d); 
    my $antenna = pack("A16A4",sprintf("%-16s",$p->{ant_type}),
                               $p->{ant_radome}
                      );
    my $htcod   = 'BPA';
    my $height  = $p->{ant_height} || 0.0;
    my $source = 'email report';
    my $comment = sprintf("|%-20s|%-5s|%-5s|%10s | %s |",$antenna,
	                                               $htcod,
						       pack("A5",$p->{ant_sn}),
						       $today,
						       $source);
    
    return (  sta_to   => $site,
              sta_from => $site,
              igs_code => $antenna,
              height   => $height,
              date     => $date,
	          comment  => $comment ) 
}



sub trim {
  my $s = shift;
  $s=~ s/^\s+//;
  $s=~ s/\s+$//;
  return $s
}
