/****************************************************************************/
/*                                                                          */
/*                          IAGA_change_baselines.c                         */
/*                                                                          */
/****************************************************************************/
/****************************************************************************/
/* This program changes baselines of given components in IMAGE data files.  */
/*                                                                          */
/* Usage:                                                                   */
/*   IAGA_change_baselines [-s] [-e] [-x] [-y] [-z] [-X] [-Y] [-Z] [-o]     */
/*                          [<] IAGAFile > NewIAGAFile                      */
/*      [-s YYMMDDHHMMSS]   Time of the first record to be changed.         */
/*                          If missing then start of file is assumed.       */
/*      [-e YYMMDDHHMMSS]   Time of the last record to be changed. If       */
/*                          missing then end of file is assumed.            */
/*      [-o StationList]    List of stations whose data is changed.         */
/*                          If missing then all stations are changed.       */
/*      [-x X-shift]        Baseline shift in X-component in nT's. If       */
/*                          missing then no change is baseline.             */
/*      [-y Y-shift]        Baseline shift in Y-component in nT's. If       */
/*                          missing then no change is baseline.             */
/*      [-z Z-shift]        Baseline shift in Z-component in nT's. If       */
/*                          missing then no change is baseline.             */
/*      [-X X-baseline]     New X value at time defined in -s option. All   */
/*                          subsequent values (until -e option) are shifted */
/*                          by the difference Xnew-Xold.                    */
/*      [-Y Y-baseline]     Same as above but with Y-component.             */
/*      [-Z Z-baseline]     Same as above but with Z-component.             */
/*      IAGAFile            Name of IAGA-format daily 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  8.4.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 4
#define UsageLineCount 20

char *HeaderText[HeaderLineCount] = {
"**************************************************************************",
" This program shifts the baselines of given stations and given components ",
" for specified time interval.                                             ",
"**************************************************************************",
};

char *UsageText[UsageLineCount] = {
"  [-s] [-e] [-x] [-y] [-z] [-X] [-Y] [-Z] [-o] [<] IAGAFile > NewIAGAFile ",
"     [-s YYMMDDHHMMSS]   Time of the first record to be changed.          ",
"                         If missing then start of file is assumed.        ",
"     [-e YYMMDDHHMMSS]   Time of the last record to be changed.           ",
"                         If missing then end of file is assumed.          ",
"     [-o StationList]    List of stations whose data is changed.          ",
"                         If missing then all stations are changed.        ",
"     [-x X-shift]        Baseline shift in X-component in nT's.           ",
"                         If missing then no change is baseline.           ",
"     [-y Y-shift]        Baseline shift in Y-component in nT's.           ",
"                         If missing then no change is baseline.           ",
"     [-z Z-shift]        Baseline shift in Z-component in nT's.           ",
"                         If missing then no change is baseline.           ",
"     [-X X-baseline]     New X value at time defined in -s option. All    ",
"                         subsequent values (until -e option) are shifted  ",
"                         by the difference Xnew-Xold.                     ",
"     [-Y Y-baseline]     Same as above but with Y-component.              ",
"     [-Z Z-baseline]     Same as above but with Z-component.              ",
"     IAGAFile            Name of IAGA-format file.                        ",
"     NewIAGAFile         Name of new IAGA-format file.                    ",
};



/*--------------------------------------------------------------------------*/
/*  Shift data for given station and component                              */
/*--------------------------------------------------------------------------*/

void ShiftData(StationPtr s, Time_sec t0, Time_sec t1, long dB, char Comp)
{
    long *DataPtr;
    long Value;
    Time_sec T;
    
    DataPtr  = GetDataPtr(s,t0,Comp);
    T = t0;
    while (T <= t1) {
        Value = *DataPtr;
        if (Value != MissingValue) {
            *DataPtr = Value+dB;
        }
        
        *DataPtr++;
        T += s->TimeStep;
    }
}


/*--------------------------------------------------------------------------*/
/*  Change the baseline for the given station and component and report      */
/*  possible errors.                                                        */
/*--------------------------------------------------------------------------*/

long ChangeBase(StationPtr Station,Time_sec StartTime, Time_sec EndTime,
                 long Base, long dB, char Comp)
{
    long Value;
    
    if ((dB != 0) || (Base != 999999)) {
        if (Base != 999999) {
            Value = GetDataValue(Station,StartTime,Comp);
            if (Value == MissingValue) {
                fprintf(stderr,"### There is no data at specified ");
                fprintf(stderr,"start time !\n");
                fprintf(stderr,"    Program execution stopped.\n");
                return 1;
            }
            dB = Base - Value;
        }
        ShiftData(Station,StartTime,EndTime,dB,Comp);
    }
    
    return 0;
}


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

int main(int argc, char *argv[])
{
    long    params;
    long    status = 0;
    long    FileCount = 0;
    char    FileName[100] = "";         /* Name of the original data file   */
    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 */
    Network_struct IMAGE;               /* Structure containing the data    */
                                        /* for all stations.                */
    StationPtr  Station;                /* Pointer to the current station   */
    long    Comp;                       /* Current magnetic component       */
    Time_sec    T;                      /* Current time                     */
    long dX = 0;                        /* X baseline shift                 */
    long dY = 0;                        /* Y baseline shift                 */
    long dZ = 0;                        /* Z baseline shift                 */
    long Xbase = 999999;                /* New X-value at StartTime         */
    long Ybase = 999999;                /* New Y-value at StartTime         */
    long Zbase = 999999;                /* New Z-value at StartTime         */


    /*==========================*/
    /* 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' : StartTime = StrToSecs(argv[++params],0); break;
                case 'e' : EndTime   = StrToSecs(argv[++params],0); break;
                case 'o' : strcpy(StationList,argv[++params]);      break;
                case 'x' : dX = 10*atof(argv[++params]);            break;
                case 'y' : dY = 10*atof(argv[++params]);            break;
                case 'z' : dZ = 10*atof(argv[++params]);            break;
                case 'X' : Xbase = 10*atof(argv[++params]);         break;
                case 'Y' : Ybase = 10*atof(argv[++params]);         break;
                case 'Z' : Zbase = 10*atof(argv[++params]);         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 there is at most one data file */
    /*===========================================*/
    
    if (FileCount>1)
    {
        PrintUsage(argv[0],1,HeaderLineCount,UsageLineCount);
        return FAIL;
    }

    /*====================================================*/
    /* Read the 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;
    }


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

    Station = IMAGE.StationList;
    
    if (StartTime == MIN_TIME) StartTime = Station->StartTime;
    if (EndTime == MAX_TIME) EndTime = Station->EndTime - Station->TimeStep;
    
    while (Station != NULL) {

        if (StationInList(Station->StationID,StationList)) {
        
            /*==================================================*/
            /* Go through all components and break the program  */
            /* execution if errors are found.                   */
            /*==================================================*/
            
            if (ChangeBase(Station,StartTime,EndTime,Xbase,dX,'X')) return 1;
            if (ChangeBase(Station,StartTime,EndTime,Ybase,dY,'Y')) return 1;
            if (ChangeBase(Station,StartTime,EndTime,Zbase,dZ,'Z')) return 1;

        }

        Station = Station->Next;
    }


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

    FreeNetwork(&IMAGE);
    return OK;
}

