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

#include <framecpp_config.h>

#include <boost/shared_ptr.hpp>

#include "framecpp/Common/IOStream.hh"
#include "framecpp/Common/Description.hh"
#include "framecpp/Common/SearchContainer.hh"
#include "framecpp/Common/FrameSpec.tcc"

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

#include "framecpp/Universal/FrRawData.hh"
#include "framecpp/Universal/FrSE.hh"
#include "framecpp/Universal/FrSH.hh"
#include "framecpp/Universal/PTR_STRUCT.hh"


using FrameCPP::Common::Description;
using FrameCPP::Common::FrameSpec;

//=======================================================================
// Static
//=======================================================================
//-----------------------------------------------------------------------
// Local functions and variables
//-----------------------------------------------------------------------

FR_OBJECT_META_DATA_DEFINE_UNIVERSAL( FrRawDataImpl,
                                      FSI_FR_RAW_DATA,
                                      "FrRawData",
                                      "Raw Data Structure" )

namespace FrameCPP
{
    namespace Universal
    {
        //=======================================================================
        // FrRawData
        //=======================================================================
        FrRawData::FrRawData( const std::string& Name )
        {
            Data::name = Name;
        }

        const FrRawData::name_type&
        FrRawData::GetName( ) const
        {
            return Data::GetName( );
        }
        bool
        FrRawData::operator==( const Common::FrameSpec::Object& Obj ) const
        {
            return FrameCPP::compare( *this, Obj );
        }

    } // namespace Universal
} // namespace FrameCPP

//=======================================================================
//               C L A S S I C   I O
//=======================================================================
namespace FrameCPP
{
    namespace Universal
    {
        namespace FrRawDataImpl
        {

            template <>
            const Common::Description*
            ClassicIO< FrRawData >::GetDescription( unsigned int frame_stream_version ) const
            {
                using Common::Description;

                Description* description{ nullptr };


                if ( frame_stream_version >= 8 )
                {
                    static Description v8_description;

                    if ( v8_description.size( ) == 0 )
                    {
                        //-----------------------------------------------
                        v8_description( FrSH( Data::StructName( ),
                                              Data::FrameSpecId( ),
                                              Data::FrameSpecDescription( ) ) );

                        v8_description(
                            FrSE( "name",
                                  Description::Ascii< io_name_type >( ),
                                  "Name of raw data." ) );
                        v8_description(
                            FrSE( "firstSer",
                                  PTR_STRUCT::Desc( FrSerData::StructName( ) ),
                                  "Identifier for first serial data structure "
                                  "in the linked list." ) );
                        v8_description(
                            FrSE( "firstAdc",
                                  PTR_STRUCT::Desc( FrAdcData::StructName( ) ),
                                  "Identifier for first ADC data structure in "
                                  "the linked list." ) );
                        v8_description(
                            FrSE( "firstTable",
                                  PTR_STRUCT::Desc( FrTable::StructName( ) ),
                                  "Identifier for first table structure in the "
                                  "linked list." ) );
                        v8_description(
                            FrSE( "logMsg",
                                  PTR_STRUCT::Desc( FrMsg::StructName( ) ),
                                  "Identifier for first error message "
                                  "structure in the linked list." ) );
                        v8_description(
                            FrSE( "more",
                                  PTR_STRUCT::Desc( FrVect::StructName( ) ),
                                  "Identifier for the additional user-defined "
                                  "data structures." ) );

                        v8_description( FrSE( "chkSum",
                                              CheckSumDataClass( ),
                                              CheckSumDataComment( ) ) );
                    }

                    description = &v8_description;
                }
                else if ( frame_stream_version >= 4 )
                {
                    static Description v4_description;

                    if ( v4_description.size( ) == 0 )
                    {
                        //-----------------------------------------------
                        v4_description( FrSH( Data::StructName( ),
                                              Data::FrameSpecId( ),
                                              Data::FrameSpecDescription( ) ) );

                        v4_description(
                            FrSE( "name",
                                  Description::Ascii< io_name_type >( ),
                                  "Name of raw data." ) );
                        v4_description(
                            FrSE( "firstSer",
                                  PTR_STRUCT::Desc( FrSerData::StructName( ) ),
                                  "Identifier for first serial data structure "
                                  "in the linked list." ) );
                        v4_description(
                            FrSE( "firstAdc",
                                  PTR_STRUCT::Desc( FrAdcData::StructName( ) ),
                                  "Identifier for first ADC data structure in "
                                  "the linked list." ) );
                        v4_description(
                            FrSE( "firstTable",
                                  PTR_STRUCT::Desc( FrTable::StructName( ) ),
                                  "Identifier for first table structure in the "
                                  "linked list." ) );
                        v4_description(
                            FrSE( "logMsg",
                                  PTR_STRUCT::Desc( FrMsg::StructName( ) ),
                                  "Identifier for first error message "
                                  "structure in the linked list." ) );
                        v4_description(
                            FrSE( "more",
                                  PTR_STRUCT::Desc( FrVect::StructName( ) ),
                                  "Identifier for the additional user-defined "
                                  "data structures." ) );
                    }

                    description = &v4_description;
                }
                else if ( frame_stream_version >= 3 )
                {
                    static Description v3_description;

                    if ( v3_description.size( ) == 0 )
                    {
                        //-----------------------------------------------
                        v3_description( FrSH( Data::StructName( ),
                                              Data::FrameSpecId( ),
                                              Data::FrameSpecDescription( ) ) );

                        v3_description(
                            FrSE( "name",
                                  Description::Ascii< io_name_type >( ),
                                  "Name of raw data." ) );
                        v3_description(
                            FrSE( "firstSer",
                                  PTR_STRUCT::Desc( FrSerData::StructName( ) ),
                                  "Identifier for first serial data structure "
                                  "in the linked list." ) );
                        v3_description(
                            FrSE( "firstAdc",
                                  PTR_STRUCT::Desc( FrAdcData::StructName( ) ),
                                  "Identifier for first ADC data structure in "
                                  "the linked list." ) );
                        v3_description(
                            FrSE( "logMsg",
                                  PTR_STRUCT::Desc( FrMsg::StructName( ) ),
                                  "Identifier for first error message "
                                  "structure in the linked list." ) );
                        v3_description(
                            FrSE( "more",
                                  PTR_STRUCT::Desc( FrVect::StructName( ) ),
                                  "Identifier for the additional user-defined "
                                  "data structures." ) );
                    }

                    description = &v3_description;
                }
                return description;
            }
        } // namespace FrRawDataImpl
    } // namespace Universal
} // namespace FrameCPP
