#pragma once

#if defined(WIN32)
#ifdef WHALETEQ_API

#else
#define WHALETEQ_API extern "C" __declspec(dllimport)
#endif
#elif defined(LINUX) || defined(OSX)
#define WHALETEQ_API extern "C" __attribute__ ((visibility ("default")))
#endif

#define DefaultAmplitude	1.0
#define MaxAmplitude		10.0
#define MinAmplitude		-10.0

#define DefaultFrequency		1.0
#define	MaxFrequency			500.0
#define MinFrequency			0.05
#define	MaxFrequencyPulseWave	5.0

#define DefaultDCOffset		0
#define MaxDCOffset			300
#define MinDCOffset			-300
#define MaxDCOffsetVarMode	1000
#define MinDCOffsetVarMode	-1000

#define DefaultPulseWidth	100
#define MaxPulseWidth		300
#define MinPulseWidth		2

#define DefaultQRSDuration	100
#define MaxQRSDuration	200
#define MinQRSDuration	5

#define DefaultTWave	0.2
#define MaxTWave		5.0
#define MinTWave		0

#define DefaultPacingAmplitude	0
#define MaxPacingAmplitude		700
#define MinPacingAmplitude		-700

#define DefaultPacingDuration	2.0
#define MaxPacingDuration		3.0
#define MinPacingDuration		0.1

#define DefaultPacingRate	60
#define MaxPacingRate		300
#define MinPacingRate		10

#define DefaultOvershootTimeConstant	0
#define MaxOvershootTimeConstant		100
#define MinOvershootTimeConstant		0

#define DefaultPacingOvershootAmp	0   //Auto set to -0.25 * Pacing Amplitude
#define MaxPacingOvershootAmp		5.0
#define MinPacingOvershootAmp		-5.0

#define DefaultECG2_27_NoiseAmp	0.1
#define MaxECG2_27_NoiseAmp		10
#define MinECG2_27_NoiseAmp		0.01

#define DefaultDynamicRangeTestAmp	1.0
#define MaxDynamicRangeTestAmp		5.0
#define MinDynamicRangeTestAmp		0
#define DefaultDynamicRangeTestFreq	40
#define MaxDynamicRangeTestFreq		50
#define MinDynamicRangeTestFreq		10

#define DefaultScanSineStartFreq	0.67
#define DefaultScanSineStopFreq		150
#define MaxScanSineFreq				500.0
#define MinScanSineFreq				0.67
#define MinScanSineStopFreq			0.01
#define DefaultScanSineDuration		30
#define MaxScanSineDuration			180
#define MinScanSineDuration			10

typedef enum _OutputFunction_E {
    Output_Off = 0,
    Output_Sine,
    Output_Triangle,
    Output_Square,
    Output_RectanglePulse,
    Output_TrianglePulse,
    Output_Exponential,
    Output_ECG2_27,
    Output_IEC227W,
    Output_IEC251W,
    Output_JJG1041,
    Output_JJG1041_HR,
    Output_JJG_Hysteresis,
    Output_ECG_File,
    Output_InputDynamicRange,
    Output_ANE20000
} OutputFunction_E;

typedef enum _OutputLead_E {
    Lead_RA = 0,	//(R)
    Lead_LA,			//(L)
    Lead_LL,			//(F)
    Lead_V1,
    Lead_V2,
    Lead_V3,
    Lead_V4,
    Lead_V5,
    Lead_V6
} OutputLead_E;

typedef enum _SpecialWave227_E {
    IEC227W_3A_A1 = 0,
    IEC227W_3B_A2,
    IEC227W_3C_A3,
    IEC227W_3D_A4,
    IEC227W_4A_B1,
    IEC227W_4A_B1x2,
    IEC227W_4A_B1d2,
    IEC227W_4B_B2,
    IEC227W_4B_B2x2,
    IEC227W_4B_B2d2,
} SpecialWave227_E;

