#ifndef H2_API_H
#define H2_API_H

#define Major_Version        2
#define Minor_Version        0
#define Increamental_Version 24

#define API_Version ((Major_Version << 16) | (Minor_Version << 8) | (Increamental_Version))

#include <stdint.h>
#include "h2_typedef.h"

#ifdef __cplusplus
extern "C" {
#endif

#if defined(_WIN32) || defined(__CYGWIN__)
  #ifdef H2_API_EXPORTS
    #define H2_API __declspec(dllexport)
  #else
    #define H2_API
  #endif
#else
  #ifdef H2_API_EXPORTS
    #if __GNUC__ >= 4
      #define H2_API __attribute__((visibility("default")))
    #else
      #define H2_API
    #endif
  #else
    #define H2_API
  #endif
#endif

/* ========================================================================== */
/* Device APIs                                                                */
/* ========================================================================== */

/**
 * @brief List the USB devices mounted on the host.
 *
 * @param[out] model      Returned USB Device Types
 * @param[out] uid_l64    Returned USB Device Low 64-bit ID
 * @param[out] uid_h32    Returned USB Device High 32-bit ID
 * @param[out] count      Total Number of Mounted USB Devices
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_list_usb(device_info* devInfo, uint32_t *count);

/**
 * @brief Force power supply through USB. This function must be called before device_open_usb().
 *
 * @param[in] dnum  USB device index
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_powered_by_usb(uint8_t dnum);

/**
 * @brief Forces an Ethernet device to use USB power. This API must be invoked before calling device_open_eth().
 *
 * @param[in] settings     eth device startup configuration
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_powered_by_eth(eth_setting settings);

/**
 * @brief Open the device and obtain channel information.
 *
 * @param[out] device      Returned Device Handle
 * @param[in]  boot        Device Boot Profile
 * @param[out] ch_o        Returned Channel Array
 * @param[out] chn         Returned Channel Count
 * @param[out] deviceInfo  	Returned Device Information
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_open_usb(void** device, uint8_t dnum, channel ch_o[], uint16_t* chn, device_info* dinfo);
//H2_API int device_open(void** device, BootSetting boot, channel ch_o[], uint16_t* chn, device_info* deviceInfo);

/**
 * @brief Open the eth device and obtain channel information.
 *
 * @param[in] device       Returned Device Handle
 * @param[in] settings     ethDevice Boot Profile
 * @param[out] ch_o        Returned Channel Array
 * @param[out] chn         Returned Channel Count
 * @param[out] dinfo       Returned Device Information
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_open_eth(void** device, eth_setting settings, channel ch_o[], uint16_t* chn, device_info* dinfo);

/**
 * @brief Close the device and release related resources.
 *
 * @param[in] device  Device Handle
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_close(void** device);

/**
 * @brief Device Reset (including full channel reset).
 *
 * @param[in] device  Device Handle
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_preset(void** device);

/**
 * @brief Query the current temperature of the device.
 *
 * @param[in]  device  Device Handle
 * @param[out] temp_o  Returned Device Temperature
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_query_temperature(void** device, float* temp_o);

/**
 * @brief Query the current state of the device.
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_query_state(void** device);

/**
 * @brief Set the fan configuration.
 *
 * @param[in]  device  Device Handle
 * @param[in]  mode    Fan Mode
 * @param[in]  auto_threshold  Temperature Threshold in Auto Mode
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_config_fan(void**device, fan_mode mode, float auto_threshold);

/**
 * @brief Set GPIO
 *
 * @param[in]  device  Device Handle
 * @param[in]  bits    GPIO I/O control: 16 GPIO pins are available. Set to 1 for high level and 0 for low level.
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_gpio_setbits(void** device, uint16_t bits);

/**
 * @brief Reset GPIO
 *
 * @param[in]  device  Device Handle
 * @param[in]  bits    GPIO I/O control: 16 GPIO pins are available. Set to 1 for high level and 0 for low level.
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_gpio_resetbits(void** device, uint16_t bits);

/**
 * @brief Query the current power supply information of the device.
 *
 * @param[in]  device  Device Handle
 * @param[out] supplyInfo_o  Returned Device Voltage & Current
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_query_supply(void** device, supply_info* supplyInfo_o);

/**
 * @brief Configure the GNSS parameters of the device.
 *
 * @param[in]  device      Device Handle
 * @param[in]  gnss        GNSS Configuration Parameters
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_config_gnss(void** device, gnss_setting gnss);

/**
 * @brief Query the current GNSS configuration of the device.
 *
 * @param[in]  device  Device Handle
 * @param[out] gnss_o  Returned Device GNSS Configuration
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_query_gnss(void** device, gnss_setting* gnss_o);


/**
 * @brief Query the current GNSS information of the device.
 *
 * @param[in]  device  Device Handle
 * @param[out] gnss_o  Returned Device GNSS Information
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int device_query_gnss_info(void** device, gnss_info* gnss_o);

/**
 * @brief 	Query the API version number.
 *
 * @return 	API Version Number
 */
H2_API uint32_t device_query_apiversion();

/**
 * @brief Configure the device reference clock.
 *
 * @param device        in,Device Handle
 * @param source        in,Reference Clock Source
 * @param fref          in,Reference Clock Frequency (Unit: Hz)
 * @param out           in,Reference Clock Output Switch Status
 *
 * @return Execution Status Code
 */
H2_API int device_config_clock(void** device, referenceclock_source source, double fref, state out);

/**
 * @brief Query the device reference clock configuration.
 *
 * @param device        in,Device Handle
 * @param source_o      out,Reference Clock Source
 * @param fref_o        out,Reference Clock Frequency (Unit: Hz)
 * @param out_o         out,Reference Clock Output Switch Status
 * @param locked_o      out,Clock Monitor Lock Status (After locking, the actual reference clock frequency can be obtained)
 *
 * @return Execution Status Code
 */
H2_API int device_query_clock(void** device, referenceclock_source* source_o, double* fref_o, state* out_o, state* locked_o);

/**
 * @brief Reset the clock monitor.
 *
 * @param[in] device Device Handle
 */
H2_API int device_reset_clock_monitor(void** device);

/**
 * @brief Query the status of licensed options.
 *
 * @param[in] device Device handle.
 * @param[out] opt_o Option array.
 * @param[out] num_o Number of active options.
 */
H2_API int device_query_options(void** device, uint32_t* opt_o, uint32_t* num_o);

/**
 * @brief Clear all waveform data in the device.
 *
 * @param[in] device  Device Handle
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_clear_waveform(void** device);

/**
 * @brief Download waveform data to the device.
 *
 * @param[in] device    Device Handle
 * @param[in] iq        IQ Data
 * @param[in] points    IQ Points
 * @param[out] waveform_o Waveform Sequence Number
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_download_waveform(void** device, int16_t iq[], uint32_t points, uint16_t* waveform_o);

/* ========================================================================== */
/* Channel APIs                                                               */
/* ========================================================================== */

/**
 * @brief Perform reset operation on multiple channels.
 *
 * @param[in] ch   Channel Array
 * @param[in] chn  Channel Count
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int channel_preset(channel* ch);
//H2_API int channel_preset_mc(channel ch[], int16_t chn);

/**
 * @brief Start multiple channels running.
 *
 * @param[in] ch   Channel Array
 * @param[in] chn  Channel Count
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int channel_start(channel* ch);
//H2_API int channel_start_mc(channel ch[], int16_t chn);

/**
 * @brief Stop multiple channels running.
 *
 * @param[in] ch   Channel Array
 * @param[in] chn  Channel Count
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int channel_stop(channel* ch);
//H2_API int channel_stop_mc(channel ch[], int16_t chn);

/**
 * @brief Initiate a single bus trigger for multiple channels.
 *
 * @param[in] ch   Channel Array
 * @param[in] chn  Channel Count
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int channel_trigger_bus(channel* ch);
//H2_API int channel_trigger_bus_mc(channel ch[], int16_t chn);


/* ========================================================================== */
/* TX APIs                                                                    */
/* ========================================================================== */

/**
 * @brief Configure the frequency and amplitude parameters (FFM) of the channel.
 *
 * @param[in] ch     Target Channel
 * @param[in] fc     Center Frequency
 * @param[in] level  Output Amplitude
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_config_ffm(channel* ch, double fc, float level);

/**
 * @brief Query the frequency and amplitude parameters (FFM) of the channel.
 *
 * @param[in]  ch       Target Channel
 * @param[out] fc_o     Returned Center Frequency
 * @param[out] level_o  Returned Output Amplitude
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_query_ffm(channel* ch, double* fc_o, float* level_o);

/**
 * @brief Configure the frequency sweep parameters (FSCAN) of the channel.
 *
 * At a fixed power level, increase the frequency from start to stop with step as the increment.
 *
 * @param[in] ch      Target Channel
 * @param[in] start   Sweep Start Frequency
 * @param[in] stop    Sweep Stop Frequency
 * @param[in] step    Sweep Step Frequency
 * @param[in] level   Output Amplitude
 * @param[in] dwell   Dwell Time per Frequency Point (s)
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_config_fscan(channel* ch, double start, double stop, double step, float level, float dwell);

/**
 * @brief Validate whether the frequency scan parameters (FSCAN) of a test channel meet the constraints. This is used for parameter limit preview during HMI/UI development.
 *
 * At a fixed output power level, the frequency is swept from start to stop with step increments.
 *
 * @param[in] ch         Target channel
 * @param[inout] start   Start frequency of the sweep
 * @param[inout] stop    Stop frequency of the sweep
 * @param[inout] step    Frequency step size
 * @param[inout] level   Output amplitude
 * @param[inout] dwell   Dwell time per frequency point (seconds)
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_test_fscan(channel* ch, double* start, double* stop, double* step, float* level, float* dwell);

/**
 * @brief Query the frequency sweep parameters (FSCAN) of the channel.
 *
 * @param[in]  ch       Target Channel
 * @param[out] start_o  Returned Sweep Start Frequency
 * @param[out] stop_o   Returned weep Stop Frequency
 * @param[out] step_o   Returned Sweep Step Frequency
 * @param[out] level_o  Returned Output Amplitude
 * @param[out] dwell_o  Returned Dwell Time per Frequency Point (s)
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_query_fscan(channel* ch, double* start_o, double* stop_o, double* step_o, float* level_o, float* dwell_o);

/**
 * @brief Configure the amplitude sweep parameters (LSCAN) of the channel.
 *
 * At a fixed center frequency fc, increase the amplitude from level_start to level_stop with level_step as the increment.
 *
 * @param[in] ch            Target Channel
 * @param[in] fc            Center Frequency
 * @param[in] level_start   Sweep Start Amplitude
 * @param[in] level_stop    Sweep Stop Amplitude
 * @param[in] level_step    Sweep Step Amplitude
 * @param[in] dwell         Dwell Time per Amplitude Point (s)
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_config_lscan(channel* ch, double fc, float level_start, float level_stop, float level_step, float dwell);

/**
 * @brief Validate whether the amplitude scan parameters (LSCAN) of a test channel meet the constraints. This is used for parameter limit preview during HMI/UI development.
 *
 * At a fixed center frequency (fc), the amplitude is swept from level_start to level_stop with level_step increments.
 *
 * @param[in] ch               Target Channel
 * @param[inout] fc            Center Frequency
 * @param[inout] level_start   Sweep Start Amplitude
 * @param[inout] level_stop    Sweep Stop Amplitude
 * @param[inout] level_step    Sweep Step Amplitude
 * @param[inout] dwell         Dwell Time per Amplitude Point (s)
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_test_lscan(channel* ch, double* fc, float* level_start, float* level_stop, float* level_step, float* dwell);

/**
 * @brief Query the amplitude sweep parameters (LSCAN) of the channel.
 *
 * @param[in]  ch              Target Channel
 * @param[out] fc_o            Returned	Center Frequency
 * @param[out] level_start_o   Returned Sweep Start Amplitude
 * @param[out] level_stop_o    Returned Sweep Stop Amplitude
 * @param[out] level_step_o    Returned Sweep Step Amplitude
 * @param[out] dwell_o         Returned Dwell Time per Amplitude Point (s)
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_query_lscan(channel* ch, double* fc_o, float* level_start_o, float* level_stop_o, float* level_step_o, float* dwell_o);

/**
 * @brief Configure the multi-point sweep parameters (MSCAN) of the channel.
 *
 * Scan sequentially from point 0 to point n-1 in array index order, using the corresponding fc[i] and level[i] for each point.
 *
 * @param[in] ch       Target Channel
 * @param[in] fc       Frequency Array, length n
 * @param[in] level    Amplitude Array, length n
 * @param[in] dwell    Dwell Time Array (s), length n
 * @param[in] n        Number of Sweep Points
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_config_mscan(channel* ch, const double fc[], const float level[], const float dwell[], int16_t n);

/**
 * @brief Validate whether the multi-point scan parameters (MSCAN) of a test channel meet the constraints. This is used for parameter limit preview during HMI/UI development.
 *
 * The scan is performed sequentially by array index, from point 0 to point n-1.
 * Each point uses the corresponding fc[i] and level[i].
 *
 * @param[in] ch          Target Channel
 * @param[inout] fc       Frequency array, length n
 * @param[inout] level    Amplitude array, length n
 * @param[inout] dwell    Dwell time array (seconds), length n
 * @param[inout] n        Number of scan points
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_test_mscan(channel* ch, double fc[], float level[], float dwell[], int16_t* n);

/**
 * @brief Query the multi-point sweep parameters (MSCAN) of the channel.
 *
 * Return the currently configured sweep sequence in array index order.
 *
 * @param[in]  ch       Target Channel
 * @param[out] fc_o     Returned Frequency Array, length n
 * @param[out] level_o  Returned Amplitude Array, length n
 * @param[out] dwell_o  Returned Dwell Time Array (s), length n
 * @param[in]  n        Number of Sweep Points
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_query_mscan(channel* ch, double fc_o[], float level_o[], float dwell_o[], int16_t* n);

/**
 * @brief Configure the channel trigger parameters.
 *
 * @param[in] ch   Target Channel
 * @param[in] trg  Trigger Configuration Parameters
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int channel_config_trigger(channel* ch, const tx_trigger* trg);

/**
 * @brief Query the channel trigger configuration.
 *
 * @param[in]  ch     Target Channel
 * @param[out] trg_o  Returned Trigger Configuration
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int channel_query_trigger(channel* ch, tx_trigger* trg_o);

/**
 * @brief 	Configure the channel trigger output parameters.
 *
 * @param[in] ch   Target Channel
 * @param[in] trg  Trigger Output Configuration Parameters
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int channel_config_trigger_out(channel* ch, const trigger_out* trg);

/**
 * @brief Query the channel trigger output configuration.
 *
 * @param[in]  ch     Target Channel
 * @param[out] trg_o  Returned Trigger Output Configuration
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int channel_query_trigger_out(channel* ch, trigger_out* trg_o);

/**
 * @brief Configure the channel LO mode.
 *
 * @param[in] ch       Target Channel
 * @param[in] lomode   LO Mode Configuration
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int channel_config_lo_mode(channel* ch, lomode mode); 

/**
 * @brief Query the channel LO mode.
 *
 * @param[in]  ch         Target Channel
 * @param[out] loMode_o   Returned LO Mode Configuration
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int channel_query_lo_mode(channel* ch, lomode* mode_o);

/**
 * @brief Configure the RF output port.
 *
 * @param[in] device Channel handle.
 * @param[in] port Port number: 0 - Standard output port, 1 - High-power output port
 */
H2_API int channel_config_port(channel* ch, uint16_t port);

/**
 * @brief Query the RF output port.
 *
 * @param[in] device Channel handle.
 * @param[out] port_o Port number: 0 - Standard output port, 1 - High-power output port
 */
H2_API int channel_query_port(channel* ch, uint16_t* port_o);

/**
 * @brief Configure the output state (RFOUT / MOD) of multiple channels.
 *
 * @param[in] ch     Channel Array
 * @param[in] rfout  RF Output Configuration
 * @param[in] mod    Modulation Output Configuration
 * @param[in] chn    Channel Count
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_config_output(channel* ch, state rfout, state mod);

/**
 * @brief Query the output state (RFOUT / MOD) of multiple channels.
 *
 * @param[in]  ch        Channel Array
 * @param[out] rfout_o   Returned RF Output State
 * @param[out] mod_o     Returned Modulation Output State
 * @param[in]  chn       Channel Count
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_query_output(channel* ch, state* rfout_o, state* mod_o);
//H2_API int tx_query_output_mc(channel ch[], int8_t* rfout_o, int8_t* mod_o, int16_t chn);

/**
 * @brief Send Continuous Wave (CW) on multiple channels.
 *
 * @param[in] ch   Channel Array
 * @param[in] chn  Channel Count
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_config_cw(channel* ch);
//H2_API int tx_config_cw_mc(channel ch[], int16_t chn);

/**
 * @brief Configure the stream playback parameters for the specified channel.
 *
 * @param[in] ch          Specified Channel
 * @param[in] sample_rate Sample Rate
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_config_stream(channel* ch, double sample_rate);

/**
 * @brief Send IQ stream for real-time playback to the specified channel.
 *
 * @param[in] ch          Specified Channel
 * @param[in] iq          IQ Data
 * @param[in] points      IQ Points
 *
 * @return 0 Success, Non-0 Fail
 */H2_API int tx_send_stream(channel* ch, int16_t iq[], uint32_t points);

/**
 * @brief Configure the waveform playback parameters for the specified channel.
 *
 * @param[in] ch        Target Channel
 * @param[in] waveform  Waveform Index Array
 * @param[in] repeat    Loop Playback Count
 * @param[in] sample_rate SampleRate Array
 * @param[in] waveforms   Number of Waveforms to Play
 *
 * @return 0 Success, Non-0 Fail
 */
H2_API int tx_config_playback(channel* ch, const int16_t waveform[], const int32_t repeat[], const double sample_rate[], int16_t waveforms);

/**
 * @brief Convert Unix Epoch nanosecond timestamp to readable UTC time.
 *
 * @param[in]  ns_sinceepoch  Time elapsed since Epoch, unit: ns
 * @param[out] year  Year (e.g., 2026)
 * @param[out] mon   Month (1 ~ 12)
 * @param[out] day   Day (1 ~ 31)
 * @param[out] hour  Hour (0 ~ 23)
 * @param[out] min   Minute (0 ~ 59)
 * @param[out] sec   Second (0 ~ 59)
 * @param[out] ms    Millisecond (0 ~ 999)
 * @param[out] us    Microsecond (0 ~ 999)
 * @param[out] ns    Nanosecond (0 ~ 999)
 */
H2_API void device_epoch_to_utc(uint64_t ns_sinceepoch, int16_t* year, int16_t* mon, int16_t* day, int16_t* hour, int16_t* min, int16_t* sec, int16_t* ms, int16_t* us, int16_t* ns);


#ifdef __cplusplus
}
#endif

#endif /* H2_API_H */
