//
// LDASTools frameCPP - A library implementing the LIGO/Virgo frame
// specification
//
// Copyright (C) 2019 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 FrameCPP_UNIVERSAL__IMPL__FrameHClassicIO_HH
#define FrameCPP_UNIVERSAL__IMPL__FrameHClassicIO_HH

#if defined( __cplusplus )
#if !defined( SWIG )

#include <boost/make_shared.hpp>

#include "framecpp/Common/FrameStream.hh"
#include "framecpp/Common/FrameH.hh"

#include "framecpp/Universal/FrEndOfFrame.hh"

#endif /* defined( SWIG ) */
#endif /* defined( __cplusplus ) */

#include "framecpp/Universal/impl/FrameHData.hh"

#if defined( __cplusplus )
#if !defined( SWIG )

namespace FrameCPP
{
    namespace Universal
    {
        class FrameH;

        namespace FrameHImpl
        {
            template < typename T >
            class ClassicIO : public virtual Data,
                              public Common::TOCInfo,
                              public ObjectWithChecksum< Common::FrameH >
            {
            public:
                // Bring base class GetDescription methods into scope
                using FrameCPP::Common::FrameSpec::Object::GetDescription;

                //-------------------------------------------------------
                //
                //-------------------------------------------------------
                ClassicIO( ) : ObjectWithChecksum< Common::FrameH >( nullptr )
                {
                }

                ClassicIO( const ClassicIO& ) = default;
                ClassicIO( ClassicIO&& ) = default;
                ClassicIO& operator=( const ClassicIO& ) = delete;
                ClassicIO& operator=( ClassicIO&& ) = delete;

                //-----------------------------------------------------------------
                /// \brief The name structure name of this object.
                ///
                /// \return
                ///     The name of the structure as specified by the frame
                ///     specification.
                //-----------------------------------------------------------------
                virtual const char*
                ObjectStructName( ) const override
                {
                    return StructName( );
                }

                //-----------------------------------------------------------------
                /// @brief The data structure description
                ///
                /// @return
                ///     The description of the data structure used to represent
                ///     this object when written to a GWF stream
                //-----------------------------------------------------------------
                virtual const Common::Description*
                GetDescription( unsigned int version ) const override;

            protected:
                typedef Common::FrameH::assign_stream_type assign_stream_type;

                //-----------------------------------------------------------------
                /// \brief Assign the contents of the instance
                ///
                /// \param[in] Stream
                ///     An input stream from which to read information for
                ///     the instance.
                ///
                /// \note
                ///     This has been hidden so programmers are not tempted to
                ///     bypass usage of IFrameStream as the input stream.
                //-----------------------------------------------------------------
                virtual void
                assign( assign_stream_type&     Stream,
                        frame_spec_version_type StreamVersion ) override;

                //-------------------------------------------------------------------
                /// \brief Frame start time in seconds
                //-------------------------------------------------------------------
                virtual inline delta_t_normalized_type
                normalizedDeltaT( ) const override
                {
                    return GetDt( );
                }
                //-------------------------------------------------------------------
                /// \brief Duration of the frame
                //-------------------------------------------------------------------
                virtual inline start_time_normalized_type
                normalizedStartTime( ) const override
                {
                    return GetGTime( );
                }

                //-----------------------------------------------------------------
                /// @brief Number of bytes needed to write this structure
                ///
                /// @param[in] Stream
                ///     The stream from which to the object is being read or
                ///     written.
                ///
                /// @return
                ///     The number of bytes need to read or write this object.
                //-----------------------------------------------------------------
                cmn_streamsize_type
                pBytes( const Common::StreamBase& Stream ) const override;

                //-----------------------------------------------------------------
                /// \brief Virtual constructor.
                ///
                /// \param[in] Stream
                ///     The input stream from which to read the object.
                ///
                /// \return
                ///    A new instance of this object.
                //-----------------------------------------------------------------
                virtual self_type* pCreate( istream_type& Stream ) const override;

                //-----------------------------------------------------------------
                /// \brief Write the structure to the stream
                ///
                /// \param[in] Stream
                ///     The output stream where the object is to be written.
                //-----------------------------------------------------------------
                virtual void pWrite( ostream_type& Stream ) const override;

                //-----------------------------------------------------------------
                /// \brief Limitted reading of the object
                ///
                /// \param[in] Stream
                ///     The input stream from which to read the object.
                /// \param[in] ElementMask
                ///     Mask of elements to read from the Stream
                //-----------------------------------------------------------------
                virtual void readSubset( istream_type& Stream,
                                         INT_4U        ElementMask ) override;

            private:
                typedef STRING io_name_type;

                using Common::FrameSpec::Object::Create;

#if WORKING_VIRTUAL_TOCQUERY
            public:
                //-----------------------------------------------------------------
                /// \brief Answer requests for information as needed by TOC
                ///
                /// \param[in] InfoClass
                ///     Class of information being requested.
                //-----------------------------------------------------------------
                void TOCQuery( int InfoClass, ... ) const;
#else /* WORKING_VIRTUAL_TOCQUERY */
            protected:
                //-----------------------------------------------------------------
                /// \brief Answer requests for information as needed by TOC
                ///
                /// \param[in] InfoClass
                ///     Class of information being requested.
                /// \param[in] vl
                ///     Variable argument list of requested data.
                //-----------------------------------------------------------------
                virtual void vTOCQuery( int InfoClass, va_list vl ) const override;
#endif /* WORKING_VIRTUAL_TOCQUERY */
            };

        } // namespace FrameHImpl
    } // namespace Universal
} // namespace FrameCPP

#endif /* defined( SWIG ) */
#endif /* defined( __cplusplus ) */

#endif /* FrameCPP_UNIVERSAL__IMPL__FrameHClassicIO_HH */
