/****************************************************************************/
/*                                                                          */
/*                              GADF_to_TEXT.c                              */
/*                                                                          */
/****************************************************************************/
/****************************************************************************/
/* This is a filter program that reads a GADF format data file and writes   */
/* out the same data in text columns.                                       */
/*                                                                          */
/* Usage:                                                                   */
/*  GADF_to_TEXT [-s] [-e | -h] [-o] [-c] [-a] [-v | -g] [-y]               */
/*                                                  [<] GADFFile > TEXTFile */
/*      [-s YYMMDDHH]       Time of the first record included. If missing   */
/*                          then start of file is assumed.                  */
/*      [-e YYMMDDHH]       Time of the record not included anymore. If     */
/*                          missing then end of file is assumed.            */
/*      [-h HH]             Number of hours included. Either -e or -h can   */
/*                          be specified, not both.                         */
/*      [-o 'Station list'] List of stations delimited by aposthropes       */
/*                          If missing then all stations included.          */
/*                          Stations are identified by three-letter code    */
/*                          and separated by exactly one space.             */
/*      [-c 'CompList']     Components to be written. Possible values are   */
/*                          tXYZT (=time,X,Y,Z,Temperature). Default value  */
/*                          is tXYZ (so temperature is not written.). Time  */
/*                          is written in the format YY MM DD HH MM SS.     */
/*      [-a AverPeriod]     Don't write all data values but averages over   */
/*                          AverPeriod.                                     */
/*      [-v]                Write headers (= Station name + Component)      */
/*                          If missing then no headers are written          */
/*      [-g]                Write the geographic coordinates of stations    */
/*                          into the first line. This can be used only if   */
/*                          -c option is not given (=tXYZ) and then the     */
/*                          format of the line is:                          */
/*                          0 0 0 0 0 0 lat_1 lon_1 0 ... lat_N lon_N 0.    */
/*      [-y]                Write the year string with two digits. Default  */
/*                          value is 4 digits (century included).           */
/*      GADFFile            Name of GADF-format file.                       */
/*      TEXTFile            Name of TEXT file.                              */
/*                                                                          */
/****************************************************************************/
/****************************************************************************/
/*                            Lasse Hakkinen                                */
/*                    Finnish Meteorological Institute                      */
/*                        Geophysical Research Division                     */
/*                              P.O.Box 503                                 */
/*                      FIN-00101, Helsinki, Finland                        */
/*                      e-mail: Lasse.Hakkinen@fmi.fi                       */
/*                      phone : (+358)-9-19294634                           */
/*                      fax   : (+358)-9-19294603                           */
/*                                                                          */
/*                      version 1.04        29.10.2003                      */
/****************************************************************************/
/****************************************************************************/
/*  Version history:                                                        */
/*                                                                          */
/*  1.04 29.10.2003 Added -g option.                                        */
/*  1.03 20.01.2000 Added -y option and changed the default year string     */
/*                  format to YYYY. Also added the checking of magnetic     */
/*                  components.                                             */
/*  1.02 17.12.1999 Fixed a bug in GADF.h which read baselines incorrectly  */
/*  1.01 02.07.1999 Fixed a Y2K bug in NewTime.h file which resulted in     */
/*                  incorrect year in date strings if year >= 2000.         */
/*  1.0  15.01.1997 First official release                                  */
/****************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Usage.h"
#include "MagnData.h"
#include "GADF.h"

char *version = "1.04";
char *date = "29.10.2003";

#define HeaderLineCount 4
#define UsageLineCount 28

char *HeaderText[HeaderLineCount] = {
"**************************************************************************",
"This program reads an GADF-format magnetometer data file and writes out   ",
"the data for given components and stations in columnar format (TEXT).     ",
"**************************************************************************",
};

char *UsageText[UsageLineCount] = {
" [-s] [-e | -h] [-o] [-c] [-a] [-v | -g] [-y] [<] GADFFile > TEXTFile",
"       [-s YYMMDDHH]       Time of the first record included. If missing   ",
"                           then start of file is assumed.                  ",
"       [-e YYMMDDHH]       Time of the record not included anymore. If     ",
"                           missing then end of file is assumed.            ",
"       [-h HH]             Number of hours included. Either -e or -h can   ",
"                           be specified, not both.                         ",
"       [-o 'Station list'] List of stations delimited by aposthropes       ",
"                           If missing then all stations included.          ",
"                           Stations are identified by three-letter code    ",
"                           and separated by exactly one space.             ",
"       [-c 'CompList']     List of components to be printed. Possible      ",
"                           values for the components are t,X,Y,Z,T. Here   ",
"                           t is time and T is temperature. The format of   ",
"                           time is YY MM DD HH MM SS. Default value for    ",
"                           CompList is tXYZ (temperature is not written).  ",
"       [-a AverPeriod]     Write data values as averages over AverPeriod.  ",
"       [-v]                Write headers (= Station names + components).   ",
"                           If missing then no headers are written.         ",
"       [-g]                Write the geographic coordinates of the stations",
"                           into the first line. This can be used only if   ",
"                           the -c option is not defined (= -tXYZ, default).",
"                           The format of the first line is then:           ",
"                           0 0 0 0 0 0 lat_1 lon_1 0 ... lat_N lon_N 0     ",
"       [-y]                Write year string with two digits. Default value",
"                           is four (century included).                     ",
"       GADFFile            Name of GADF-format file.                       ",
"       TEXTFile            Name of ASCII file.                             ",
};


/*--------------------------------------------------------------------------*/
/*  Write headers (= Station name + component).                             */
/*--------------------------------------------------------------------------*/

