#include <stdio.h>
#include <string.h>
#include <vector>
#include <iostream>
#include "htra_api.h"
#include "example.h"
using namespace std;

#define IS_USB 1 // Default is using USB device, if using Ethernet device, set IS_USB to 0.

int DETMode_EZStandard()
{
    int Status = 0;      // Return value of the function.
    void* Device = NULL; // Memory address of the current device.
    int DevNum = 0;      // Specify the device number.

    BootProfile_TypeDef BootProfile; // Boot configuration structure, including physical interface, power supply, etc.
    BootInfo_TypeDef BootInfo;       // Boot information structure, including device information, USB rate, etc.

    BootProfile.DevicePowerSupply = USBPortAndPowerPort; // Use USB data port and independent power port for dual power supply.

#if IS_USB==1
    // Configure USB interface
    BootProfile.PhysicalInterface = USB;
#else 
    // Configure ETH interface
    BootProfile.PhysicalInterface = ETH;
    BootProfile.ETH_IPVersion = IPv4;
    BootProfile.ETH_RemotePort = 5000;
    BootProfile.ETH_ReadTimeOut = 5000;
    BootProfile.ETH_IPAddress[0] = 192;
    BootProfile.ETH_IPAddress[1] = 168;
    BootProfile.ETH_IPAddress[2] = 1;
    BootProfile.ETH_IPAddress[3] = 100;
#endif

    Status = Device_Open(&Device, DevNum, &BootProfile, &BootInfo); // Open the device.

    Device_Open_ErrorHandling(Status, &Device, DevNum, &BootProfile, &BootInfo); // Handle errors when Status is not 0.

    DET_EZProfile_TypeDef DET_EZProfileIn;  // DET input configuration, including center frequency, decimation factor, reference level, etc.
    DET_EZProfile_TypeDef DET_EZProfileOut; // DET output configuration.
    DET_StreamInfo_TypeDef StreamInfo;      // DET data related information, including number of data points, byte size, etc.

    DET_EZProfileDeInit(&Device, &DET_EZProfileIn); // Initialize the parameters for configuring DET mode.

    DET_EZProfileIn.CenterFreq_Hz = 1e9;    // Configure center frequency.
    DET_EZProfileIn.RefLevel_dBm = 0;       // Configure reference level.
    DET_EZProfileIn.DecimateFactor = 2;     // Configure decimation factor.
    DET_EZProfileIn.TriggerMode = Adaptive; // Configure trigger mode.
    DET_EZProfileIn.TriggerSource = Bus;    // Configure trigger source as internal bus trigger
    DET_EZProfileIn.TriggerLength = 16243;  // Configure the number of points captured per trigger. Only valid in FixedPoints mode.

    Status = DET_EZConfiguration(&Device, &DET_EZProfileIn, &DET_EZProfileOut, &StreamInfo); // Apply DET configuration.

    if (Status==0)
    {
        cout << "Configuration applied successfully!" << endl;
    }
    else
    {
        cout << "Error in DET_EZConfiguration call, Status = " << Status << endl;
        Device_Close(&Device);
        return 0;
    }

    vector<float> NormalizedPowerStream(StreamInfo.PacketSamples); // Create power array.
    float ScaleToV = 0;                                            // This parameter is the scale factor for absolute amplitude (in volts).
    DET_TriggerInfo_TypeDef TriggerInfo;                           // Trigger information.
    MeasAuxInfo_TypeDef MeasAuxInfo;                               // Auxiliary information for measurement data, including max power index, max power, device temperature, GPS coordinates, timestamp, etc.

    bool tag = false; // When RTA_ProfileOut.TriggerMode = Adaptive, control the trigger once before fetching data.

    while (1)
    {
        if (DET_EZProfileOut.TriggerMode == Adaptive && tag != true) // Only trigger once when DET_EZProfileOut.TriggerMode = Adaptive.
        {
            Status = DET_BusTriggerStart(&Device);                   // Trigger the device using RTA_BusTriggerStart. No need to call this function if the trigger source is external.
            tag = true;
        }
        if (DET_EZProfileOut.TriggerMode == FixedPoints)            // Trigger every cycle when DET_EZProfileOut.TriggerMode = FixedPoints.
        {
            Status = DET_BusTriggerStart(&Device);                  // Trigger the device using RTA_BusTriggerStart. No need to call this function if the trigger source is external.
        }
        for (uint32_t i = 0; i < StreamInfo.PacketCount; i++)       // Only effective when TriggerMode is FixedPoints. When TriggerMode is Adaptive, StreamInfo.PacketCount will be 1.
        {

            Status = DET_GetPowerStream(&Device, NormalizedPowerStream.data(), &ScaleToV, &TriggerInfo, &MeasAuxInfo); // Fetch DET data and trigger info.

            if (Status == APIRETVAL_NoError)
            {
                // UserCode here
                /*

                // Convert DET data units to dBm
                for (int i = 0; i < StreamInfo.PacketSamples; i++)
                {
                    NormalizedPowerStream[i] = 10 * log10(20 * pow(NormalizedPowerStream[i] * ScaleToV, 2));
                }

                */
            }

            else
            {
                switch (Status)
                {
                    case APIRETVAL_WARNING_IFOverflow:
                        cout << "Warning - IF saturation detected. It is recommended to reconfigure with Reference Level <= Signal Power." << endl;
                        break;
                    case APIRETVAL_WARNING_ReconfigurationIsRecommended:
                        cout << "Warning - Significant temperature variation detected in the device. It is recommended to reconfigure the temperature settings." << endl;
                        break;
                    default:
                        cout << "Other error returned. Status = " << Status << endl;
                        Device_Close(&Device);
                        break;
                }
            }
        }
    }

    Status = DET_BusTriggerStop(&Device); // Stop triggering the device. No need to call this function if the trigger source is external.

    Device_Close(&Device); // Close the device.

    return 0;
}
