/* * LDASTools frameCPP - A library implementing the LIGO/Virgo frame
 * specification
 *
 * Copyright (C) 2018 California Institute of Technology
 *
 * LDASTools frameCPP is free software; you may redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 (GPLv2) of the
 * License or at your discretion, any later version.
 *
 * LDASTools frameCPP is distributed in the hope that it will be useful, but
 * without any warranty or even the implied warranty of merchantability
 * or fitness for a particular purpose. See the GNU General Public
 * License (GPLv2) for more details.
 *
 * Neither the names of the California Institute of Technology (Caltech),
 * The Massachusetts Institute of Technology (M.I.T), The Laser
 * Interferometer Gravitational-Wave Observatory (LIGO), nor the names
 * of its contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * You should have received a copy of the licensing terms for this
 * software included in the file LICENSE located in the top-level
 * directory of this package. If you did not, you can view a copy at
 * http://dcc.ligo.org/M1500244/LICENSE
 */

#include <stdio.h>

#include <stdlib.h>

#include "framecppc/FrameC.h"
#include "framecppc/FrChan.h"
#include "framecppc/FrDetector.h"
#include "framecppc/FrEvent.h"
#include "framecppc/FrHistory.h"
#include "framecppc/FrVect.h"
#include "framecppc/FrameH.h"
#include "framecppc/Stream.h"

/*----------------------------------------------------------------------
 * Structures
 *----------------------------------------------------------------------
 */

typedef struct
{
    frame_h_name_t         name;
    frame_h_run_t          run;
    frame_h_frame_t        frame;
    frame_h_data_quality_t dataQuality;
    frame_h_gtime_t        GTime;
    frame_h_dt_t           dt;
} FrameH;

/*----------------------------------------------------------------------
 * Global variables
 *----------------------------------------------------------------------
 */

FrameCError* ErrorCode; /* Records the error code	*/
const char*  ProcessName; /* Name of the running process	*/
int          ExitStatus = 0; /* Exit code			*/

/*----------------------------------------------------------------------
 * Local functions
 *----------------------------------------------------------------------
 */

int
Failed( const char* FunctionName )
{
    if ( ErrorCode )
    {
        fprintf( stderr,
                 "%s: FAIL: %s: %s (%d)\n",
                 ProcessName,
                 FunctionName,
                 ErrorCode->s_message,
                 ErrorCode->s_errno );
        ExitStatus = 1;
        return 1;
    }
    return 0;
}

void
dumpFrameH( const FrameH* frameh )
{
    printf( "FrameH:       name: %s\n", frameh->name );
    printf( "               run: %d\n", frameh->run );
    printf( "             frame: %d\n", frameh->frame );
    printf( "       dataQuality: %d\n", frameh->dataQuality );
    printf( "                dt: %g\n", frameh->dt );
}

void
frameIteration( const char* filename )
{
    static const char* FUNCTION_NAME = "frameIteration";
    fr_file_t*         ifs = (fr_file_t*)NULL;
    frame_h_t*         frameh_ptr = (frame_h_t*)NULL;
    int                file_checksum_retval = 0;

    /*--------------------------------------------------------------------
     * Open the stream
     *--------------------------------------------------------------------
     */
    ifs = FrameCFileOpen( &ErrorCode, filename, FRAMEC_FILE_MODE_INPUT );

    if ( Failed( FUNCTION_NAME ) )
        goto error;

    /*--------------------------------------------------------------------
     * Verify the frame file checksum
     *--------------------------------------------------------------------
     */
    file_checksum_retval = FrameCFileCksumValid( &ErrorCode, ifs );

    if ( ( !file_checksum_retval ) || Failed( FUNCTION_NAME ) )
        goto error;

    /*--------------------------------------------------------------------
     * Read the next frame from the stream
     *--------------------------------------------------------------------
     */
    frameh_ptr = FrameCFrameHReadNext( &ErrorCode, ifs );

    if ( Failed( FUNCTION_NAME ) )
        goto error;

    {
        FrameH frameh;

        FrameCFrameHQuery( &ErrorCode,
                           frameh_ptr,
                           FRAME_H_FIELD_NAME,
                           &frameh.name,
                           FRAME_H_FIELD_RUN,
                           &frameh.run,
                           FRAME_H_FIELD_FRAME,
                           &frameh.frame,
                           FRAME_H_FIELD_DATA_QUALITY,
                           &frameh.dataQuality,
                           FRAME_H_FIELD_DT,
                           &frameh.dt,
                           FRAME_H_FIELD_LAST );

        dumpFrameH( &frameh );
    }

error:
{
    FrameCError* ignored_error_code; /* Records the error code	*/

    FrameCErrorInit( &ignored_error_code );
    /*------------------------------------------------------------------
     * Release the frame resources if they were allocated
     *------------------------------------------------------------------
     */
    if ( frameh_ptr )
    {
        FrameCFrameHFree( &ignored_error_code, frameh_ptr );
        frameh_ptr = (frame_h_t*)NULL;
    }
    /*------------------------------------------------------------------
     * Close the stream
     *------------------------------------------------------------------
     */
    if ( ifs )
    {
        FrameCFileClose( &ignored_error_code, ifs );
        FrameCFileFree( &ignored_error_code, ifs );
        ifs = (fr_file_t*)NULL;
    }
}
    /*--------------------------------------------------------------------
     * Need to report the error
     *--------------------------------------------------------------------
     */
}

int
main( int ArgC, char** ArgV )
{
    FrameCErrorInit( &ErrorCode );
    const char* base_name = "Z-R_std_test_frame_ver8-600000000-1.gwf";
    char        filename[ 4096 ];

    /* --------------------------------------------------------------------
     *  Test reading frames sequentially
       --------------------------------------------------------------------
     */
    const char* td = getenv( "TEST_DIR" );
    if ( td )
    {
        snprintf( filename, sizeof(filename), "%s/%s", td, base_name );
    }
    else
    {
        snprintf( filename, sizeof(filename), "%s", base_name );
    }
    frameIteration( filename );

    /* --------------------------------------------------------------------
     *  Prepare for exiting
     * --------------------------------------------------------------------
     */
    FrameCCleanup( );
    exit( ExitStatus );
}