typedef enum _SpecialWave251_E {
    IEC251W_1 = 0,	//CAL05000
    IEC251W_2,		//CAL10000
    IEC251W_3,		//CAL15000
    IEC251W_4,		//CAL20000
    IEC251W_6,		//CAL30000
    IEC251W_10,		//CAL50000
    CAL20002,		//--------- New Added ------------------------
    CAL20100,
    CAL20110,
    CAL20160,
    CAL20200,
    CAL20210,
    CAL20260,
    CAL20500,
    CAL20502,
    CAL40000
} SpecialWave251_E;

typedef enum _BaselineTest_E {
    Baseline_Off = 0,
    Baseline_50Hz,
    Baseline_60Hz,
    Baseline_80Hz,
    Baseline_100Hz
} BaselineTest_E;

typedef enum _ECG2_27_NoiseFreq_E {
    Noise_None = 0,
    Noise_50Hz,
    Noise_60Hz
} ECG2_27_NoiseFreq_E;

typedef enum _PacingPulse_E {
    SinglePulse = 0,
    DoublePulse_150ms,
    DoublePulse_250ms
} PacingPulse_E;

/// \fn ConnectedCallback
/// \brief Called when the device is connected or disconnected
/// @param[in] connected    true if connected; otherwise, it's false
typedef void (*ConnectedCallback) (bool connected);


/// \fn OutputSignalCallback
/// \brief Called back with outputted data
/// @param[in] time              Unit: second
/// @param[in] amplitude         Unit: mV
typedef void (*TimeAmplitudeCallback) (double time, double amplitude);

/// \fn OutputSignalCallback
/// \brief Called back with current frequency; usued in "Baseline Reset Test" or "Frequency Scanning"
/// @param[in] frequency         Unit: Hz
typedef void (*SyncFreqCallback) (double frequency);

/// \fn SyncMainFuncCallback
/// \brief Call back with the changed main function; used in "Frequency Scanning"
/// @param[in] function          //!< enum ::OutputFunction_E
typedef void (*SyncMainFuncCallback) (OutputFunction_E function);

///
/// Initialization
///
/// During initialization, it will try to connect a device. If a device is found,
/// the cb function will be called. After then, if a device is disconnected,
/// the cb will be called again to notify the disconnection event. 
/// @param[in] cb  a callback function to notify the connection or disconnection event
///
WHALETEQ_API
bool
Init (
    ConnectedCallback cb
);

///
/// Connect the device
///
/// @param[in] portNumber            Device COM port number; -1 means the port number is automatically selected
/// @param[in] millisecondsTimeout   Connection timeout; the number of milliseconds to connect, or -1 to wait indefinitely.
/// @return true if the device is connected; false if the time-out interval elapsed and 
///         the device is still not connected
///
WHALETEQ_API
bool
Connect (
    unsigned int portNumber,
    unsigned int millisecondsTimeout
);

///
/// Reset all settings to default value; also set Lead RA ON
///
WHALETEQ_API
void
ResetSECG (
    void
);

///
/// Reset all settings to default value; also set all leads OFF
///
WHALETEQ_API
void
ResetSECG_AllLeadOff (
    void
);

///
/// Disconnect the device and clean up library resource
///
WHALETEQ_API
void
Close (
    void
);

///
/// Get device connection status
///
WHALETEQ_API
bool
IsConnected (
    void
);

///
/// Get device serial number
///
/// @return a null-terminated string of serial number text; DO NOT free the returned string
///
WHALETEQ_API
char*
GetSerialNumber (
    void
);

///
/// Get device firmware version
///
/// @return a null-terminated string of firmware version text; DO NOT free the returned string
///
WHALETEQ_API
char*
GetFWVersion (
    void
);

///
/// Get device hardware version
///
/// @return a null-terminated string of hardware version text; DO NOT free the returned string
///
WHALETEQ_API
char*
GetHWVersion (
    void
);

///
/// The "TimeAmplitudeCB cb" would be triggered during SECG outputting signal.
/// About 0.006 second(6ms) interval between each callback be triggered
///
WHALETEQ_API
void
RegisterTimeAmpCB (
    TimeAmplitudeCallback cb
);

