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

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

#include "framecpp/Universal/FrameH.hh"
#include "framecpp/Universal/FrAdcData.hh"
#include "framecpp/Universal/FrDetector.hh"
#include "framecpp/Universal/FrEndOfFile.hh"
#include "framecpp/Universal/FrEndOfFrame.hh"
#include "framecpp/Universal/FrEvent.hh"
#include "framecpp/Universal/FrHeader.hh"
#include "framecpp/Universal/FrHistory.hh"
#include "framecpp/Universal/FrMsg.hh"
#include "framecpp/Universal/FrProcData.hh"
#include "framecpp/Universal/FrRawData.hh"
#include "framecpp/Universal/FrSerData.hh"
#include "framecpp/Universal/FrSimData.hh"
#include "framecpp/Universal/FrSimEvent.hh"
#include "framecpp/Universal/FrStatData.hh"
#include "framecpp/Universal/FrSummary.hh"
#include "framecpp/Universal/FrTable.hh"
#include "framecpp/Universal/FrTOC.hh"
#include "framecpp/Universal/FrVect.hh"

using FrameCPP::Universal::FrSE;
using FrameCPP::Universal::FrSH;
using FrameCPP::Universal::PTR_STRUCT;
using FrameCPP::Universal::StreamRef;

using FrameCPP::Universal::FrAdcData;
using FrameCPP::Universal::FrameH;
using FrameCPP::Universal::FrDetector;
using FrameCPP::Universal::FrEndOfFile;
using FrameCPP::Universal::FrEndOfFrame;
using FrameCPP::Universal::FrEvent;
using FrameCPP::Universal::FrHeader;
using FrameCPP::Universal::FrHistory;
using FrameCPP::Universal::FrMsg;
using FrameCPP::Universal::FrProcData;
using FrameCPP::Universal::FrRawData;
using FrameCPP::Universal::FrSerData;
using FrameCPP::Universal::FrSimData;
using FrameCPP::Universal::FrSimEvent;
using FrameCPP::Universal::FrStatData;
using FrameCPP::Universal::FrSummary;
using FrameCPP::Universal::FrTable;
using FrameCPP::Universal::FrTOC;
using FrameCPP::Universal::FrVect;

#include "framecpp/Version5/FrameSpec.hh"

namespace
{
    const FrameCPP::Common::DetectorNames&
    dnt_init( )
    {
        static FrameCPP::Common::DetectorNames retval;

        //-----------------------------------------------------------------
        // Setup the DetectorNameTable from the appendix
        //-----------------------------------------------------------------
        typedef std::pair< int, int > dqb;

        retval( "TAMA_300", "TAMA 300", "T1:", dqb( 0, 1 ) );
        retval(
            "Virgo_CITF", "Virgo Central Interferometer", "V1:", dqb( 2, 3 ) );
        retval( "Virgo", "Virgo 3 km", "V1:", dqb( 4, 5 ) );
        retval( "GEO_600", "GEO 600", "G1:", dqb( 6, 7 ) );
        retval( "LHO_2k", "LIGO LHO 2 km", "H2:", dqb( 8, 9 ) );
        retval( "LHO_4k", "LIGO LHO 4 km", "H1:", dqb( 10, 11 ) );
        retval( "LLO_4k", "LIGO LLO 4 km", "L1:", dqb( 12, 13 ) );
        retval( "CIT_40", "Caltech 40 meters", "P1:", dqb( 14, 15 ) );
        retval( "ALLEGRO_<theta>",
                "Allegro with <theta> degrees azimuth",
                "A1:",
                dqb( 16, 17 ) );
        retval( "AURIGA", "Auriga", "O1:", dqb( 18, 19 ) );
        retval.Freeze( );

        return retval;
    }
} // namespace

namespace FrameCPP
{
    namespace Version_5
    {
        const Common::DetectorNames& DetectorNameTable = dnt_init( );

        bool
        init_frame_spec( )
        {
            using Common::FrameSpec;

            static bool initialized = false;

            if ( !initialized )
            {
                //---------------------------------------------------------------
                // Local storage describing implementation of the frame spec
                //---------------------------------------------------------------
                std::unique_ptr< Common::FrameSpec::Info > info(
                    new Common::FrameSpec::Info( DATA_FORMAT_VERSION,
                                                 LIBRARY_MINOR_VERSION ) );

                info->FrameObject( new PTR_STRUCT );
                info->FrameObject( new StreamRef );

                info->FrameObject( new FrAdcData );
                info->FrameObject( new FrameH );
                info->FrameObject( new FrDetector );
                info->FrameObject( new FrEndOfFile );
                info->FrameObject( new FrEndOfFrame );
                info->FrameObject( new FrEvent );
                info->FrameObject( new FrHeader );
                info->FrameObject( new FrHistory );
                info->FrameObject( new FrMsg );
                info->FrameObject( new FrProcData );
                info->FrameObject( new FrRawData );
                info->FrameObject( new FrSE );
                info->FrameObject( new FrSerData );
                info->FrameObject( new FrSH );
                info->FrameObject( new FrSimData );
                info->FrameObject( new FrSimEvent );
                info->FrameObject( new FrStatData );
                info->FrameObject( new FrSummary );
                info->FrameObject( new FrTable );
                info->FrameObject( new FrTOC );
                info->FrameObject( new FrVect );

                //---------------------------------------------------------------
                // Register with the stream manipulator
                //---------------------------------------------------------------
                FrameSpec::SpecInfo(
                    FrameSpec::version_type( DATA_FORMAT_VERSION ),
                    info.release( ) );
                initialized = true;
            }
            return true;
        }

#ifndef SWIGIMPORTED
        extern const Common::DetectorNames& DetectorNameTable;
#endif /* SWIGIMPORTED */

    } // namespace Version_5
} // namespace FrameCPP
