#pragma once

extern "C"
{
#define DLL_FUNC __declspec(dllimport)

  enum PHASETYPE
  {
    PT_MERTZ = 1,
    PT_FORMAN = 2,
    PT_FORMANRES = 3
  };

  enum APODTYPE
  {
    APOD_NONE = 0,
    APOD_BOXCAR = APOD_NONE,
    APOD_TRIANGULAR = 1,
    APOD_WEAKNORTONBEER = 2,
    APOD_MEDIUMNORTONBEER = 3,
    APOD_STRONGNORTONBEER = 4,
    APOD_HAPPGENZEL = 5,
    APOD_BESSEL = 6,
    APOD_COSINE = 7,
    APOD_HANNING = APOD_COSINE,
  };

  enum FTIR_STATE
  {
    FTIR_Init = 0,
    FTIR_Collecting = 1,
    FTIR_DataReady = 2,
    FTIR_Aborting = 3,
    FTIR_Error = 4,
  };

  enum PHASEPOINTS
  {
    PP_128 = 128,
    PP_256 = 256,
    PP_512 = 512,
    PP_1024 = 1024
  };

  enum OFFSETCORRECTTYPE
  {
    OT_NONE = 0,
    OT_ALL = 1,
    OT_ENDS = 2
  };

  enum ZFFTYPE
  {
    ZFF_NONE = 0,
    ZFF_2 = 1,
    ZFF_4 = 2,
    ZFF_8 = 3,
    ZFF_16 = 4
  };

  enum SAMPLINGTECHNOLOGYTYPE
  {
    ST_NONE = 0,
    ST_ATRSINGLE = -1,
    ST_ATRTRIPLE = -3,
    ST_ATRNINEBOUNCE = -9,
    ST_TRANSMISSIONCELL = 1,
    ST_GASCELL = 2,
    ST_REFLECTANCE = 3,
  };

  enum ML_INSTRUMENT_TYPE
  {
    eInstrumentType_Undefined = 0,
    eInstrumentType_ML = 1,
    eInstrumentType_MLP = 2,
    eInstrumentType_MLX = 3,
    eInstrumentType_Exoscan = 4,
  };

  enum DATAXTYPE
  {
    XT_ARB = 0,
    XT_WN = 1,
    XT_uM = 2,
    XT_nM = 3,
    XT_Seconds = 4,
    XT_Minutes = 5,
    XT_MassCharge = 9,
    XT_RAMSHFT = 13,
    XT_Points = 22,
    XT_Hours = 30,
    XT_AMU = 50,
    XT_Custom = 51
  };

  enum DATAYTYPE
  {
    YT_ARB = 0,
    YT_IGRAM = 1,
    YT_Abs = 2,
    YT_Percent = 11,
    YT_Intensity = 12,
    YT_RelAbundance = 13,
    YT_Trans = 128,
    YT_Refl = 129,
    YT_Custom = 51,
    YT_Abundance = 52,
  };

  enum REJECTREASON
  {
    RR_GOOD = 0,
    RR_20PCT = 0x00010004,
    RR_CENTERBURST = 0x00010005,
    RR_HW_UNSTABLE = 0x00010010
  };

  struct _instrumentMLDiag
  {
    int nVersion;       // struct version (100 to 102)
    int nEnergyStatus;  // Height of Center burst
    int nLaserStatus;
    int numTemps;
    int nBatteryMinutes;
    int nBatteryPct;
    int nBatteryState;  // bits: 1=connected, 2=ac connected,
                        // 4=charging, 16=fully charged
    float fSourceCurrentStatus;
    float fSourceVoltageStatus;
    float fSpare;
    float fTempCPU;       // Cpu board temperature
    float fTempPower;     // Power board temperature
    float fTempIR;        // IR board temperature
    float fTempDetector;  // Detector temperature
                          // MLDiag 102+
    int nSystemStatus;    // System Status
    int nShutdownReason;  // System Shutdown Reason
  };

  struct _instrumentMLVersion
  {
    int nVersion;            // struct version (100 to 103)
    int fwRev;               // firmware rev
    int dllRev;              // dll rev
    int nReserved0;          // reserved; return value is undefined
    int instrType;           // ML_INSTRUMENT_TYPE enum value
    int sampleTechType;      // negative ==> ATR
    int atrType;             // 1, 3, 9 (for ATR type sampleTechs)
    int spare;               // always returned as 0
    double dLaserWN;         // in WN
    double dBasePathLength;  // Transmission/gascell sampleTechs in mm
    double dAdjPathLength;   // Transmission/gascell sampleTechs in mm
                             // MLVersion 101+
                             // Serial number (in WCHAR-compatible format)
    short serialNo01;
    short serialNo02;
    short serialNo03;
    short serialNo04;
    short serialNo05;
    short serialNo06;
    short serialNo07;
    short serialNo08;
    short serialNo09;
    short serialNo10;
    short serialNo11;
    short serialNo12;
    short serialNo13;
    short serialNo14;
    short serialNo15;
    short serialNo16;
    short serialNo17;
    // MLVersion 102+
    int nCpuBrdRev;
    int nPwrBrdRev;
    int nIrBrdRev;
    int nLasBrdRev;
    // MLVersion 103+
    int nUpdFwRev;
    int nBootloaderFwRev;
    int nFpgaRev;
  };

  struct _progress
  {
    int nStructSize;  // size bytes of struct (initially = 28)
    FTIR_STATE state;
    int currentUnits;
    int totalUnits;
    int recentRejected;
    int rejectReason;    // reason, or Good if the last scan good
    int numRejectsSame;  // num consec rejects w same rejectReason
  };

  struct MLSyncdVals
  {
    int nVersion;  // struct version; currently 101
    int bBlockTempValid;
    float fBlockTemp;
    float fAdjustedLaserFreq;
    int nAdjustEnabled;
    int nLaserStandardizationType;
  };

  DLL_FUNC long FTIRInst_SetTargetDeviceUsb(wchar_t* pDeviceName);
  DLL_FUNC long FTIRInst_SetTargetDeviceSerialPort(long nPort);
  DLL_FUNC long FTIRInst_SetTargetDeviceNetwork(wchar_t* pDeviceName);
  DLL_FUNC long FTIRInst_Init();
  DLL_FUNC long FTIRInst_Deinit();
  DLL_FUNC long FTIRInst_SetComputeParams(PHASEPOINTS ppoints, PHASETYPE ptype,
    APODTYPE papod, APODTYPE iapod, ZFFTYPE zff, OFFSETCORRECTTYPE offset);
  DLL_FUNC long FTIRInst_dptrStartSingleBeam(long numScans, double* from,
    double* to, long res, long bAutoSetBkg, long bAutoSetClean);
  DLL_FUNC long FTIRInst_dptrStartSpectrum(long numScans, double* from,
    double* to, long res, DATAXTYPE xtype, DATAYTYPE ytype,
    long bAutoSetUnknown);
  DLL_FUNC long FTIRInst_dptrGetLiveSpectrum(double* from, double* to, long res,
    DATAXTYPE xtype, DATAYTYPE ytype, double* buffer, long size,
    double* actualFrom, double* actualTo, long* actualRes);

  DLL_FUNC long FTIRInst_dptrGetSingleBeam(double* buffer, long size,
    double* actualFrom, double* actualTo, long* actualRes);
  DLL_FUNC long FTIRInst_dptrGetBackground(double* buffer, long size,
    double* actualFrom, double* actualTo, long* actualRes);
  DLL_FUNC long FTIRInst_dptrGetClean(double* buffer, long size,
    double* actualFrom, double* actualTo, long* actualRes);
  DLL_FUNC long FTIRInst_dptrGetSpectrum(double* buffer, long size,
    double* actualFrom, double* actualTo, long* actualRes);
  DLL_FUNC long FTIRInst_dptrGetRatioSpectrum(double* bkgarray,
    double* smparray, double* outarray, long size, DATAYTYPE ytype);
  DLL_FUNC long FTIRInst_KillCollection();
  DLL_FUNC long FTIRInst_SetLaserWaveNumber(float* newLaser);
  DLL_FUNC long FTIRInst_SetPathlen(float* newPathlength);
  DLL_FUNC long FTIRInst_GetLaserWaveNumber(float* curLaser);
  DLL_FUNC long FTIRInst_GetPathlenEx(
    _instrumentMLVersion* _instrumentMLVersion, float* curPathlength);
  DLL_FUNC long FTIRInst_GetVersion(long* fwRev, long* dllRev, long* serialNo);
  DLL_FUNC long FTIRInst_GetVersionEx(_instrumentMLVersion* _vInfo);
  DLL_FUNC long FTIRInst_GetStatus(long* nEnergyStatus, float* fBatteryStatus,
    float* fSourceCurrentStatus, float* fSourceVoltageStatus,
    long* nLaserStatus, float* fDetectorStatus);
  DLL_FUNC long FTIRInst_GetStatusEx(_instrumentMLDiag* _dStatus);
  DLL_FUNC FTIR_STATE FTIRInst_CheckProgress(
    long* currentUnits, long* totalUnits);
  DLL_FUNC FTIR_STATE FTIRInst_CheckProgressEx(
    long* currentUnits, long* totalUnits, long* rejectedScans);
  DLL_FUNC long FTIRInst_CheckProgressStruct(_progress* pProgress);
  DLL_FUNC long FTIRInst_dptrGetLiveIGram(long res, double* buffer, long size,
    long* pActualFrom, long* pActualTo, long* pActualRes);
  DLL_FUNC long FTIRInst_StartCoaddedIgram(
    long numScans, long nRes, long nPhasePts);
  DLL_FUNC long FTIRInst_dptrGetCoaddedIGram(double* pArray, long nArraySize);
  DLL_FUNC long FTIRInst_dptrSetBackground(
    double* pArray, long nSize, double from, double to, long nRes);
  DLL_FUNC long FTIRInst_dptrGetLiveSingleBeam(long res, double* pArray,
    long size, double* actualFrom, double* actualTo, long* actualRes);
  DLL_FUNC long FTIRInst_GetIrGain(long* nVal);
  DLL_FUNC long FTIRInst_SetIrGain(long res, unsigned long flags);
  // DLL_FUNC long FTIRInst_RegisterStatus(HWND whandle, long wm_MessageID);
  DLL_FUNC long FTIRInst_SetAppLedState(long nLedState);
}
