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

#ifndef FRAMECPP_UTILITIES_FR_SAMPLE_TEST_CONSTANTS_HH
#define FRAMECPP_UTILITIES_FR_SAMPLE_TEST_CONSTANTS_HH

#include <cmath>
#include "ldastoolsal/types.hh"

/// @file FrSampleTestConstants.hh
/// @brief Shared test constants for framecpp_sample and framel_sample utilities
///
/// @details This header defines all test parameters used when creating minimal
/// frame structures. By centralizing these constants, we ensure that both
/// FrameCPP and FrameL policies create IDENTICAL test structures that can be
/// verified for cross-library compatibility.
///
/// CRITICAL: All changes to test parameters must be made here to maintain
/// consistency between framecpp_sample and framel_sample outputs.

namespace FrameSampleCommon {
namespace TestConstants {

//=============================================================================
/// \name FrDetector Test Parameters
//=============================================================================
///@{

/// @brief Default detector name
constexpr const char* DETECTOR_NAME = "TestDetector";

/// @brief Detector prefix code
constexpr const char* DETECTOR_PREFIX = "TD";

/// @brief Detector longitude (degrees, minutes, seconds)
constexpr INT_2S DETECTOR_LONGITUDE_D = 0;
constexpr INT_2S DETECTOR_LONGITUDE_M = 0;
constexpr REAL_4 DETECTOR_LONGITUDE_S = 0.0f;

/// @brief Detector latitude (degrees, minutes, seconds)
constexpr INT_2S DETECTOR_LATITUDE_D = 0;
constexpr INT_2S DETECTOR_LATITUDE_M = 0;
constexpr REAL_4 DETECTOR_LATITUDE_S = 0.0f;

/// @brief Detector elevation (meters above WGS84 ellipsoid)
constexpr REAL_4 DETECTOR_ELEVATION = 0.0f;

/// @brief Detector arm orientations (radians East of North)
constexpr REAL_4 DETECTOR_ARM_X_AZIMUTH = 0.0f;
constexpr REAL_4 DETECTOR_ARM_Y_AZIMUTH = 0.0f;

/// @brief Detector arm altitudes (radians from horizontal)
constexpr REAL_4 DETECTOR_ARM_X_ALTITUDE = 0.0f;
constexpr REAL_4 DETECTOR_ARM_Y_ALTITUDE = 0.0f;

/// @brief Detector arm midpoints (meters from vertex)
constexpr REAL_4 DETECTOR_ARM_X_MIDPOINT = 0.0f;
constexpr REAL_4 DETECTOR_ARM_Y_MIDPOINT = 0.0f;

///@}

//=============================================================================
/// \name FrHistory Test Parameters
//=============================================================================
///@{

/// @brief History record name
constexpr const char* HISTORY_NAME = "TestFrame";

/// @brief Default history comment (overridden by --with-history-msg)
constexpr const char* HISTORY_COMMENT_FRAMECPP = "framecpp_sample test frame";
constexpr const char* HISTORY_COMMENT_FRAMEL = "framel_sample test frame";

///@}

//=============================================================================
/// \name FrAdcData Test Parameters
//=============================================================================
///@{

/// @brief ADC channel name
constexpr const char* ADC_CHANNEL_NAME = "H1:TEST_ADC";

/// @brief ADC channel group identifier
constexpr INT_4U ADC_CHANNEL_GROUP = 1;

/// @brief ADC channel number
constexpr INT_4U ADC_CHANNEL_NUMBER = 0;

/// @brief ADC number of bits (INT_2S = 16-bit)
constexpr INT_4U ADC_NBITS = 16;

/// @brief ADC number of samples
constexpr int ADC_NUM_SAMPLES = 100;

/// @brief ADC data pattern: ramp from 0 to 99
inline void fillAdcData(INT_2S* data, int nSamples) {
    for (int i = 0; i < nSamples; i++) {
        data[i] = static_cast<INT_2S>(i);
    }
}

/// @brief ADC calibration bias
constexpr double ADC_BIAS = 0.0;

/// @brief ADC calibration slope
constexpr double ADC_SLOPE = 1.0;

/// @brief ADC units
constexpr const char* ADC_UNITS = "counts";

/// @brief ADC frequency shift
constexpr double ADC_FSHIFT = 0.0;

/// @brief ADC time offset
constexpr double ADC_TIME_OFFSET = 0.0;

///@}

//=============================================================================
/// \name FrProcData Test Parameters
//=============================================================================
///@{

/// @brief Processed data channel name
constexpr const char* PROC_CHANNEL_NAME = "H1:TEST_PROC";

/// @brief Processed data comment
constexpr const char* PROC_COMMENT = "Test processed data for minimal frame";

/// @brief Processed data type (0 = unspecified)
constexpr INT_4U PROC_TYPE = 0;

/// @brief Processed data subtype (0 = unspecified)
constexpr INT_4U PROC_SUBTYPE = 0;

/// @brief Processed data number of samples
constexpr int PROC_NUM_SAMPLES = 50;

/// @brief Processed data pattern: sine wave, sin(i * 0.1)
inline void fillProcData(REAL_8* data, int nSamples) {
    for (int i = 0; i < nSamples; i++) {
        data[i] = std::sin(i * 0.1);
    }
}

/// @brief Processed data units
constexpr const char* PROC_UNITS = "strain";

/// @brief Processed data time offset
constexpr double PROC_TIME_OFFSET = 0.0;

/// @brief Processed data frequency shift
constexpr double PROC_FSHIFT = 0.0;

/// @brief Processed data phase
constexpr double PROC_PHASE = 0.0;

/// @brief Processed data frequency range
constexpr double PROC_FRANGE = 0.0;

/// @brief Processed data bandwidth
constexpr double PROC_BW = 0.0;

///@}

//=============================================================================
/// \name FrSimData Test Parameters
//=============================================================================
///@{

/// @brief Simulated data channel name
constexpr const char* SIM_CHANNEL_NAME = "H1:TEST_SIM";

/// @brief Simulated data comment
constexpr const char* SIM_COMMENT = "Test simulated data for minimal frame";

/// @brief Simulated data number of samples
constexpr int SIM_NUM_SAMPLES = 50;

/// @brief Simulated data pattern: cosine wave, cos(i * 0.1)
inline void fillSimData(REAL_4* data, int nSamples) {
    for (int i = 0; i < nSamples; i++) {
        data[i] = std::cos(i * 0.1f);
    }
}

/// @brief Simulated data units
constexpr const char* SIM_UNITS = "strain";

/// @brief Simulated data time offset
constexpr double SIM_TIME_OFFSET = 0.0;

/// @brief Simulated data frequency shift
constexpr double SIM_FSHIFT = 0.0;

/// @brief Simulated data phase
constexpr double SIM_PHASE = 0.0;

///@}

//=============================================================================
/// \name FrSerData Test Parameters
//=============================================================================
///@{

/// @brief Serial data channel name
constexpr const char* SER_CHANNEL_NAME = "H1:TEST_SER";

/// @brief Serial data number of samples
constexpr int SER_NUM_SAMPLES = 20;

/// @brief Serial data pattern: integer sequence 0-19
inline void fillSerData(INT_4U* data, int nSamples) {
    for (int i = 0; i < nSamples; i++) {
        data[i] = static_cast<INT_4U>(i);
    }
}

/// @brief Serial data units
constexpr const char* SER_UNITS = "counts";

///@}

//=============================================================================
/// \name FrEvent Test Parameters
//=============================================================================
///@{

/// @brief Event name
constexpr const char* EVENT_NAME = "TestEvent";

/// @brief Event comment
constexpr const char* EVENT_COMMENT = "Test event for minimal frame";

/// @brief Event input channel
constexpr const char* EVENT_INPUTS = "H1:TEST_CHANNEL";

/// @brief Event time before trigger (seconds)
constexpr double EVENT_TIME_BEFORE = 5.0;

/// @brief Event time after trigger (seconds)
constexpr double EVENT_TIME_AFTER = 10.0;

/// @brief Event status code
constexpr INT_4U EVENT_STATUS = 0;

/// @brief Event amplitude
constexpr REAL_4 EVENT_AMPLITUDE = 1.0f;

/// @brief Event probability
constexpr REAL_4 EVENT_PROBABILITY = 0.95f;

/// @brief Event statistics string (empty = not used)
constexpr const char* EVENT_STATISTICS = "";

/// @brief Event parameter name
constexpr const char* EVENT_PARAM_NAME = "test_param";

/// @brief Event parameter value
constexpr REAL_8 EVENT_PARAM_VALUE = 1.0;

///@}

//=============================================================================
/// \name FrSimEvent Test Parameters
//=============================================================================
///@{

/// @brief Simulated event name
constexpr const char* SIMEVENT_NAME = "TestSimEvent";

/// @brief Simulated event comment
constexpr const char* SIMEVENT_COMMENT = "Test simulated event";

/// @brief Simulated event input channel
constexpr const char* SIMEVENT_INPUTS = "H1:SIM_CHANNEL";

/// @brief Simulated event time before trigger (seconds)
constexpr double SIMEVENT_TIME_BEFORE = 10.0;

/// @brief Simulated event time after trigger (seconds)
constexpr double SIMEVENT_TIME_AFTER = 5.0;

/// @brief Simulated event amplitude
constexpr REAL_4 SIMEVENT_AMPLITUDE = 2.0f;

/// @brief Simulated event parameter name
constexpr const char* SIMEVENT_PARAM_NAME = "injection_scale";

/// @brief Simulated event parameter value
constexpr REAL_8 SIMEVENT_PARAM_VALUE = 1.0;

///@}

//=============================================================================
/// \name FrMsg Test Parameters
//=============================================================================
///@{

/// @brief Message alarm identifier
constexpr const char* MSG_ALARM = "TEST_ALARM";

/// @brief Message text
constexpr const char* MSG_MESSAGE = "Test message for minimal frame";

/// @brief Message severity level
constexpr REAL_4 MSG_SEVERITY = 3.0f;

///@}

//=============================================================================
/// \name FrSummary Test Parameters
//=============================================================================
///@{

/// @brief Summary data name
constexpr const char* SUMMARY_NAME = "TestSummary";

/// @brief Summary data comment
constexpr const char* SUMMARY_COMMENT = "Test summary for minimal frame";

/// @brief Summary statistical test name
constexpr const char* SUMMARY_TEST = "chi_squared";

///@}

//=============================================================================
/// \name FrTable Test Parameters
//=============================================================================
///@{

/// @brief Table name
constexpr const char* TABLE_NAME = "TestTable";

/// @brief Table comment
constexpr const char* TABLE_COMMENT = "Test table for minimal frame";

/// @brief Table number of rows
constexpr INT_4U TABLE_NROWS = 10;

/// @brief Table column 1 name (INT_4S data type)
constexpr const char* TABLE_COLUMN1_NAME = "Column1";

/// @brief Table column 1 data: ramp 0-9
inline void fillTableColumn1(INT_4S* data, int nSamples) {
    for (int i = 0; i < nSamples; i++) {
        data[i] = static_cast<INT_4S>(i);
    }
}

/// @brief Table column 1 units
constexpr const char* TABLE_COLUMN1_UNITS = "counts";

/// @brief Table column 2 name (REAL_4 data type)
constexpr const char* TABLE_COLUMN2_NAME = "Column2";

/// @brief Table column 2 data: constant 42.0
inline void fillTableColumn2(REAL_4* data, int nSamples) {
    for (int i = 0; i < nSamples; i++) {
        data[i] = 42.0f;
    }
}

/// @brief Table column 2 units
constexpr const char* TABLE_COLUMN2_UNITS = "value";

///@}

//=============================================================================
/// \name FrStatData Test Parameters
//=============================================================================
///@{

/// @brief Static data name
constexpr const char* STAT_NAME = "TestStatData";

/// @brief Static data comment
constexpr const char* STAT_COMMENT = "Test static data for minimal frame";

/// @brief Static data representation
constexpr const char* STAT_REPRESENTATION = "Test representation";

/// @brief Static data version
constexpr INT_4U STAT_VERSION = 1;

/// @brief Static data number of samples
constexpr int STAT_NUM_SAMPLES = 5;

/// @brief Static data pattern: constant 42.0
inline void fillStatData(REAL_4* data, int nSamples) {
    for (int i = 0; i < nSamples; i++) {
        data[i] = 42.0f;
    }
}

/// @brief Static data units
constexpr const char* STAT_UNITS = "units";

///@}

//=============================================================================
/// \name FrRawData Container Test Parameters
/// @brief For testing FrRawData container with multiple object types
//=============================================================================
///@{

// Container FrAdcData
constexpr const char* CONTAINER_ADC_NAME = "H1:CONTAINER_ADC";
constexpr int CONTAINER_ADC_NUM_SAMPLES = 50;
constexpr INT_4U CONTAINER_ADC_NBITS = 32; // REAL_4 is 32-bit
inline void fillContainerAdcData(REAL_4* data, int nSamples) {
    for (int i = 0; i < nSamples; i++) {
        data[i] = std::sin(i * 0.1f);
    }
}

// Container FrSerData
constexpr const char* CONTAINER_SER_NAME = "H1:CONTAINER_SER";
constexpr int CONTAINER_SER_NUM_SAMPLES = 10;
inline void fillContainerSerData(INT_4U* data, int nSamples) {
    for (int i = 0; i < nSamples; i++) {
        data[i] = static_cast<INT_4U>(i);
    }
}

// Container FrMsg
constexpr const char* CONTAINER_MSG_ALARM = "CONTAINER_TEST";
constexpr const char* CONTAINER_MSG_MESSAGE = "Container test";
constexpr REAL_4 CONTAINER_MSG_SEVERITY = 3.0f;

///@}

} // namespace TestConstants
} // namespace FrameSampleCommon

#endif // FRAMECPP_UTILITIES_FR_SAMPLE_TEST_CONSTANTS_HH
