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

#if defined( __cplusplus ) && !defined( SWIG )
#include <vector>

#include "framecpp/Common/FrameSpec.hh"
#include "framecpp/Common/FrameSpec.tcc"
#include "framecpp/Common/FrStatData.hh"
#include "framecpp/Common/TOCInfo.hh"

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

namespace FrameCPP
{
    namespace Universal
    {

        class FrStatData;

        namespace FrStatDataImpl
        {
            using base_object_type = Common::FrStatData;

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

                typedef Common::FrStatData::fr_detector_type fr_detector_type;
                //-------------------------------------------------------
                //
                //-------------------------------------------------------
                ClassicIO( ) : ObjectWithChecksum< base_object_type >( nullptr )
                {
                }

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

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

                //-----------------------------------------------------------------
                /// \brief Retrieve the detector associated with the object.
                ///
                /// \return
                ///     The detector associated with the object.
                //-----------------------------------------------------------------
                virtual Common::FrStatData::fr_detector_type
                GetDetector( ) const
                {
                    return Data::GetDetector( );
                }

                //-----------------------------------------------------------------
                /// \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
                {
                    return StructName( );
                }

#if WORKING_VIRTUAL_TOCQUERY
            public:
                //-----------------------------------------------------------------
                /// \brief Answer requests for information as needed by TOC
                ///
                /// \param[in] InfoClass
                ///     Class of information being requested.
                //-----------------------------------------------------------------
                virtual void TOCQuery( int InfoClass, ... ) const;
#else
            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;
#endif /*  WORKING_VIRTUAL_TOCQUERY */

            protected:
                //-----------------------------------------------------------------
                /// \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.
                //-----------------------------------------------------------------
                virtual cmn_streamsize_type
                pBytes( const Common::StreamBase& Stream ) const;

                //-----------------------------------------------------------------
                /// \brief Virtual constructor
                ///
                /// \param[in] Stream
                ///     The input stream from where the object is being read.
                //-----------------------------------------------------------------
                virtual self_type* pCreate( istream_type& Stream ) const;

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

            private:
                typedef STRING io_name_type;
                typedef STRING io_comment_type;
                typedef STRING io_representation_type;

            }; // class ClassicIO
        } // namespace FrStatDataImpl
    } // namespace Universal
} // namespace FrameCPP

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

#if 0
#include <vector>

#include "framecpp/Common/TOCInfo.hh"
#include "framecpp/Common/SearchContainer.hh"
#include "framecpp/Common/FrameStream.hh"
#include "framecpp/Common/FrStatData.hh"

#include "framecpp/Universal/FrDetector.hh"
#include "framecpp/Universal/FrVect.hh"

#include "framecpp/Version7/FrStatData.hh"

#include "framecpp/Version8/FrameSpec.hh"
#include "framecpp/Version8/STRING.hh"
#include "framecpp/Version8/PTR_STRUCT.hh"

#include "framecpp/Version8/FrSE.hh"
#include "framecpp/Version8/FrTOC.hh"

namespace FrameCPP
{
    namespace Universal
    {
        //===================================================================
        //===================================================================

        typedef Version_4::
        FrStatDataPST< PTR_STRUCT, FrDetector, FrVect, FrTable >
                FrStatDataPS;