void WriteHeaders(NetworkPtr NETWORK, char *CompStr, long Year2option)
{
    long i,CompCount;
    StationPtr s;
    
    CompCount = strlen(CompStr);
    
    /* Write time */
    if (CompStr[0] == 't') {
        if (Year2option == 1) 
            printf("YY MM DD HH MM SS   ");
        else
            printf("YYYY MM DD HH MM SS   ");
        CompCount--;
    }
    
    /* Write station names and components */
    s = NETWORK->StationList;
    while (s != NULL) {
        for (i = strlen(CompStr)-CompCount; i < strlen(CompStr); i++)
            printf("  %s %c ",s->StationID,CompStr[i]);
        s = s->Next;
    }
    printf("\n");
}


/*--------------------------------------------------------------------------*/
/*  Write horizontal line.                                                  */
/*--------------------------------------------------------------------------*/

void WriteHorLine(NetworkPtr NETWORK, char *CompStr, long Year2option)
{
    long i,CompCount;
    
    CompCount = strlen(CompStr);
    
    
    /* Write a dashed line */
    if (CompStr[0] == 't') {
        if (Year2option == 1)
            printf("--------------------");
        else
            printf("----------------------");
        CompCount--;
    }
    for (i = 0; i < CompCount*(NETWORK->StationCount);i++)
        printf("--------");
    printf("\n");
}


/*--------------------------------------------------------------------------*/
/*  Write geographic locations of the stations in format:                   */
/*  0 0 0 0 0 0 lat_1 lon_1 0  ...  lat_N lon_N 0                           */
/*--------------------------------------------------------------------------*/

void WriteLocations(NetworkPtr NETWORK, char *CompStr, long Year2option)
{
    long i,CompCount;
    StationPtr s;
    
    CompCount = strlen(CompStr);
    
    
    /* Write time */
    if (CompStr[0] == 't') {
        if (Year2option == 1) 
            printf(" 0  0  0  0  0  0   ");
        else
            printf("   0  0  0  0  0  0   ");
        CompCount--;
    }
    
    /* Write station locations */
    s = NETWORK->StationList;
    while (s != NULL) {
        printf("   %5.2f   %5.2f     0  ",(s->Latitude)/100.0,(s->Longitude)/100.0);
        s = s->Next;
    }
    printf("\n");
}


/*--------------------------------------------------------------------------*/
/*                          The main procedure                              */
/*--------------------------------------------------------------------------*/