///
/// The "TimeAmplitudeCB cb" would be triggered during outputting waveform with pacing signal
///
WHALETEQ_API
void
RegisterPacingTimeAmpCB (
    TimeAmplitudeCallback cb
);

WHALETEQ_API
void
RegisterSyncFreqCB (
    SyncFreqCallback cb

);

WHALETEQ_API
void
RegisterSyncMainFuncCB (
    SyncMainFuncCallback cb
);

//Return value:
// 0:  succeed
// -1: Mainfunction not set to IEC227W
// Call after set main func to Output_IEC227w
WHALETEQ_API
int
SetSpecialWave227 (
    SpecialWave227_E spec
);

WHALETEQ_API
SpecialWave227_E
GetSpecialWave227 (
    void
);

//Return value:
// 0:  succeed
// -1: Mainfunction not set to IEC251W
// Call after set main func to Output_IEC251w
WHALETEQ_API
int
SetSpecialWave251 (
    SpecialWave251_E spec
);

WHALETEQ_API
SpecialWave251_E
GetSpecialWave251 (
    void
);

//Return value:
// 0:  succeed
// -1: lead (0~2: LeadI/II/III; 3~8: Lead V1~V6)
// Main func would change to Output_ANE20000 after Call 
WHALETEQ_API
int
SetANE20000Lead (
    int lead
);

WHALETEQ_API
int
GetANE20000Lead (
        void
);

//Return value:
//	0:	succeed
//	-1:	SECG not be initialized
WHALETEQ_API
int
SetOutputFunc (
    OutputFunction_E func
);

WHALETEQ_API
OutputFunction_E
GetOutputFunc (
    void
);

//Parameter - amp:
//	value range: -10 ~ 10
//	unit: millivolt(mV)
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: value out of range
//  -3: "Baseline Reset Test" is working
//Default value after InitSECG(): 1mV
WHALETEQ_API
int
SetAmplitude (
    double amp
);

WHALETEQ_API
double
GetAmplitude (
    void
);

//Parameter - freq:
//	value range: 0.05 ~ 5, if Output is Pulse Waveforms
//               0.05 ~ 3, if Output is Exponential
//               0.05 ~ 6, if Output is ECG2_27
//               0.05 ~ 500, others
//	unit: hertz
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: value out of range
//	-3: "Frequency Scan" is working
//  -4: "Baseline Reset Test" is working
//Default value after InitSECG(): 1Hz
WHALETEQ_API
int
SetFrequency (
    double freq
);

WHALETEQ_API
double
GetFrequency (
    void
);

//Parameter - setting:
//	value range: -300 ~ 300 - DCOffset Variable mode Off
//               -1000 ~ 1000 - DCOffset Variable mode On
//	unit: millivolt(mV)
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: value out of range
//Default value after InitSECG(): 0mV
WHALETEQ_API
int
SetDCOffset (
    int setting
);

WHALETEQ_API
int
GetDCOffset (
    void
);

//Return value:
//	0: succeed
//	-1: SECG not be initialized
//Default value after InitSECG(): false(Off)
WHALETEQ_API
int
SetDCOffsetVariableMode (
    bool OnOff
);

WHALETEQ_API
bool
GetDCOffsetVariableMode (
    void
);

//Return value:
//	0: succeed
//	-1: SECG not be initialized
//Default value after InitSECG(): false(Off)
WHALETEQ_API
int
SetDCOffsetCommonMode (
    bool OnOff
);

//For backward compatical the typo
WHALETEQ_API
int
SetDCOffsetCommoneMode (
    bool OnOff
);

WHALETEQ_API
bool
GetDCOffsetCommonMode (
    void
);

//Return value:
//	0: succeed
//	-1: SECG not be initialized
//Default value after InitSECG(): Lead_RA - On; all others - Off;
WHALETEQ_API
int
SetOutputLead (
    OutputLead_E lead, bool OnOff
);

WHALETEQ_API
bool
GetOutputLead (
    OutputLead_E lead
);

