#pragma once

#include "data/config/SensorSpecificSettings.h"
#include "data/config/SingleAxisConfig.h"

namespace inertia
{

struct NexoDAQChannelConfig;
struct NexoDAQChannelCapability;
typedef std::shared_ptr<NexoDAQChannelConfig> NexoDAQChannelConfigPtr;
typedef std::shared_ptr<NexoDAQChannelCapability> NexoDAQChannelCapabilityPtr;


// Channel Special Configuration Descriptor ID
enum NexoDAQDescriptorID : uint8_t
{
	NDQ_INPUT_STAGE = 0,
	NDQ_SEHV_FRONT_END = 1,
	NDQ_DLV_FRONT_END = 2,
	NDQ_DCA_FRONT_END = 3,
	NDQ_HARDWARE_GAIN = 4,
	NDQ_HARDWARE_BIAS = 5,
	NDQ_CURRENT_SOURCE = 6,
	NDQ_USER_POWER = 7,
	NDQ_TEDS = 8,
	NDQ_AUTO_RAIL = 9,
	NDQ_WAKEUP_SOURCE = 10,
	NDQ_TRIGGER_SOURCE = 11,
	NDQ_LED_BEHAVIOR = 12,
	NDQ_ADC = 13,
	NDQ_USER_GPIO = 14,
	NDQ_USER_CALIBRATION = 15,
	NDQ_METADATA = 16,
	NDQ_DESCR_ID_UNKNOWN,
};

enum NexoDAQUserGPIOMode : uint8_t
{
	NDQ_USER_GPIO_MODE_DIGITAL_IN = 0,
	NDQ_USER_GPIO_MODE_DIGITAL_OUT = 1,
	NDQ_USER_GPIO_MODE_ANALOG_IN = 2,
	NDQ_USER_GPIO_MODE_LAST
};

enum NexoDAQTEDSMode : uint8_t
{
	NDQ_TEDS_MODE_NONE = 0,
	NDQ_TEDS_MODE_C1 = 1,
	NDQ_TEDS_MODE_C2 = 2,
};


struct INERTIA_API NexoDAQSettings
	: SpecificSensorSettings
{
	std::vector<NexoDAQChannelConfigPtr> channelConfigs;

	NexoDAQSettings();
	NexoDAQSettings(uint8_t const* in, const unsigned offset, const unsigned _length);
	NexoDAQSettings(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out, const size_t bitfieldOffset) const override;
	const std::wstring ToString() const override;
	const std::wstring ToSimpleString() const;
};


struct INERTIA_API NexoDAQChannelConfig
{
private:
	NexoDAQDescriptorID descrID;

public:
	NexoDAQChannelConfig(NexoDAQDescriptorID const _descrID);
	NexoDAQChannelConfig(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfig(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	NexoDAQDescriptorID GetDescrID() const;

	unsigned GetLength(unsigned const subType = 0) const;
	virtual void GetBytes(std::vector<uint8_t>& out) const;
	virtual const std::wstring ToString() const;
};


struct INERTIA_API NexoDAQChannelConfigInputStage
	: NexoDAQChannelConfig
{
	bool selectACDC;
	uint8_t activeFrontEndSelect;

	NexoDAQChannelConfigInputStage();
	NexoDAQChannelConfigInputStage(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigInputStage(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigSEHVFrontEnd
	: NexoDAQChannelConfig
{
	bool enable200InputImp;
	bool force1MInputImpOnAINP;

	NexoDAQChannelConfigSEHVFrontEnd();
	NexoDAQChannelConfigSEHVFrontEnd(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigSEHVFrontEnd(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigDLVFrontEnd
	: NexoDAQChannelConfig
{
	bool enable10mInputImp;
	bool disableDrivenGuard;
	bool useSingleEndedMode;

	NexoDAQChannelConfigDLVFrontEnd();
	NexoDAQChannelConfigDLVFrontEnd(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigDLVFrontEnd(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigDCAFrontEnd
	: NexoDAQChannelConfig
{
	bool useSingleEndedMode;
	uint8_t rangeSelect;
	uint8_t cornerFreqBinSelect;

	NexoDAQChannelConfigDCAFrontEnd();
	NexoDAQChannelConfigDCAFrontEnd(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigDCAFrontEnd(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigHardwareGain
	: NexoDAQChannelConfig
{
	uint16_t gain;

	NexoDAQChannelConfigHardwareGain();
	NexoDAQChannelConfigHardwareGain(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigHardwareGain(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigHardwareBias
	: NexoDAQChannelConfig
{
	float bias;

	NexoDAQChannelConfigHardwareBias();
	NexoDAQChannelConfigHardwareBias(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigHardwareBias(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigCurrentSource
	: NexoDAQChannelConfig
{
	bool enableCurrentSource;
	float current;

	NexoDAQChannelConfigCurrentSource();
	NexoDAQChannelConfigCurrentSource(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigCurrentSource(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigUserPower
	: NexoDAQChannelConfig
{
	bool enableUserPower;
	bool autoEnableUserPower;
	bool userPowerDuringSleep;

	NexoDAQChannelConfigUserPower();
	NexoDAQChannelConfigUserPower(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigUserPower(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigTEDS
	: NexoDAQChannelConfig
{
	NexoDAQTEDSMode tedsMode;

	NexoDAQChannelConfigTEDS();
	NexoDAQChannelConfigTEDS(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigTEDS(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigAutoRail
	: NexoDAQChannelConfig
{
	bool enableAutoRail;
	bool enableAutoRailSignalFollower;
	float maxSignalAmplitude;
	float requiredSignalHeadroom;

	NexoDAQChannelConfigAutoRail();
	NexoDAQChannelConfigAutoRail(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigAutoRail(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigWakeupSource
	: NexoDAQChannelConfig
{
	bool useAsWakeupSource;
	bool useAlternateSourceUserGPIO;
	bool wirelessStreamWhileMonitoring;

	uint8_t eventChannel;
	uint8_t detectorMode;
	uint8_t monitoringMode;

	uint8_t monitoringChannel;
	uint8_t monitoringSwitchDelay;
	uint8_t eventHoldOff;

	float lowerThreshold;
	float higherThreshold;

	NexoDAQChannelConfigWakeupSource();
	NexoDAQChannelConfigWakeupSource(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigWakeupSource(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigTriggerSource
	: NexoDAQChannelConfig
{
	NexoDAQChannelConfigTriggerSource();
	NexoDAQChannelConfigTriggerSource(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigTriggerSource(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigLedBehavior
	: NexoDAQChannelConfig
{
	bool enableLedOverride;
	std::vector<uint8_t> ledBehavior;

	NexoDAQChannelConfigLedBehavior();
	NexoDAQChannelConfigLedBehavior(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigLedBehavior(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigADC
	: NexoDAQChannelConfig
{
	bool enableAdcOverride;
	uint8_t osrSelect;
	uint8_t filterSelect;

	NexoDAQChannelConfigADC();
	NexoDAQChannelConfigADC(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigADC(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigUserGPIO
	: NexoDAQChannelConfig
{
	NexoDAQUserGPIOMode gpioMode;
	bool enableUserGPIO;

	// digital input
	bool triggerOnRisingEdge;
	bool triggerOnFallingEdge;
	uint8_t eventChannel;
	uint8_t eventHoldOff;

	// digital output
	uint16_t reserved;

	// analog input
	SingleAxisConfig analogIn;

	NexoDAQChannelConfigUserGPIO();
	NexoDAQChannelConfigUserGPIO(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigUserGPIO(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigUserCalibration
	: NexoDAQChannelConfig
{
	bool enableUserCalibration;

	NexoDAQChannelConfigUserCalibration();
	NexoDAQChannelConfigUserCalibration(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigUserCalibration(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigMetadata
	: NexoDAQChannelConfig
{
	std::vector<uint8_t> metadata;

	NexoDAQChannelConfigMetadata();
	NexoDAQChannelConfigMetadata(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigMetadata(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelConfigUnknown
	: NexoDAQChannelConfig
{
	std::vector<uint8_t> payload;

	NexoDAQChannelConfigUnknown();
	NexoDAQChannelConfigUnknown(uint8_t const* in, const unsigned _length);
	NexoDAQChannelConfigUnknown(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


// ------------- capabilities -------------


struct INERTIA_API NexoDAQCapabilities
	: SpecificSensorSettings
{
	std::vector<NexoDAQChannelCapabilityPtr> channelCapabilities;

	NexoDAQCapabilities();
	NexoDAQCapabilities(uint8_t const* in, const unsigned offset, const unsigned _length);
	NexoDAQCapabilities(std::wstring const& argString);


#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out, const size_t bitfieldOffset) const override;
	const std::wstring ToString() const override;
	const std::wstring ToSimpleString() const;
};


struct INERTIA_API NexoDAQChannelCapability
{
private:
	NexoDAQDescriptorID descrID;

public:
	NexoDAQChannelCapability(NexoDAQDescriptorID const _descrID);
	NexoDAQChannelCapability(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapability(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	NexoDAQDescriptorID GetDescrID() const;

	unsigned GetLength(unsigned const subType = 0) const;
	virtual void GetBytes(std::vector<uint8_t>& out) const;
	virtual const std::wstring ToString() const;
};


struct INERTIA_API NexoDAQChannelCapabilityInputStage
	: NexoDAQChannelCapability
{
	bool dcCouplingSupported;
	bool acCouplingSupported;

	NexoDAQChannelCapabilityInputStage();
	NexoDAQChannelCapabilityInputStage(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityInputStage(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilitySEHVFrontEnd
	: NexoDAQChannelCapability
{
	uint8_t hardwareID;
	uint32_t hardwareSpecific;

	NexoDAQChannelCapabilitySEHVFrontEnd();
	NexoDAQChannelCapabilitySEHVFrontEnd(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilitySEHVFrontEnd(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityDLVFrontEnd
	: NexoDAQChannelCapability
{
	uint8_t hardwareID;
	uint32_t hardwareSpecific;

	NexoDAQChannelCapabilityDLVFrontEnd();
	NexoDAQChannelCapabilityDLVFrontEnd(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityDLVFrontEnd(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityDCAFrontEnd
	: NexoDAQChannelCapability
{
	uint8_t hardwareID;
	uint32_t hardwareSpecific;

	NexoDAQChannelCapabilityDCAFrontEnd();
	NexoDAQChannelCapabilityDCAFrontEnd(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityDCAFrontEnd(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityHardwareGain
	: NexoDAQChannelCapability
{
	uint8_t gainStepSize;
	uint8_t gainBits;

	NexoDAQChannelCapabilityHardwareGain();
	NexoDAQChannelCapabilityHardwareGain(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityHardwareGain(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityHardwareBias
	: NexoDAQChannelCapability
{
	uint8_t hardwareID;

	NexoDAQChannelCapabilityHardwareBias();
	NexoDAQChannelCapabilityHardwareBias(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityHardwareBias(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityCurrentSource
	: NexoDAQChannelCapability
{
	uint8_t hardwareID;

	NexoDAQChannelCapabilityCurrentSource();
	NexoDAQChannelCapabilityCurrentSource(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityCurrentSource(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityUserPower
	: NexoDAQChannelCapability
{
	uint8_t reserved;

	NexoDAQChannelCapabilityUserPower();
	NexoDAQChannelCapabilityUserPower(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityUserPower(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityTEDS
	: NexoDAQChannelCapability
{
	bool class1supported;
	bool class2supported;

	NexoDAQChannelCapabilityTEDS();
	NexoDAQChannelCapabilityTEDS(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityTEDS(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityAutoRail
	: NexoDAQChannelCapability
{
	bool dynamicSignalAmplitudeFollowerSupported;

	NexoDAQChannelCapabilityAutoRail();
	NexoDAQChannelCapabilityAutoRail(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityAutoRail(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityWakeupSource
	: NexoDAQChannelCapability
{
	bool thresholdDetectWhileOffSupported;
	bool lowResCapturewhileOffSupported;
	bool wakeupFromUserGPIOSupported;
	uint8_t hardwareID;

	NexoDAQChannelCapabilityWakeupSource();
	NexoDAQChannelCapabilityWakeupSource(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityWakeupSource(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityTriggerSource
	: NexoDAQChannelCapability
{
	NexoDAQChannelCapabilityTriggerSource();
	NexoDAQChannelCapabilityTriggerSource(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityTriggerSource(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityLedBehavior
	: NexoDAQChannelCapability
{
	NexoDAQChannelCapabilityLedBehavior();
	NexoDAQChannelCapabilityLedBehavior(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityLedBehavior(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityADC
	: NexoDAQChannelCapability
{
	uint8_t hardwareID;

	NexoDAQChannelCapabilityADC();
	NexoDAQChannelCapabilityADC(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityADC(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityUserGPIO
	: NexoDAQChannelCapability
{
	bool analogSamplingSupported;
	bool inputTriggerSupported;

	uint8_t hardwareID;

	NexoDAQChannelCapabilityUserGPIO();
	NexoDAQChannelCapabilityUserGPIO(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityUserGPIO(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityUserCalibration
	: NexoDAQChannelCapability
{
	bool userCalibrationSupported;

	NexoDAQChannelCapabilityUserCalibration();
	NexoDAQChannelCapabilityUserCalibration(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityUserCalibration(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityMetadata
	: NexoDAQChannelCapability
{
	bool metadataSupported;

	NexoDAQChannelCapabilityMetadata();
	NexoDAQChannelCapabilityMetadata(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityMetadata(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};


struct INERTIA_API NexoDAQChannelCapabilityUnknown
	: NexoDAQChannelCapability
{
	std::vector<uint8_t> payload;

	NexoDAQChannelCapabilityUnknown();
	NexoDAQChannelCapabilityUnknown(uint8_t const* in, const unsigned _length);
	NexoDAQChannelCapabilityUnknown(std::wstring const& argString);

#ifdef WITH_BOOST_PROGRAM_OPTIONS
	static const po::options_description GetOptionDescription();
#endif

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
};

}
