//
// 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 "framecpp/Universal/impl/FrameSpec.hh"

#include "framecpp/Universal/FrSummary.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( FrSummaryImpl,
                                      FSI_FR_SUMMARY,
                                      "FrSummary",
                                      "Summary Data Structure" )

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

        FrSummary::FrSummary( const name_type&    Name,
                              const comment_type& Comment,
                              const test_type&    Test,
                              const gtime_type&   GTime )
        {
            name = Name;
            comment = Comment;
            test = Test;
            gtime = GTime;
        }

        const FrSummary::name_type&
        FrSummary::GetName( ) const
        {
            return Data::GetName( );
        }

        FrSummary&
        FrSummary::Merge( const FrSummary& RHS )
        {
            /// \todo
            ///   Need to implement Merge routine
            std::string msg( "Merge currently not implemented for " );
            msg += StructName( );

            throw std::domain_error( msg );
            return *this;
        }

        bool
        FrSummary::operator==( const Common::FrameSpec::Object& RHS ) const
        {
            return FrameCPP::compare( *this, RHS );
        }
    } // namespace Universal
} // namespace FrameCPP

//=======================================================================
//               C L A S S I C   I O
//=======================================================================
namespace FrameCPP
{
    namespace Universal
    {
        namespace FrSummaryImpl
        {
            template <>
            const Common::Description*
            ClassicIO< FrSummary >::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 summary statistic." ) );
                        v8_description(
                            FrSE( "comment", //
                                  Description::Ascii< io_comment_type >( ), //
                                  "Comment." ) );
                        v8_description(
                            FrSE( "test", //
                                  Description::Ascii< io_name_type >( ), //
                                  "Statistical test(s) used on raw data." ) );
                        v8_description( FrSE(
                            "GTimeS", //
                            Description::Ascii< GPSTime::seconds_type >( ), //
                            "GPS time in seconds corresponding for this "
                            "FrSummary." ) );
                        v8_description(
                            FrSE( "GTimeN", //
                                  Description::Ascii<
                                      GPSTime::nanoseconds_type >( ), //
                                  "GPS time in residual nanoseconds relative "
                                  "to GTimeS." ) );

                        v8_description(
                            FrSE( "moments",
                                  PTR_STRUCT::Desc( FrVect::StructName( ) ), //
                                  "Identifier for vector containing "
                                  "statistical descriptors" ) );
                        v8_description(
                            FrSE( "table",
                                  PTR_STRUCT::Desc( FrTable::StructName( ) ),
                                  "Identifier for table structure containing "
                                  "additional summary information" ) );

                        v8_description( FrSE(
                            "next", PTR_STRUCT::Desc( Data::StructName( ) ) ) );

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

                    description = &v8_description;
                }
                else if ( frame_stream_version >= 5 )
                {
                    static Description v5_description;

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

                        v5_description(
                            FrSE( "name", //
                                  Description::Ascii< io_name_type >( ), //
                                  "Name of summary statistic." ) );
                        v5_description(
                            FrSE( "comment", //
                                  Description::Ascii< io_comment_type >( ), //
                                  "Comment." ) );
                        v5_description(
                            FrSE( "test", //
                                  Description::Ascii< io_name_type >( ), //
                                  "Statistical test(s) used on raw data." ) );
                        v5_description( FrSE(
                            "GTimeS", //
                            Description::Ascii< GPSTime::seconds_type >( ), //
                            "GPS time in seconds corresponding for this "
                            "FrSummary." ) );
                        v5_description(
                            FrSE( "GTimeN", //
                                  Description::Ascii<
                                      GPSTime::nanoseconds_type >( ), //
                                  "GPS time in residual nanoseconds relative "
                                  "to GTimeS." ) );

                        v5_description(
                            FrSE( "moments",
                                  PTR_STRUCT::Desc( FrVect::StructName( ) ), //
                                  "Identifier for vector containing "
                                  "statistical descriptors" ) );
                        v5_description(
                            FrSE( "table",
                                  PTR_STRUCT::Desc( FrTable::StructName( ) ),
                                  "Identifier for table structure containing "
                                  "additional summary information" ) );

                        v5_description( FrSE(
                            "next", PTR_STRUCT::Desc( Data::StructName( ) ) ) );
                    }

                    description = &v5_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 summary statistic." ) );
                        v4_description(
                            FrSE( "comment", //
                                  Description::Ascii< io_comment_type >( ), //
                                  "Comment." ) );
                        v4_description(
                            FrSE( "test", //
                                  Description::Ascii< io_name_type >( ), //
                                  "Statistical test(s) used on raw data." ) );

                        v4_description(
                            FrSE( "moments",
                                  PTR_STRUCT::Desc( FrVect::StructName( ) ), //
                                  "Identifier for vector containing "
                                  "statistical descriptors" ) );
                        v4_description(
                            FrSE( "table",
                                  PTR_STRUCT::Desc( FrTable::StructName( ) ),
                                  "Identifier for table structure containing "
                                  "additional summary information" ) );

                        v4_description( FrSE(
                            "next", PTR_STRUCT::Desc( Data::StructName( ) ) ) );
                    }

                    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 summary statistic." ) );
                        v3_description(
                            FrSE( "comment", //
                                  Description::Ascii< io_comment_type >( ), //
                                  "Comment." ) );
                        v3_description(
                            FrSE( "test", //
                                  Description::Ascii< io_name_type >( ), //
                                  "Statistical test(s) used on raw data." ) );

                        v3_description( //
                            FrSE( "moments",
                                  PTR_STRUCT::Desc( FrVect::StructName( ) ), //
                                  "Identifier for vector containing "
                                  "statistical descriptors" ) );

                        v3_description( FrSE(
                            "next", PTR_STRUCT::Desc( Data::StructName( ) ) ) );
                    }

                    description = &v3_description;
                }
                return description;
            }

        } // namespace FrSummaryImpl
    } // namespace Universal
} // namespace FrameCPP