//Parameter - width:
//	value range: 2 ~ 300
//	unit: milisecond(ms)
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: value out of range
//Default value after InitSECG(): 100ms
WHALETEQ_API
int
SetPulseWidth (
    double width
);

WHALETEQ_API
double
GetPulseWidth (
    void
);

//Return value:
//	0: succeed
//	-1: SECG not be initialized
//Default value after InitSECG(): true(On - 620k&/4.7nF shorted)
WHALETEQ_API
int
SetInputImpedanceMode (
    bool OnOff
);

WHALETEQ_API
bool
GetInputImpedanceMode (
    void
);

//Return value:
//	0:	succeed
//	-1:	SECG not be initialized
//Default value after InitSECG(): SinglePulse
WHALETEQ_API
int
SetPacingPulseMode (
    PacingPulse_E mode
);

WHALETEQ_API
PacingPulse_E
GetPacingPulseMode (
    void
);

//Parameter - time:
//	value range: 5 ~ 200
//	unit: milisecond(ms)
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: value out of range
//Default value after InitSECG(): 100ms
WHALETEQ_API
int
SetQRSDuration (
    double time
);

WHALETEQ_API
double
GetQRSDuration (
    void
);

//Parameter - amp:
//	value range: 0 ~ 5
//	unit: millivolt(mV)
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: value out of range
//Default value after InitSECG(): 0.2mV
WHALETEQ_API
int
SetTWave (
    double amp
);

WHALETEQ_API
double
GetTWave (
    void
);


//Parameter - amp:
//	value range: -700 ~ 700
//	unit: millivolt(mV)
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: value out of range
//Default value after InitSECG(): 0mV
WHALETEQ_API
int
SetPacingAmplitude (
    double amp
);

WHALETEQ_API
double
GetPacingAmplitude (
    void
);

//Parameter - time:
//	value range: 0.1 ~ 2
//	unit: milisecond(ms)
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: value out of range
//Default value after InitSECG(): 2ms
WHALETEQ_API
int
SetPacingDuration (
    double time
);

WHALETEQ_API
double
GetPacingDuration (
    void
);

//Parameter - BPM:
//	value range: 10 ~ 300
//	unit: beats per minute(BPM)
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: value out of range
//Default value after InitSECG(): 60BPM
WHALETEQ_API
int
SetPacingRate(
    unsigned BPM
);

WHALETEQ_API
unsigned
GetPacingRate (
    void
);

//Parameter - time:
//	value range: 0 ~ 100
//	unit: millisecond(ms)
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: value out of range
//Default value after InitSECG(): 0ms
WHALETEQ_API
int
SetOvershootTimeConstant (
    unsigned time
);

WHALETEQ_API
unsigned
GetOvershootTimeConstant (
    void
);

//Parameter - amp:
//	value range: -2 ~ 2
//	unit: millivolt(mV)
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: value out of range
//Default value after InitSECG(): 0mV -> Auto set to -0.25 * Pacing Amplitude
WHALETEQ_API
int
SetPacingOvershootAmp (
    double amp
);

WHALETEQ_API
double
GetPacingOvershootAmp (
    void
);


//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: current main output function not be "Output_Sine"
//Default value after InitSECG(): Baseline_Off
//"Output Function" must be set to "Output_Sine" before setting as "non - Baseline_Off" value
//After setting as "non - Baseline_Off" value, "Amplitude" would be locked to "2.5mV"
//and "Frequency" would be locked as "50/60/80/100" Hz.
WHALETEQ_API
int
SetBaselineResetTest (
    BaselineTest_E mode
);

WHALETEQ_API
BaselineTest_E
GetBaselineResetTest (
    void
);

//Parameter - freq:
//	Default value after InitSECG(): Noise_None
//Parameter - amp:
//	value range: 0.01 ~ 10
//	unit: millivolt(mV)
//	Default value after InitSECG(): 0.1mV
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: current main output function is not "Output_ECG2_27"
//	-3: amp out of range 
WHALETEQ_API
int
SetECG2_27_Noise (
    ECG2_27_NoiseFreq_E freq, double amp
);

