/****************************************************************************/
/*                                                                          */
/*                          IAGA_interpolate.c                              */
/*                                                                          */
/****************************************************************************/
/****************************************************************************/
/* This program fills the given records in an IAGA-format file by           */
/* interpolating the data values from the values at the end points of the   */
/* interval. Corrected data is then written into standard output.           */
/*                                                                          */
/* Usage:                                                                   */
/*    IAGA_interpolate [-s -e] | [-a] [-v] [-o] [-c] IAGAFile > NewIAGAFile */
/*         -s YYMMDDHHMMSS  First point to be interpolated                  */
/*         -e YYMMDDHHMMSS  Last point to be interpolated                   */
/*         -a MaxGap        Automatically interpolate every gap whose       */
/*                          length is <= MaxGap seconds.                    */
/*         -v               Verbose. Display information about interpolated */
/*                          gaps.                                           */
/*         -o StationID     Three letter ID of the station.                 */
/*         -c Components    Components to be interpolated                   */
/*         IAGAFile         Name of IAGA-format file.                       */
/*         NewIAGAFile      Name of corrected IAGA-format 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.01        9.9.1999                        */
/****************************************************************************/
/****************************************************************************/
/*  Version history:                                                        */
/*                                                                          */
/*  1.01 09.09.1999 Fixed a Y2K bug in NewTime.h file which resulted in     */
/*                  incorrect year in date strings if year >= 2000.         */
/*  1.0  11.02.1997 First official release                                  */
/****************************************************************************/

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

char *version = "1.01";
char *date = "9.9.1999";

#define HeaderLineCount 6
#define UsageLineCount 16

char *HeaderText[HeaderLineCount] = {
"**************************************************************************",
"IAGA_interpolate fills given records in an IAGA-format data file by       ",
"interpolating the data values from the values at the end points of the    ",
"interval. This program may be used e.g. to remove spikes. It may also be  ",
"used to automatically fill data gaps in data files.                       ",
"**************************************************************************",
};

char *UsageText[UsageLineCount] = {
"  [-s -e] | [-a] [-v] [-c] [-o]  [<] IAGAFile > NewIAGAFile",
"     [-s YYMMDDHHMMSS]   First point to be replaced with interpolated data.",
"     [-e YYMMDDHHMMSS]   Last point to be replaced with interpolated data.",
"     [-a MaxGap]         Automatically interpolate every gap whose length",
"                         is less than or equal to MaxGap.",
"                         If -s and -e are specified then -a should not be",
"                         specified. If -a is specified then it is illegal",
"                         to give -s and -e.", 
"     [-v]                Verbose. Display information about interpolated",
"                         gaps.",
"     [-c XYZ]            Components to be interpolated.",
"                         If missing then all components (XYZ) filled.",
"     [-o StationList]    Three letter ID's of the stations. If missing",
"                         then all stations interpolated.",
"     IAGAFile            Name of IAGA-format file.",
"     NewIAGAFile         Name of new IAGA-format file.",
};



/*--------------------------------------------------------------------------*/
/*  Write station, component, start time and length of the interpolated gap */
/*--------------------------------------------------------------------------*/

void WriteGapInfo(StationPtr Station,Time_sec T1, Time_sec T2, char Comp)
{
    char StartStr[20];
    
    SecsToStr(T1,StartStr);
    fprintf(stderr,"%s %c   %.6s %s   %u secs\n",Station->StationID,Comp,
        StartStr,StartStr+6,T2-T1);
}


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

int main(int argc, char *argv[])
{
    long    params;
    long    status = 0;
    long    FileCount = 0;
    long    MaxGap = -1;                /* Largest gap to be interpolated   */
    char    FileName[100] = "";         /* Name of the original data file   */
    Time_sec T,GapStart,GapEnd;
    Time_sec StartTime = MIN_TIME;      /* Time of first data block (secs)  */
    Time_sec EndTime   = MAX_TIME;      /* Time of last data block          */
    char    StationList[100] = "";      /* List of stations in command line */
    char    CompStr[5] = "XYZ";         /* List of components               */
    Network_struct IMAGE;               /* Structure containing the data    */
                                        /* for all stations.                */
    StationPtr  Station;                /* Pointer to the corrected station */
    long    Comp;                       /* Current magnetic component       */
    long    VerboseFlag = 0;            /* Display information about gaps   */


    /*==========================*/
    /* 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 'a' : MaxGap = atol(argv[++params]);           break;
                case 's' : StartTime = StrToSecs(argv[++params],0); break;
                case 'e' : EndTime   = StrToSecs(argv[++params],0); break;
                case 'o' : strcpy(StationList,argv[++params]);      break;
                case 'c' : strcpy(CompStr,argv[++params]);          break;
                case 'v' : VerboseFlag = 1;                         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 that all necessary parameters are defined */
    /*=================================================*/
    
    if (FileCount>1)
    {
        PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount);
        return FAIL;
    }

    if (((StartTime == MIN_TIME) || (EndTime == MAX_TIME)) && (MaxGap == -1))
    {
        PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount);
        return FAIL;
    }

    /*================================================*/
    /* Read data from an IAGA format file into memory */
    /*================================================*/

    status = ReadIAGA(FileName,&IMAGE,NULL,NULL,NULL);

    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 IAGA format file\n",FileName);
        return FAIL;
    }

    /*=======================================================*/
    /* Check that the values of the parameters are resonable */
    /*=======================================================*/
        
    Station = IMAGE.StationList;

    if ((MaxGap == -1) && (StartTime > EndTime)) {
        fprintf(stderr,"StartTime > EndTime !?\n");
        return FAIL;    
    }

    if ((MaxGap == -1) &&
        ((StartTime-Station->StartTime) % Station->TimeStep) != 0) {
        fprintf(stderr,
            "Illegal StartTime. There is no such data point in the datafile\n");
        return FAIL;    
    }

    if ((MaxGap == -1) &&
        ((EndTime-Station->StartTime) % Station->TimeStep) != 0) {
        fprintf(stderr,
            "Illegal EndTime. There is no such data point in the datafile\n");
        return FAIL;    
    }

    
    /*======================================*/
    /* Go through all stations in NETWORK   */
    /*======================================*/

    while (Station != NULL) {

        if (StationInList(Station->StationID,StationList)) {
        
            /*======================================*/
            /* Go through all specified components  */
            /*======================================*/
    
            for (Comp=0;Comp<strlen(CompStr);Comp++) {

                if (MaxGap != -1) {     /*** Find and interpolate data gaps ***/

                    T = Station->StartTime;
                    while (T < Station->EndTime) {
                        if (FindGap(Station,CompStr[Comp],T,&GapStart,&GapEnd)) {
                            if (GapEnd-GapStart <= MaxGap) {
                                InterpolateData(Station,GapStart,
                                    GapEnd-Station->TimeStep,CompStr[Comp]);
                                if (VerboseFlag == 1)
                                    WriteGapInfo(Station,GapStart,GapEnd,CompStr[Comp]);
                            }
                        }
                        T = GapEnd;
                    }
                }

                else {                  /*** Interpolate single interval ***/
                    InterpolateData(Station,StartTime,EndTime,CompStr[Comp]);
                    if (VerboseFlag == 1)
                        WriteGapInfo(Station,StartTime,EndTime,CompStr[Comp]);
                }
            }
        }                           /* End of if */

        Station = Station->Next;
    }                               /* End of Station Loop */


    /*==========================================*/
    /* Write the corrected data into stdout     */
    /*==========================================*/
    
    WriteIAGA(NULL,&IMAGE,NULL,NULL,NULL);

    FreeNetwork(&IMAGE);
    return OK;
}

