//
// 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 <framecpp_config.h>

#include <iostream.h>
#include <fstream.h>

#undef PLAIN_READER_TEST
#ifdef PLAIN_READER_TEST
#include "../src/frame.hh"
#include "../src/framereader.hh"

using FrameCPP::Frame;
using FrameCPP::FrameReader;
#else
#include "../src/daqframe.hh"
#include "../src/daqreader.hh"

using FrameCPP::DaqFrame;
using FrameCPP::DaqReader;
#endif

void
error_watch( const string& msg )
{
    cerr << msg << endl;
}

int
main( int argc, char* argv[] )
{
    ifstream tin( argv[ 1 ] );
#ifdef PLAIN_READER_TEST
    FrameReader
#else
    DaqReader
#endif
        fr( tin );
    fr.setErrorWatch( error_watch );
#ifdef PLAIN_READER_TEST
    Frame
#else
    DaqFrame
#endif
        * tf( 0 );
    try
    {
        tf = fr.readFrame( ); // template frame
    }
    catch ( cannot_update& e )
    {
        cerr << e.what( ) << endl;
        exit( 1 );
    }
    catch ( ... )
    {
        cerr << "couldn't read reference frame" << endl;
        exit( 1 );
    }

    tf->getRawData( )->refAdc( ).rehash( );

    for ( unsigned int i = 0; i < tf->getRawData( )->refAdc( ).getSize( ); i++ )
    {
        cerr << tf->getRawData( )->refAdc( )[ i ]->getName( ) << '\t'
             << tf->getRawData( )->refAdc( )[ i ]->getInstance( ) << endl;
        // print out some data from the vector
        //
        REAL_4* data = (REAL_4*)tf->getRawData( )
                           ->refAdc( )[ 0 ]
                           ->refData( )[ 0 ]
                           ->getData( );
        for ( unsigned int j = 0; j < 3; j++ )
        {
            cerr << data[ j ];
        }
        cerr << endl;
    }

#ifndef PLAIN_READER_TEST
    // reader `fr' may be deleted now
    try
    {
        cerr << "Start" << endl;
        tf->printActiveChannels( cerr );

        tf->daqActivateAllADCs( );
        cerr << "After activate all" << endl;
        tf->printActiveChannels( cerr );

        tf->daqResetADCs( ); // deactivate all ADCs
        cerr << "After reset all" << endl;
        tf->printActiveChannels( cerr );

        tf->daqActivateAllADCs( );
        cerr << "After activate all" << endl;
        tf->printActiveChannels( cerr );

#ifdef not_def
        tf->daqResetADCs( ); // deactivate all ADCs
        cerr << "After reset all" << endl;
        tf->printActiveChannels( cerr );

        tf->daqTriggerADC( "H0:PEM-BT5_MIC", true ); // activate one
        cerr << "After activate H0:PEM-BT5_MIC" << endl;
        tf->printActiveChannels( cerr );

        tf->daqTriggerADC( "H0:PEM-BT5_MIC", false ); // activate one
        cerr << "After deactivate H0:PEM-BT5_MIC" << endl;
        tf->printActiveChannels( cerr );

        tf->daqTriggerADC( "H0:PEM-BT5_MIC", true ); // activate one
        cerr << "After activate H0:PEM-BT5_MIC" << endl;
        tf->printActiveChannels( cerr );

        tf->daqTriggerADC( 2, true ); // activate one by index
        cerr << "After activate #2" << endl;
        tf->printActiveChannels( cerr );

        tf->daqTriggerADC( 1, 100, true ); // activate a range of them
        cerr << "After activate ## 1-100" << endl;
        tf->printActiveChannels( cerr );
#endif
    }
    catch ( ... )
    {
        cerr << "ADC activation failed" << endl;
        exit( 1 );
    }

    for ( int i = 2; i < argc; i++ )
    {
        ifstream in( argv[ i ] );
        try
        {
            tf->daqUpdate( &in );
        }
        catch ( read_failure )
        {
            cerr << "daqUpdate(): read failure" << endl;
            exit( 1 );
        }
        catch ( cannot_update )
        {
            cerr << "daqUpdate(): cannot update" << endl;
            exit( 1 );
        }
        cerr << tf->getFrame( ) << "\t" << tf->getGTime( ).getSec( ) << "\t"
             << endl;

        for ( unsigned int i = 0; i < tf->getRawData( )->refAdc( ).getSize( );
              i++ )
        {
            cerr << tf->getRawData( )->refAdc( )[ i ]->getName( ) << '\t'
                 << tf->getRawData( )->refAdc( )[ i ]->getInstance( ) << endl;
            // print out some data from the vector
            //
            REAL_4* data = (REAL_4*)tf->getRawData( )
                               ->refAdc( )[ 0 ]
                               ->refData( )[ 0 ]
                               ->getData( );
            for ( unsigned int j = 0; j < 3; j++ )
            {
                cerr << data[ j ];
            }
            cerr << endl;
        }
    }
#endif
}
