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

#if !defined( SWIGIMPORTED )
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/version.hpp>

#include "framecpp/Common/FrameSpec.hh"
#include "framecpp/Universal/impl/HelperSerialIO.hh"
#include "framecpp/Universal/impl/FrObjectMetaData.hh"
#endif /* !defined( SWIGIMPORTED ) */

#if !defined( SWIGIMPORTED )
namespace FrameCPP
{
    namespace Universal
    {
        /// \brief Serialization I/O implementation for FrObject base template
        ///
        /// This class provides versioned serialization support for FrObject
        /// template instances using Boost.Serialization. It serves as a base
        /// serialization interface for frame objects that handles common
        /// metadata and versioning functionality.
        ///
        /// \tparam FR_OBJECT_T The FrObject template type being serialized
        template < typename FR_OBJECT_T >
        class FrObjectSerialIO : public FR_OBJECT_T
        {
        public:
            /// \brief Default constructor
            ///
            /// Constructs an empty SerialIO object ready for serialization
            /// operations. The object inherits from the FrObject template
            /// type provided.
            FrObjectSerialIO( ) : FR_OBJECT_T( )
            {
            }

        private:
            friend class boost::serialization::access;

            /// \brief Serialize FrObject data to an archive
            ///
            /// This method saves the FrObject data to a serialization archive.
            /// Since FrObject is primarily a template base class that provides
            /// common functionality, it has minimal direct data to serialize.
            ///
            /// \tparam Archive The Boost.Serialization archive type
            ///
            /// \param[in,out] ar The archive to write data to
            /// \param[in] version The target serialization version (3-9)
            ///
            /// \throws boost::archive::archive_exception on serialization
            /// errors
            ///
            /// Version-specific handling:
            /// - v3+: All versions supported (base template functionality)
            /// - Pre-v3: Not supported
            ///
            /// \note FrObject provides template base functionality
            /// \note Actual data serialization handled by derived classes
            template < class Archive >
            void
            save( Archive& ar, const unsigned int version ) const
            {
                using boost::serialization::make_nvp;

                if ( version >= 3 )
                {
                    // FrObject template base class is primarily structural
                    // The actual object data is handled by the specific
                    // SerialIO classes for each frame object type
                    
                    // Placeholder for any future FrObject-specific metadata
                    // that might need to be serialized across all frame objects
                }
            }

            /// \brief Deserialize FrObject data from an archive
            ///
            /// This method loads FrObject data from a serialization archive.
            /// Since FrObject is primarily a template base class that provides
            /// common functionality, it has minimal direct data to deserialize.
            ///
            /// \tparam Archive The Boost.Serialization archive type
            ///
            /// \param[in,out] ar The archive to read data from
            /// \param[in] version The source serialization version (3-9)
            ///
            /// \throws boost::archive::archive_exception on deserialization
            /// errors
            ///
            /// Version-specific handling:
            /// - v3+: All versions supported (base template functionality)
            /// - Pre-v3: Initialize with default values
            ///
            /// \note FrObject provides template base functionality
            /// \note Actual data deserialization handled by derived classes
            ///
            /// \warning The caller must ensure the archive contains valid
            /// FrObject data
            template < class Archive >
            void
            load( Archive& ar, const unsigned int version )
            {
                using boost::serialization::make_nvp;

                if ( version >= 3 )
                {
                    // FrObject template base class is primarily structural
                    // The actual object data is handled by the specific
                    // SerialIO classes for each frame object type
                    
                    // Placeholder for any future FrObject-specific metadata
                    // that might need to be deserialized across all frame objects
                }
                else
                {
                    // Pre-v3: Initialize with default values
                    // No specific data to initialize for FrObject base template
                }
            }

            /// \brief Boost.Serialization split member macro
            ///
            /// This macro splits the serialize() method into separate
            /// save() and load() methods, allowing for different logic
            /// during serialization and deserialization. This maintains
            /// consistency with other SerialIO implementations.
            BOOST_SERIALIZATION_SPLIT_MEMBER( )
        };

    } // namespace Universal
} // namespace FrameCPP

/// \brief Specify the class version for Boost.Serialization
///
/// This macro tells Boost.Serialization that FrObjectMetaData is at version 9,
/// which corresponds to the v9 frame specification. The serialization framework
/// uses this version number to determine how to serialize/deserialize the data.
///
/// \note This version number is passed to the save() and load() methods
BOOST_CLASS_VERSION( FrameCPP::Universal::Impl::FrObjectMetaData< void >, 9 )

#endif /* !defined( SWIGIMPORTED ) */

#endif /* FrameCPP_UNIVERSAL__IMPL__FrObjectSerialIO_HH */