int main(int argc, char *argv[])
{
    long params;
    long status    = 0;
    long FileCount = 0;
    long HourCount = 0;
    long AvePeriod = 0;
    long i,Ave;
    char FileName[100]    = "";
    char StartTimeStr[14] = "";
    char EndTimeStr[14]   = "";
    char StationStr[200]   = "";
    char ComponentStr[14] = "";
    StationPtr s;
    Time_sec t,EndTime;
    long FirstComp;
    long HeaderFlag = 0;
    long LocationFlag = 0;      /* Flag for writing geographic locations    */
    long Year2option = 0;       /* Print year with two digits, default = 4  */
    char TimeStr[20];
    
    Network_struct NETWORK;

    
    /*==========================*/
    /* Analyse the command line */
    /*==========================*/
    if (argc == 1) {        /* No arguments, show the usage text */
        PrintUsage(argv[0],0,HeaderLineCount,UsageLineCount);
        return OK;
    }

    for (params = 1; params < argc; params++) {
        if (*argv[params] != '-') {
            strcpy(FileName,argv[params]);
            FileCount++;
        } else {
            switch (*(argv[params]+1)) {
                case 's' : strcpy(StartTimeStr,argv[++params]); break;
                case 'e' : strcpy(EndTimeStr,argv[++params]);   break;
                case 'h' : HourCount = atol(argv[++params]);    break;
                case 'o' : strcpy(StationStr,argv[++params]);   break;
                case 'c' : strcpy(ComponentStr,argv[++params]); break;
                case 'a' : AvePeriod = atol(argv[++params]);    break;
                case 'v' : HeaderFlag = 1;                      break;
                case 'g' : LocationFlag = 1;                    break;
                case 'y' : Year2option = 1;                     break;
                case 'p' : /* Do nothing */                     break;
                default  :
                    fprintf(stderr,"\n### %s: \"%s\" is not an option.\n\n",
                            argv[0], argv[params]);
                    PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount);
                    return FAIL;
                    break;
            }
        }
    }
    
    /*====================================*/
    /* Check the values of the parameters */
    /*====================================*/
    
    if (FileCount > 1) {
        PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount);
        return FAIL;
    }
    if ((HourCount != 0) && (strlen(EndTimeStr) > 0)) {
        PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount);
        return FAIL;
    }
    if ((HourCount != 0) && (strlen(StartTimeStr) == 0)) {
        PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount);
        return FAIL;
    }
    if ((LocationFlag == 1) && (strlen(ComponentStr) > 0)) {
        PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount);
        return FAIL;
    }
    if (HourCount != 0) {
        SecsToStr(StrToSecs(StartTimeStr,0)+3600*HourCount,EndTimeStr);
    }


    /*====================================================*/
    /* Read the data from an GADF format file into memory */
    /*====================================================*/

    status = ReadGADF(FileName,&NETWORK,StartTimeStr,EndTimeStr,StationStr);

    if (status != 0) {
        if (status == FileError)
            fprintf(stderr,"Error in reading file %s\n",FileName);
        if (status == OutOfMemory)
            fprintf(stderr,"Out of memory while reading file %s\n",FileName);
        if (status == FileFormatError)
            fprintf(stderr,"%s is not an GADF format file\n",FileName);
        return FAIL;
    }


    /*===============================*/
    /* Check the magnetic components */
    /*===============================*/

    if (strlen(ComponentStr) == 0) {
        *ComponentStr = 't';
        strcpy(ComponentStr+1,NETWORK.StationList->Components);
    }
    else {
        for (i=0;i<strlen(ComponentStr);i++) {
            if (ComponentStr[i] == 't') continue;
            if (strchr(NETWORK.StationList->Components,ComponentStr[i]) == NULL) {
                fprintf(stderr,"Component %c not found in data file %s\n",
                                                    ComponentStr[i],FileName);
                return FAIL;
            }
        }
    }


    /*==========================================*/
    /* Write the data in columns into stdout    */
    /*==========================================*/
    
    if (HeaderFlag) WriteHeaders(&NETWORK,ComponentStr,Year2option);
    if (LocationFlag) WriteLocations(&NETWORK,ComponentStr,Year2option);
    if (HeaderFlag) WriteHorLine(&NETWORK,ComponentStr,Year2option);
    if (AvePeriod == 0) AvePeriod = NETWORK.StationList->TimeStep;
    
    if (strlen(StartTimeStr) == 0)
        t = NETWORK.StationList->StartTime;
    else
        t = StrToSecs(StartTimeStr,0);

    if (strlen(EndTimeStr) == 0)
        EndTime = NETWORK.StationList->EndTime;
    else
        EndTime = StrToSecs(EndTimeStr,0);
        
    while (t < EndTime) {
        FirstComp = 0;
        if (ComponentStr[0] == 't') {       /* Write time */
            SecsToStr(t,TimeStr);
            if (Year2option == 0) {     /* Write century */
                if (t >= YEAR2000)
                    printf("20");
                else
                    printf("19");
            }
            printf("%.2s %.2s %.2s %.2s %.2s %.2s   ",TimeStr,TimeStr+2,
                    TimeStr+4,TimeStr+6,TimeStr+8,TimeStr+10);          
            FirstComp++;
        }
        
        s = NETWORK.StationList;            /* go through the stations */
        while (s != NULL) {
            for (i=FirstComp;i<strlen(ComponentStr);i++) {
                Ave = ComputeAverage(s,ComponentStr[i],t,AvePeriod);
                if (Ave != MissingValue)
                    printf(" %7.1f",Ave/10.0);
                else
                    printf(" 99999.9");
            }
            s = s->Next;
        }
        printf("\n");
        
        t += AvePeriod;
    }

    FreeNetwork(&NETWORK);
    return OK;
}

