//
// 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/FrEvent.hh"

#include "framecppc/FrameH.h"
#include "framecppc/FrEvent.h"

#include "FrameCInternal.hh"
#include "FrEventInternal.hh"

using FrameC::Set;

namespace FrameC
{
    template <>
    const char*
    Pointers::Name< POINTER_FR_EVENT >( )
    {
        return "FrEvent";
    }

} // namespace FrameC

fr_event_t*
FrameCFrEventAlloc( FrameCError**                 Error,
                    const fr_event_name_t         Name,
                    const fr_event_comment_t      Comment,
                    const fr_event_inputs_t       Inputs,
                    const fr_event_gtime_t        GTime,
                    const fr_event_time_before_t  TimeBefore,
                    const fr_event_time_after_t   TimeAfter,
                    const fr_event_event_status_t EventStatus,
                    const fr_event_amplitude_t    Amplitude,
                    const fr_event_probability_t  Probability,
                    const fr_event_statistics_t   Statistics,
                    const fr_event_n_param_t      NParam,
                    const fr_event_parameters_t*  Parameters )
{
    Set( Error );

    FrameC::FrEvent*                   retval = (FrameC::FrEvent*)NULL;
    std::unique_ptr< FrameC::FrEvent > tmp;

    try
    {
        tmp.reset( new FrameC::FrEvent( Name,
                                        Comment,
                                        Inputs,
                                        GTime,
                                        TimeBefore,
                                        TimeAfter,
                                        EventStatus,
                                        Amplitude,
                                        Probability,
                                        Statistics,
                                        NParam,
                                        Parameters ) );
    }
    catch ( const std::exception& Exception )
    {
        Set( Error, FRAMEC_ERRNO_FR_EVENT_ALLOC_ERROR, Exception.what( ) );
        tmp.reset( (FrameC::FrEvent*)NULL );
    }

    if ( tmp.get( ) )
    {
        FrameC::Handle::Deposit( tmp.get( ) );
        retval = tmp.release( );
    }
    return ( reinterpret_cast< fr_event_t* >( retval ) );
}

int
FrameCFrEventFree( FrameCError** Error, fr_event_t* Event )
{
    int retval = true;

    Set( Error );

    FrameC::Handle::Free( Error,
                          Event,
                          FrameC::POINTER_FR_EVENT,
                          FRAMEC_ERRNO_FR_EVENT_FREE_ERROR );

    if ( *Error )
    {
        retval = false;
    }

    return retval;
}

namespace FrameC
{
    FrEvent::FrEvent( ) : Handle( POINTER_FR_EVENT )
    {
    }

    FrEvent::FrEvent( const fr_event_name_t         Name,
                      const fr_event_comment_t      Comment,
                      const fr_event_inputs_t       Inputs,
                      const fr_event_gtime_t        GTime,
                      const fr_event_time_before_t  TimeBefore,
                      const fr_event_time_after_t   TimeAfter,
                      const fr_event_event_status_t EventStatus,
                      const fr_event_amplitude_t    Amplitude,
                      const fr_event_probability_t  Probability,
                      const fr_event_statistics_t   Statistics,
                      const fr_event_n_param_t      NParam,
                      const fr_event_parameters_t*  Parameters )
        : Handle( POINTER_FR_EVENT )
    {
        FrameCPP::FrEvent::ParamList_type params;
        FrameCPP::FrEvent::time_type      gtime( GTime.sec, GTime.nan );

        for ( fr_event_n_param_t cur = 0, last = NParam; cur != last; ++cur )
        {
            params.push_back( FrameCPP::FrEvent::Param_type(
                Parameters[ cur ].s_parameter_name,
                Parameters[ cur ].s_parameter ) );
        }
        m_data.reset( new FrameCPP::FrEvent( Name,
                                             Comment,
                                             Inputs,
                                             gtime,
                                             TimeBefore,
                                             TimeAfter,
                                             EventStatus,
                                             Amplitude,
                                             Probability,
                                             Statistics,
                                             params ) );
    }
} // namespace FrameC