        //===================================================================
        /// \brief Static Data Structure Definition
        //===================================================================
        class FrStatData : public ObjectWithChecksum< Common::FrStatData >,
                           public FrStatDataNPS,
                           public FrStatDataPS,
                           public Common::TOCInfo
        {
        public:
                // Bring base class GetDescription methods into scope
                using FrameCPP::Common::FrameSpec::Object::GetDescription;

            typedef FrStatDataNPS nps_type;
            typedef FrStatDataPS  ps_type;

            //-----------------------------------------------------------------
            /// \brief Default constructor
            ///
            /// \return
            ///    A new instance of this object.
            //-----------------------------------------------------------------
            FrStatData( );

            //-----------------------------------------------------------------
            /// \brief Copy Constructor
            ///
            /// \param[in] Source
            ///     The object from which to copy the information.
            ///
            /// \return
            ///    A new instance of this object.
            //-----------------------------------------------------------------
            FrStatData( const FrStatData& Source );

            //-----------------------------------------------------------------
            /// \brief Constructor
            ///
            /// \param[in] name
            ///     Static data name
            /// \param[in] comment
            ///     Comemnt
            /// \param[in] representation
            ///     Type of static data being represented
            /// \param[in] timeStart
            ///     Start time of static data validity.
            /// \param[in] timeEnd
            ///     End time of static data validity.
            /// \param[in] version
            ///     Version number of this static structure.
            ///
            /// \return
            ///     A new instance of the object.
            //-----------------------------------------------------------------
            FrStatData( const std::string& name,
                        const std::string& comment,
                        const std::string& representation,
                        INT_4U             timeStart,
                        INT_4U             timeEnd,
                        INT_4U             version );

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

            //-----------------------------------------------------------------
            /// \brief The description of structure
            ///
            /// \return
            ///     A Description object which describes this structure as
            ///     specified by the frame specification.
            //-----------------------------------------------------------------
            static const Common::Description* StructDescription( );

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

#if WORKING_VIRTUAL_TOCQUERY
            //-----------------------------------------------------------------
            /// \brief Answer requests for information as needed by TOC
            ///
            /// \param[in] InfoClass
            ///     Class of information being requested.
            //-----------------------------------------------------------------
            virtual void TOCQuery( int InfoClass, ... ) const;
#endif /*  WORKING_VIRTUAL_TOCQUERY */

            //-----------------------------------------------------------------
            /// \brief Merge with another FrAdcData
            ///
            /// \param[in] RHS
            ///     The source of the information to append to this FrAdcData
            ///     structure.
            ///
            /// \return
            ///     A reference to this object
            //-----------------------------------------------------------------
            FrStatData& Merge( const FrStatData& RHS );

            //-----------------------------------------------------------------
            /// \brief equality operator
            ///
            /// \param[in] RHS
            ///     The FrAdcData object to be compared.
            ///
            /// \return
            ///     The value true is returned if this object is equivelent
            ///     to the RHS instance; false otherwise.
            //-----------------------------------------------------------------
            bool operator==( const FrStatData& RHS ) const;

            //-----------------------------------------------------------------
            /// \brief equality operator for abstract data type
            ///
            /// \param[in] RHS
            ///     The object to be compared.
            ///
            /// \return
            ///     The value true is returned if this object is equivelent
            ///     to the RHS instance; false otherwise.
            //-----------------------------------------------------------------
            virtual bool
            operator==( const Common::FrameSpec::Object& RHS ) const;

        protected:
        private:
            //-----------------------------------------------------------------
            /// \brief Object with checksum data.
            //-----------------------------------------------------------------
            typedef ObjectWithChecksum< Common::FrStatData > object_type;

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

            //-----------------------------------------------------------------
            /// \brief Stream Constructor
            ///
            /// \param[in] Stream
            ///     The stream from which the object is being read.
            ///
            /// \return
            ///    A new instance of this object.
            //-----------------------------------------------------------------
            FrStatData( istream_type& Stream );
        };

        //===================================================================
        //===================================================================
        inline const char*
        FrStatData::StructName( )
        {
            static const char* name = "FrStatData";
            return name;
        }

        inline bool
        FrStatData::operator==( const FrStatData& RHS ) const
        {
            return (
                ( this == &RHS ) ||
                ( nps_type::operator==( RHS ) && ps_type::operator==( RHS ) ) );
        }
    } // namespace Universal
} // namespace FrameCPP

#endif /* 0 */

#endif /* FrameCPP_UNIVERSAL__IMPL__FrStatDataClassicIO_HH */
