//
// 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
//

#ifndef FRAME_CPP__C_INTERFACE__FRAME_H_INTERNAL_HH
#define FRAME_CPP__C_INTERFACE__FRAME_H_INTERNAL_HH

#include <boost/shared_ptr.hpp>

namespace FrameC
{
    struct FrameH : public Handle
    {
        typedef FrameCPP::FrameH                 data_core_t;
        typedef boost::shared_ptr< data_core_t > data_t;

        data_t m_data;

        FrameH( );

        FrameH( const char*     Name,
                frame_h_gtime_t Start,
                frame_h_dt_t    Dt,
                frame_h_frame_t FrameNumber );

        ~FrameH( );

        inline void
        Read( ::fr_file_t* Stream, ::frame_h_frame_t Offset )
        {
            FrameCPP::IFrameStream* fs( StreamAsInput( Stream ) );

            m_data = fs->ReadFrameH( Offset, 0 );

            if ( !m_data )
            {
                std::ostringstream msg;

                msg << "Failed to read frame " << Offset << " from the stream.";

                throw std::runtime_error( msg.str( ) );
            }
        }

        inline void
        ReadNext( ::fr_file_t* Stream )
        {
            FrameCPP::IFrameStream* fs( StreamAsInput( Stream ) );

            m_data = fs->ReadNextFrame( );

            if ( !m_data )
            {
                std::ostringstream msg;

                msg << "Failed to read the next frame from the stream.";

                throw std::runtime_error( msg.str( ) );
            }
        }
    };

    template <>
    inline pointer_type
    PointerType( FrameH* Value )
    {
        return POINTER_FRAME_H;
    }

    template <>
    const char*
    Pointers::Name< POINTER_FRAME_H >( )
    {
        return "FrameH";
    }
} // namespace FrameC

#endif /* FRAME_CPP__C_INTERFACE__FRAME_H_INTERNAL_HH */
