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

#include "framecpp/frame.hh"
#include "framecpp/framereader.hh"

using FrameCPP::AdcData;
using FrameCPP::Frame;
using FrameCPP::FrameReader;
using FrameCPP::RawData;

main( int argc, char* argv[] )
{
    ifstream    in( argv[ 1 ] );
    FrameReader r( in );

    Frame* f( r.readFrame( ) );

    RawData* raw = f->getRawData( );

    char                       type;
    char                       q[ 500 ];
    RawData::adcData_iterator  iter( raw->refAdc( ).begin( ) );
    RawData::AdcDataContainer& adc( raw->refAdc( ) );

    do
    {
        for ( int i = 0; i < raw->refAdc( ).getSize( ); ++i )
        {
            cout << raw->refAdc( )[ i ]->getName( ) << " ";
        }

        cout << "\n1: normal\n2: next normal\n3: regex\n4: next regex\n5: "
                "hash\n6: Quit\n\nType? ";
        cin >> type;

        if ( type != '6' )
        {
            cout << "Query? ";
            cin >> q;
        }
        adc.rehash( );

        switch ( type )
        {
        case '1':
            iter = adc.find( q, adc.begin( ) );
            if ( iter != adc.end( ) )
                cout << ( *iter )->getName( ) << endl;
            else
                cout << "NOT FOUND" << endl;
            break;

        case '2':
            if ( iter == adc.end( ) )
            {
                cout << "NOT FOUND" << endl;
                break;
            }

            iter = adc.find( q, ++iter );
            if ( iter != adc.end( ) )
                cout << ( *iter )->getName( ) << endl;
            else
                cout << "NOT FOUND" << endl;
            break;

        case '3':
            iter = adc.regexFind( q, adc.begin( ) );
            if ( iter != adc.end( ) )
                cout << ( *iter )->getName( ) << endl;
            else
                cout << "NOT FOUND" << endl;
            break;

        case '4':
            if ( iter == adc.end( ) )
            {
                cout << "NOT FOUND" << endl;
                break;
            }

            iter = adc.regexFind( q, ++iter );
            if ( iter != adc.end( ) )
                cout << ( *iter )->getName( ) << endl;
            else
                cout << "NOT FOUND" << endl;
            break;

        case '5':
            pair< RawData::adcData_hash_iterator,
                  RawData::adcData_hash_iterator >
                p( adc.hashFind( q ) );
            for ( RawData::adcData_hash_iterator hiter = p.first;
                  hiter != p.second;
                  ++hiter )
            {
                cout << hiter->second->getName( ) << endl;
            }
            if ( p.first == p.second )
            {
                cout << "NOT FOUND" << endl;
            }
            break;
        }

        cout << endl;

    } while ( type != '6' );

    in.close( );
}
