#!/usr/bin/env perl

# ========================================================================
# createRnx3Aliases.pl
# ========================================================================
#
# Purpose : Helps to create Rnx3 alias mountpoints for a existing
#           BKG NtripCaster installation. See help for details.
#
# Revision: $Id:$
# ========================================================================

# Uses
use strict;
use warnings;

# Arguments
my ($confDir) = @ARGV;
if ( !defined $confDir || $confDir =~ /-h|--help/ ) {
    print <<EOI_HLP;

createRnx3Aliases.pl - Helps to create Rnx3 alias mountpoints for a existing
    BKG NtripCaster installation.

    See White Paper URL???
    For NtripCaster admins.
    The output contains the alias records for the ntripcaster.conf file.
    Creates a new sourcetable file with alias records included.

USAGE:
  $0 <ntripcaster-conf-dir>

EXAMPLES:
   $0 /home/rt/eurefcaster/conf

Authors:
   Erwin Wiesensarter <Erwin.Wiesensarter\@bkg.bund.de>

EOI_HLP
    exit;
}

my $ntripcaster_conf = $confDir . '/ntripcaster.conf';
my $sourcetable_dat  = $confDir . '/sourcetable.dat';

my @igsLongNames = <DATA>;
chomp $_ for (@igsLongNames);

my @existing_mpts;
my %st_streams = parseSourcetable($sourcetable_dat);

# Create alias names for each stream
# ----------------------------------
my @alias;
my $rnx3Name = "";
while ( my ( $fourCharId, $rows ) = each %st_streams ) {

    # RAW streams
    my @raw = grep ( $_->[3] =~ /RAW/i, @$rows );
    if (@raw) {
        if ( scalar @raw > 1 ) {
            warn "WARN: more than one RAW stream for $fourCharId\n";
        }
        my $i = 0;
        foreach (@raw) {
            if ( $i == 0 ) {
                $rnx3Name = $fourCharId . "00" . $_->[8] . 9;
                if ( grep { $rnx3Name eq $_ } @existing_mpts ) {
                    print "$rnx3Name already exists - skip";
                    next;
                }
                printf "%-5s  %-8s  %-6s %-9s\n", $_->[1], $_->[3], $_->[4], $rnx3Name;
                push ( @alias, [ $_->[1], $rnx3Name ] );
            }
            else {
                printf "%-5s  %-8s  %-6s %-9s\n", $_->[1], $_->[3], $_->[4], "skipped";
            }

            $i++;
        }
    }

    # RTCM streams
    my @rtcm = map { $_->[0] }
      sort { $b->[2] <=> $a->[2] }
      map { [ $_, split ( /\s+/, $_->[3], 2 ) ] }
      grep { $_->[3] =~ /RTCM/i } @$rows;

    my $i = 0;
    foreach (@rtcm) {
        $rnx3Name = $fourCharId . "00" . $_->[8] . $i++;
        if ( grep { $rnx3Name eq $_ } @existing_mpts ) {
            print "$rnx3Name already exists - skip";
            next;
        }
        printf "%-5s  %-15s  %-9s\n", $_->[1], $_->[3], $rnx3Name;
        push ( @alias, [ $_->[1], $rnx3Name ] );
    }

    print "\n";
}

print "===================== Alias ===================== (insert in $ntripcaster_conf)\n";
foreach ( sort { ( $a->[1] ) cmp ( $b->[1] ) } @alias ) {
    print "alias /$_->[1] /$_->[0]\n";
}
print "\n";

writeNewSourcetable($sourcetable_dat);

