/*! \file AxisConfig.h */
#pragma once

#include "data/config/AbstractConfig.h"

namespace inertia
{

/** AxisConfigDescriptorType */
enum AxisConfigDescriptorType {
	AXIS_DESCRIPTOR_CONFIGURATION = 0,
	AXIS_DESCRIPTOR_CAPABILITIES = 1,
	AXIS_DESCRIPTOR_TYPE_LAST = 2
};


struct INERTIA_API AxisConfig
{
public:
	uint8_t GetHeaderRevision() const;
	uint8_t GetSensorRevision() const;
	uint8_t GetSensorID() const;
	unsigned GetHeaderSize() const;
	unsigned GetLength() const;
	AxisConfigDescriptorType GetDescriptorType() const;
	virtual unsigned GetInstanceMask() const = 0;

	virtual void GetBytes(std::vector<uint8_t>& out) const = 0;
	virtual const std::wstring ToString() const = 0;
	virtual const std::wstring ToSimpleString(uint16_t const globalRate) const = 0;

	static std::vector<std::pair<ConfigType, uint8_t> > GetConfigsWithCapabilities();
	static bool HasDescriptorType(ConfigType const config, uint8_t const _sensorID);

protected:
	ConfigType configType;
	AxisConfigDescriptorType descriptorType;

	uint8_t headerRevision;
	uint8_t sensorRevision;
	uint8_t sensorID;
	unsigned length;
	std::vector<uint8_t> unparsedData;

	AxisConfig(ConfigType const config, AxisConfigDescriptorType const _descriptorType, uint8_t const _sensorID, uint8_t const _headerRevision, uint8_t const _sensorRevision);
	AxisConfig(ConfigType const config, uint8_t const* in, const unsigned _length);
	AxisConfig(ConfigType const config, std::wstring const& argString);
	virtual ~AxisConfig();
	AxisConfig(AxisConfig const&) = default;
	AxisConfig& operator = (AxisConfig const&) = default;

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

	void SetLength(std::vector<uint8_t>& out, size_t const offset, size_t const cfgLen) const;
};


struct INERTIA_API AxisConfigHeader
	: AxisConfig
{
	AxisConfigHeader(ConfigType const config, uint8_t const* in, const unsigned _length);

	void GetBytes(std::vector<uint8_t>& out) const override;
	const std::wstring ToString() const override;
	const std::wstring ToSimpleString(uint16_t const globalRate) const override;
	unsigned GetInstanceMask() const override;
};


typedef std::shared_ptr<AxisConfig> AxisConfigPtr; ///< Pointer to an AxisConfig.

}
