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

#include "ldastoolsal/Logger.hh"

// Forward declaration to avoid circular dependencies
namespace FrameCPP {
namespace Common {
    struct FrameCPPServices;
}
}

namespace FrameCPP
{
    namespace Universal
    {
        class FrTOCSerData;

        namespace FrTOCImpl
        {
            class FrTOCSerDataData
            {
            public:
                struct v4
                {
                    using n_type = INT_4U;
                    using name_type = std::string;
                    using position_type = INT_8U;

                    using info_type = std::vector< position_type >;
                    using MapSer_type = std::map< name_type, info_type >;
                    using key_container_type = std::vector< name_type >;
                };
                using v5 = v4;
                using v6 = v5;
                using v7 = v6;
                using v8 = v7;
                using v9 = v8;
                // ------------------------------------------------------
                using current_version = v9;
                // ------------------------------------------------------
                using n_type = current_version::n_type;
                using name_type = current_version::name_type;
                using position_type = current_version::position_type;

                using info_type = current_version::info_type;
                using MapSer_type = current_version::MapSer_type;
                using key_container_type = current_version::key_container_type;

                virtual ~FrTOCSerDataData( ) = default;

                const key_container_type&
                GetPositionKeys( ) const
                {
                    return m_keys;
                }

                //-----------------------------------------------------------------
                /// \brief Return all channels
                ///
                /// \return
                ///     Constant container to the indexed FrSerData elements.
                //-----------------------------------------------------------------
                inline const MapSer_type&
                GetSer( ) const
                {
                    return m_info;
                }

                //-----------------------------------------------------------------
                /// \brief Return the indexed data for a named channel.
                ///
                /// \param[in] Channel
                ///     The name of the channel.
                ///
                /// \return
                ///     Constant iterator to the indexed FrSerData element.
                //-----------------------------------------------------------------
                inline MapSer_type::const_iterator
                GetSer( const std::string& Channel ) const
                {
                    return m_info.find( Channel );
                }

                //-----------------------------------------------------------------
                /// \brief Return the indexed data for a named channel.
                ///
                /// \param[in] Channel
                ///     The numeric offset of the channel.
                ///
                /// \return
                ///     Constant iterator to the indexed FrSerData element.
                //-----------------------------------------------------------------
                inline MapSer_type::const_iterator
                GetSer( INT_4U Channel ) const
                {
                    if ( Channel >= m_info.size( ) )
                    {
                        return m_info.end( );
                    }
                    return m_info.find( m_keys[ Channel ] );
                }

                const FrTOCSerDataData&
                operator=( const FrTOCSerDataData& Source );

            protected:
                /// @brief Get the logger for FrTOCSerData debugging (static version)
                /// @return Static logger instance (thread-safe, lazy initialization)
                /// Moved to FrTOCSerData.cc to avoid ODR violations from function-local statics
                static SimpleLogger* logger();

                /// @brief Get the logger for FrTOCSerData debugging (dependency injection version)
                /// @param services Services context containing logger manager
                /// @return Logger instance from services context
                static SimpleLogger* logger(const FrameCPP::Common::FrameCPPServices& services);

                key_container_type m_keys;
                MapSer_type        m_info;
            };

        } // namespace FrTOCImpl
    } // namespace Universal
} // namespace FrameCPP

#endif /* FrameCPP_UNIVERSAL__IMPL__FrTOCSerDataData_HH */