###############################################################################
sub parseSourcetable {
    my ($sourcetableFil) = @_;

    my %st;
    open ( my $ST, '<', $sourcetableFil ) || die "Could not open file '$sourcetableFil': $!\n";
    while (<$ST>) {
        chomp;
        next if ( $_ =~ /^#/ );
        $_ =~ /^(CAS|NET|STR);.+/ || die "Weird sourcetable line: [$_]";
        if ( $_ =~ /^STR;/ ) {
            my @fields = split ';', $_;
            push ( @existing_mpts, $fields[1] );
            scalar @fields >= 18 || die "Not enough fields in line: [$_]\nsee http://software.rtcm-ntrip.org/wiki/STR";
            if ( $fields[1] =~ /^CLK|EPH$/i ) {
                print "INFO: skip $fields[1]\n";
                next;
            }

            # Consider only mountpoint names with length 5
            if ( length ( $fields[1] ) == 5 ) {
                my $fourCharId = substr ( $fields[1], 0, 4 );

                # Compare country code with official IGS station list (IGS Network.csv 21.12.2017 from
                # http://www.igs.org/network)
                my @igs_found = grep ( $fourCharId eq substr ( $_, 0, 4 ), @igsLongNames );
                if (@igs_found) {
                    my $rnx3Name = $fourCharId . "00" . $fields[8];
                    $rnx3Name eq $igs_found[0]
                      || warn
                      "ERROR: wrong country code \"$fields[8]\" for sourcetable stream $fields[1] (IGS: $igs_found[0])\n"
                      ;    # die
                }
                push ( @{ $st{$fourCharId} }, \@fields );
            }
        }
    }
    close ($ST);
    return %st;
}

sub writeNewSourcetable {
    my ($sourcetable_orig) = @_;

    my $sourcetable_new = $sourcetable_orig . '.new';

    open ( my $ORIG, '<', $sourcetable_orig ) || die "Could not open file '$sourcetable_orig': $!\n";
    open ( my $NEW,  '>', $sourcetable_new )  || die "Could not open file '$sourcetable_new': $!\n";
    while (<$ORIG>) {
        print $NEW $_;
        my @fields = split ( ';', $_ );
        if ( @fields && $fields[0] eq "STR" ) {
            my @found = grep ( $_->[0] eq $fields[1], @alias );    # search for mountpoint
            if (@found) {
                $fields[1]  = $found[0]->[1];
                $fields[18] = $found[0]->[0];
                my $alias_rc = join ( ';', @fields );
                print $NEW "$alias_rc\n";
            }
        }
    }
    close ($ORIG) || die "Could not close file $sourcetable_orig: $!";
    close ($NEW)  || die "Could not close file $sourcetable_new: $!";

    print "INFO: New sourcetable $sourcetable_new created\n";
}

__DATA__
ABMF00GLP
ABPO00MDG
ADIS00ETH
AGGO00ARG
AIRA00JPN
AJAC00FRA
ALBH00CAN
ALGO00CAN
ALIC00AUS
ALRT00CAN
AMC200USA
ANKR00TUR
ANMG00MYS
ANTC00CHL
AREG00PER
AREQ00PER
ARTU00RUS
ARUC00ARM
ASCG00SHN
ASPA00USA
AUCK00NZL
AZU100USA
BADG00RUS
BAIE00CAN
BAKE00CAN
BAKO00IDN
BAMF00CAN
BARH00USA
BHR300BHR
BHR400BHR
BIK000KGZ
BILL00USA
BJCO00BEN
BJFS00CHN
BJNM00CHN
BLYT00USA
BNOA00IDN
BOGI00POL
BOGT00COL
BOR100POL
BRAZ00BRA
BREW00USA
BRFT00BRA
BRMU00GBR
BRST00FRA
BRUN00BRN
BRUX00BEL
BSHM00ISR
BTNG00IDN
BUCU00ROU
BZRG00ITA
CAGS00CAN
CAS100ATA
CCJ200JPN
CEBR00ESP
CEDU00AUS
CGGN00NGA
CHAN00CHN
CHIL00USA
CHOF00JPN
CHPG00BRA
CHPI00BRA
CHTI00NZL
CHUM00KAZ
CHUR00CAN
CHWK00CAN
CIT100USA
CKIS00COK
CKSV00TWN
CLAR00USA
CMP900USA
CMUM00THA
CNMR00USA
COCO00AUS
CORD00ARG
COSO00USA
COTE00ATA
COYQ00CHL
CPNM00THA
CPVG00CPV
CRAO00UKR
CRFP00USA
CRO100VIR
CUSV00THA
CUT000AUS
CUUT00THA
CZTG00ATF
DAE200KOR
DAEJ00KOR
DAKR00SEN
DARW00AUS
DAV100ATA
DEAR00ZAF
DGAR00GBR
DHLG00USA
DJIG00DJI
DLF100NLD
DLTV00VNM
DRAG00ISR
DRAO00CAN
DUBO00CAN
DUM100ATA
DUND00NZL
DYNG00GRC
EBRE00ESP
EIL300USA
EIL400USA
EPRT00USA
ESCU00CAN
EUSM00MYS
FAA100PYF
FAIR00USA
FALE00WSM
FALK00FLK
FFMJ00DEU
FLIN00CAN
FLRS00PRT
FRDN00CAN
FTNA00WLF
FUNC00PRT
GAMB00PYF
GAMG00KOR
GANP00SVK
GCGO00USA
GENO00ITA
GLPS00ECU
GLSV00UKR
GMSD00JPN
GODE00USA
GODN00USA
GODS00USA
GODZ00USA
GOL200USA
GOLD00USA
GOP600CZE
GOP700CZE
GOPE00CZE
GOUG00SHN
GRAC00FRA
GRAS00FRA
GRAZ00AUT
GUAM00GUM
GUAO00CHN
GUAT00GTM
GUUG00GUM
HALY00SAU
HAMD00IRN
HARB00ZAF
HARV00USA
HERS00GBR
HERT00GBR
HKSL00HKG
HKWS00HKG
HLFX00CAN
HNLC00USA
HNPT00USA
HNUS00ZAF
HOB200AUS
HOFN00ISL
HOLB00CAN
HOLM00CAN
HOLP00USA
HRAG00ZAF
HRAO00ZAF
HUEG00DEU
HYDE00IND
IENG00ITA
IISC00IND
INEG00MEX
INVK00CAN
IQAL00CAN
IQQE00CHL
IRKJ00RUS
IRKM00RUS
IRKT00RUS
ISBA00IRQ
ISPA00CHL
ISTA00TUR
IZMI00TUR
JCTW00ZAF
JFNG00CHN
JNAV00VNM
JOG200IDN
JOZ200POL
JOZE00POL
JPLM00USA
JPRE00ZAF
KARR00AUS
KAT100AUS
KELY00GRL
KERG00ATF
KGNI00JPN
KHAR00UKR
KIR000SWE
KIR800SWE
KIRI00KIR
KIRU00SWE
KIT300UZB
KITG00UZB
KMNM00TWN
KOKB00USA
KOKV00USA
KOS100NLD
KOUC00NCL
KOUG00GUF
KOUR00GUF
KRGG00ATF
KRS100TUR
KSMV00JPN
KUNM00CHN
KUUJ00CAN
KZN200RUS
LAE100PNG
LAMA00POL
LAUT00FJI
LBCH00USA
LCK300IND
LCK400IND
LEIJ00DEU
LHAZ00CHN
LLAG00ESP
LMMF00MTQ
LPAL00ESP
LPGS00ARG
LROC00FRA
M0SE00ITA
MAC100AUS
MAD200ESP
MADR00ESP
MAG000RUS
MAJU00MHL
MAL200KEN
MANA00NIC
MAR600SWE
MAR700SWE
MARS00FRA
MAS100ESP
MAT100ITA
MATE00ITA
MATG00ITA
MAUI00USA
MAW100ATA
MAYG00MYT
MBAR00UGA
MCHL00AUS
MCIL00JPN
MCM400ATA
MDO100USA
MDVJ00RUS
MEDI00ITA
MELI00ESP
MERS00TUR
MET300FIN
METG00FIN
METS00FIN
MFKG00ZAF
MGUE00ARG
MIKL00UKR
MIZU00JPN
MKEA00USA
MOBJ00RUS
MOBK00RUS
MOBN00RUS
MOBS00AUS
MOIU00KEN
MONP00USA
MORP00GBR
MQZG00NZL
MRL100NZL
MRL200NZL
MRO100AUS
MTKA00JPN
MTV100URY
MTV200URY
NAIN00CAN
NAMA00SAU
NANO00CAN
NAUR00NRU
NCKU00TWN
NICO00CYP
NIST00USA
NIUM00NIU
NKLG00GAB
NLIB00USA
NNOR00AUS
NOT100ITA
NOVM00RUS
NRC100CAN
NRIL00RUS
NRL100USA
NRMD00NCL
NTUS00SGP
NURK00RWA
NVSK00RUS
NYA100NOR
NYA200NOR
NYAL00NOR
OAK100GBR
OAK200GBR
OBE400DEU
OHI200ATA
OHI300ATA
ONS100SWE
ONSA00SWE
OPMT00FRA
ORID00MKD
OSN300KOR
OSN400KOR
OUS200NZL
OWMG00NZL
PADO00ITA
PALM00ATA
PARC00CHL
PARK00AUS
PBRI00IND
PDEL00PRT
PEN200HUN
PENC00HUN
PERT00AUS
PETS00RUS
PGEN00PHL
PICL00CAN
PIE100USA
PIMO00PHL
PIN100USA
PNGM00PNG
POHN00FSM
POL200KGZ
POLV00UKR
POTS00DEU
POVE00BRA
PPPC00PHL
PRDS00CAN
PRE300ZAF
PRE400ZAF
PTAG00PHL
PTBB00DEU
PTGG00PHL
PTVL00VUT
QAQ100GRL
QIKI00CAN
QUI300ECU
QUI400ECU
QUIN00USA
RABT00MAR
RAEG00PRT
RAMO00ISR
RBAY00ZAF
RCMN00KEN
RDSD00DOM
RECF00BRA
REDU00BEL
RESO00CAN
REUN00REU
REYK00ISL
RGDG00ARG
RIGA00LVA
RIO200ARG
RIOP00ECU
ROAP00ESP
ROCK00USA
ROTH00ATA
SALU00BRA
SAMO00WSM
SANT00CHL
SASK00CAN
SASS00DEU
SAVO00BRA
SBOK00ZAF
SCH200CAN
SCIP00USA
SCOR00GRL
SCRZ00BOL
SCTB00ATA
SCUB00CUB
SEJN00KOR
SEY200SYC
SEYG00SYC
SFDM00USA
SFER00ESP
SGOC00LKA
SHAO00CHN
SHE200CAN
SIMO00ZAF
SIN100SGP
SMST00JPN
SNI100USA
SOD300FIN
SOFI00BGR
SOLA00SAU
SOLO00SLB
SPK100USA
SPT000SWE
SPTU00BRA
SSIA00SLV
STFU00USA
STHL00GBR
STJ300CAN
STJO00CAN
STK200JPN
STR100AUS
STR200AUS
SULP00UKR
SUTH00ZAF
SUTM00ZAF
SUWN00KOR
SVTL00RUS
SYDN00AUS
SYOG00ATA
TABL00USA
TANA00ETH
TASH00UZB
TCMS00TWN
TDOU00ZAF
TEHN00IRN
THTG00PYF
THTI00PYF
THU200GRL
THU300GRL
TID100AUS
TIDB00AUS
TIT200DEU
TIXI00RUS
TLSE00FRA
TLSG00FRA
TNML00TWN
TONG00TON
TORP00USA
TOW200AUS
TRAK00USA
TRO100NOR
TSK200JPN
TSKB00JPN
TUBI00TUR
TUVA00TUV
TWTF00TWN
UCAL00CAN
UCLP00USA
UCLU00CAN
UFPR00BRA
ULAB00MNG
ULDI00ZAF
UNB300CAN
UNBD00CAN
UNBJ00CAN
UNBN00CAN
UNSA00ARG
UNX200AUS
UNX300AUS
URUM00CHN
USN700USA
USN800USA
USN900USA
USNO00USA
USUD00JPN
UZHL00UKR
VACS00MUS
VALD00CAN
VESL00ATA
VILL00ESP
VIS000SWE
VNDP00USA
VOIM00MDG
WAB200CHE
WARK00NZL
WARN00DEU
WDC500USA
WDC600USA
WES200USA
WGTN00NZL
WHC100USA
WHIT00CAN
WIDC00USA
WILL00CAN
WIND00NAM
WLSN00USA
WROC00POL
WSRT00NLD
WTZ300DEU
WTZA00DEU
WTZR00DEU
WTZS00DEU
WTZZ00DEU
WUH200CHN
WUHN00CHN
XIAN00CHN
XMIS00AUS
YAKT00RUS
YAR200AUS
YAR300AUS
YARR00AUS
YEBE00ESP
YEL200CAN
YELL00CAN
YIBL00OMN
YKRO00CIV
YONS00KOR
YSSK00RUS
ZAMB00ZMB
ZECK00RUS
ZIM200CHE
ZIM300CHE
ZIMJ00CHE
ZIMM00CHE
ZWE200RUS