WHALETEQ_API
ECG2_27_NoiseFreq_E
GetECG2_27_NoiseFreq (
    void
);

WHALETEQ_API
double
GetECG2_27_NoiseAmp (
    void
);

//Parameter - enableDriftTest
//    true, enable AAMI EC 13 Drift test; adds 4mVpp 0.1Hz triangle waveform to the ECG signal 
//    false, disable AAMI EC 13 Drift test
//Return value:
//	0: succeed
//	-1: SECG not be initialized
WHALETEQ_API
int
SetECG2_27_AAMIDriftTest (
    bool enableDriftTest
);

WHALETEQ_API
bool
GetECG2_27_AAMIDriftTest (
    void
);

//Parameter - amp:
//	value range: 0 ~ 5
//	unit: millivolt(mV)
//	Default value after InitSECG(): 1mV
//Parameter - freq:
//	value range: 10 ~ 50
//	unit: hertz
//	Default value after InitSECG(): 40Hz
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: current main output function not be "Output_Square"
//	-3: amp out of range
//	-4: freq out of range
WHALETEQ_API
int
SetDynamicRangeTest (
    bool OnOff,
    double amp,
    double freq
);

WHALETEQ_API
bool
GetDynamicRangeTest (
    void
);

WHALETEQ_API
double
GetDynamicRangeTestAmp (
    void
);

WHALETEQ_API
double
GetDynamicRangeTestFreq (
    void
);

//Parameter - startFreq:
//	value range: 0.67 ~ 500
//	unit: hertz
//	Default value after InitSECG(): 0.67Hz
//Parameter - stopFreq:
//	value range: 0.01 ~ 500
//	unit: hertz
//	Default value after InitSECG(): 150Hz
//Parameter - duration:
//	value range: 10 ~ 180
//	unit: millisecond(ms)
//	Default value after InitSECG(): 30ms
//Return value:
//	0: succeed
//	-1: SECG not be initialized
//	-2: startFreq out of range
//	-3: stopFreq out of range
//	-4: duration out of range
//"Output Function" would be set to "Output_Sine" when setting "OnOff" as true,
//then "Frequency" would be locked(SetFrequency() return -3) for periodly scanning change.
//"Output Function" would be set to "Output_Off" when setting "OnOff" as false.
WHALETEQ_API
int
SetFreqScanSine (
    bool OnOff,
    double startFreq,
    double stopFreq,
    int duration
);

WHALETEQ_API
bool
GetFreqScanSine (
    void
);

WHALETEQ_API
double
GetFreqScanSineStartFreq (
    void
);

WHALETEQ_API
double
GetFreqScanSineStopFreq (
    void
);

WHALETEQ_API
int
GetFreqScanSineDuration (
    void
);

//Start Frequency as 3BPM(0.05Hz)
//Stop Frequency as 30BPM(0.5Hz)
//Duration as 30ms
//"Output Function" would be set to "Output_ECG2_27" when setting "OnOff" as true,
//then "Frequency" would be locked(SetFrequency() return -3) for periodly scanning change.
//"Output Function" would be set to "Output_Off" when setting "OnOff" as false.
WHALETEQ_API
int
SetFreqScanECG (
    bool OnOff
);

WHALETEQ_API
bool
GetFreqScanECG (
    void
);

//Return value:
// >0: succeed, the number of sample data loaded
// -1: Open file failed
// -2: Can't solve sample rate in Line 1
// -3: Can't solve sample number in Line 2
// -4: Raw data file is too large to fit the memory
WHALETEQ_API
int
LoadECGtxt (
    wchar_t* file
);

WHALETEQ_API
int
LoadECGbin (
    wchar_t* file
);

//Return value:
// 0:  succeed
WHALETEQ_API
int
EnablePlayRawDataLoop (
    bool enable
);


///
/// Get DLL file version
///
WHALETEQ_API
char*
GetSDKVersion (
    void
);