#pragma once

#include "dll/InertiaExport.h"

#ifdef __cplusplus
extern "C"
{
#endif

	/** Open or close a connection.
	*  @param port The serial port to connect to
	*  @param open true to open the connection, false to close
	*  @return true when successful
	*/
	INERTIA_API bool setConnection(const char* port, bool open);

	/** Get Inertial samples.
	*  Get 18 values per row (timestamp, ax, ay, az, cx, cy, cz, gx, gy, gz, axhg, ayhg, azhg, qw, qx, qy, qz, pressure), if an input is not available it is filled with NAN.
	*  This value is returned by getImuColumns().
	*  @param port The serial port
	*  @param addrID The addrID to get a sample from
	*  @param data Memory block of doubles for data with size=rows*getImuColumns()
	*  @param rows Number of samples to get
	*  @param timeoutMs Maximum time in milliseconds to fetch samples, 0 for infinite
	*  @return the number of filled rows, unfilled data is not initialized to NAN
	*/
	INERTIA_API unsigned getImuSamples(const char* port, unsigned addrID, double* data, unsigned rows, unsigned timeoutMs);

	/** Get the number of columns used by getImuSamples.
	*  @return the number of columns
	*/
	INERTIA_API unsigned getImuColumns();

	/** Get ADC samples.
	*  @param port The serial port
	*  @param addrID The addrID to get a sample from
	*  @param data Memory block of doubles for data with size=rows*cols
	*  @param rows Number of samples to get
	*  @param cols Number of items per sample, 1st col = timestamp, remaining columns are ADC inputs, if input is not available it is filled with NAN
	*  @param timeoutMs Maximum time in milliseconds to fetch samples, 0 for infinite
	*  @return the number of filled rows, unfilled data is not initialized to NAN
	*/
	INERTIA_API unsigned getADCSamples(const char* port, unsigned addrID, double* data, unsigned rows, unsigned cols, unsigned timeoutMs);

	/** Set to use raw or converted ADC samples.
	*  By default, the ADC samples are converted to Voltage. Use this to enable or disable this conversion.
	*  @param enable Enable raw ADC Samples
	*/
	INERTIA_API void setUseRawADCSamples(bool enable);

	/** Get status samples.
	*  Get 5 values per row (timestamp, bat, cpu temp, exIn, rssi), if input is not available it is filled with NAN.
	*  This value is returned by getStatusColumns().
	*  @param port The serial port
	*  @param addrID The addrID to get a sample from
	*  @param data Memory block of doubles for data with size=rows*getStatusColumns()
	*  @param rows Number of samples to get
	*  @return the number of filled rows, unfilled data is not initialized to NAN
	*/
	INERTIA_API unsigned getStatusSamples(const char* port, unsigned addrID, double* data, unsigned rows);

	/** Get the number of columns used by getStatusSamples.
	*  @return the number of columns
	*/
	INERTIA_API unsigned getStatusColumns();

	/** Get lost and total sample statistics.
	 *  Statistics are reset after the request.
	 *  @param port The serial port
	 *  @param addrID The addrID to get a statistics from
	 *  @param lost the lost samples
	 *  @param received the received samples
	 */
	INERTIA_API void getDataLossStats(const char* port, unsigned addrID, unsigned long& lost, unsigned long& received);

	/** Reset the orientation algorithm.
	*  @param port The serial port
	*  @return true when successful
	*/
	INERTIA_API bool resetOrientationAlgorithm(const char* port);

	/** Configure the orientation algorithm.
	*  @param enable Enable the orientation algorithm (default false)
	*  @param useCompass Use the compass (default true)
	*  @param enableBiasEstimation Reduce gyroscope drift in rest (default true)
	*  @param resetInRest Reset the algorithm when a node is in reset (default true)
	*  @return true when successful
	*/
	INERTIA_API bool setOrientationSettings(bool enable, bool useCompass, bool enableBiasEstimation, bool resetInRest);

	/** Update nexoDAQ gain and bias configuration.
	*  @param port The serial port
	*  @param addrID The addrID of the nexoDAQ
	*  @param channel The nexoDAQ channel (1, 2 or 3) to get/update the settings from
	*  @param channelMask Mask to indicate what channels should receive the configuration, 0 to use 'channel'
	*  @param enable Turn the channel on or off
	*  @param hwGain the new hardware gain
	*  @param hwBias the new hardware bias
	*  @param voltagePH1 the new (positive, bi-polar) phase1 output voltage
	*  @param voltagePH2 the new (positive, bi-polar) phase2 output voltage
	*  @param current the new output current (IEPE mode only)
	*  @param acdc AC (true) or DC (false) (Low/High Voltage modes only)
	*  @param frontEnd the front-end to use (0=Low Voltage, 1=High Voltage, 2=IEPE, 3=Charge, 4=4-20ma)
	*  @return true when configuration is sent successfully
	*/
	INERTIA_API bool updateNexoSettings(const char* port, unsigned addrID, unsigned channel, unsigned channelMask, bool enable,
		unsigned hwGain, float hwBias, float voltagePH1, float voltagePH2, float current, bool acdc, unsigned frontEnd);

	/** Set the operating mode.
	*  @param port The serial port
	*  @param addrID The addrID
	*  @param mode The operating mode, 0=active, 1=standby, 2=sleep, 3=deepsleep, 4=TEDS
	*/
	INERTIA_API bool setOperatingMode(const char* port, unsigned addrID, unsigned mode);

	/** Update the firmware.
	*  @param port The serial port
	*  @param addrID The addrID
	*  @param file The fwu file
	*  @param validate Enable validation of hwID, fwID, rev, and components
	*/
	INERTIA_API void firmwareUpdate(const char* port, unsigned addrID, const char* file, bool validate);

	/** Get the firmware update status.
	*  @return 0=OK/Ready, 1=Busy, 2=Error
	*/
	INERTIA_API int getFirmwareUpdateStatus();

#ifdef __cplusplus
}
#endif
