#pragma once

#include "data/config/GenericConfig.h"

namespace inertia
{

/** VmonBoardType */
enum VmonBoardType {
	VMON_NON_DIFF = 0,
	VMON_VOLTAGE_IEPE = 1
};

/** ChannelInputSelect */
enum ChannelInputSelect {
	STRAIGHT_TO_INSTR_AMP = 0,
	DECOUPLED_240K,
	DECOUPLED_24K,
	DECOUPLED_2_4K
};

/** ResistiveFeedbackSelect */
enum ResistiveFeedbackSelect {
	RESISTIVE_FEEDBACK_24K = 0,
	RESISTIVE_FEEDBACK_1M,
	RESISTIVE_FEEDBACK_10M,
	RESISTIVE_FEEDBACK_100M
};

/** CapacitiveFeedbackSelect */
enum CapacitiveFeedbackSelect {
	CAPACITIVE_FEEDBACK_10P = 0,
	CAPACITIVE_FEEDBACK_100P,
	CAPACITIVE_FEEDBACK_1N,
	CAPACITIVE_FEEDBACK_10N
};

struct INERTIA_API ChannelConfig {
	bool inputSelectEnable, resistiveFeedbackSelectEnable, capacitiveFeedbackSelectEnable,
		currentInjectEnable, gainPotEnable, currentInjectPotEnable;
	ChannelInputSelect inputSelect;
	ResistiveFeedbackSelect resistiveFeedback;
	CapacitiveFeedbackSelect capacitiveFeedback;
	uint8_t amplifierGain, injectCurrent;
	uint16_t lowPassCutoffFrequency;

	ChannelConfig();
	ChannelConfig(uint8_t const* in);
	ChannelConfig(std::wstring const& argString);

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

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

struct INERTIA_API IndustrialBoardNonDiff {
	VmonBoardType type;
	uint8_t stackPosition, ibndRevision;
	ChannelConfig channels[4];

	IndustrialBoardNonDiff();
	IndustrialBoardNonDiff(uint8_t const* in);
	IndustrialBoardNonDiff(std::wstring const& argString);

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

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

struct INERTIA_API IEPE_voltage {
	VmonBoardType type;
	bool enable, potEnable;
	uint8_t voltage;
	uint8_t reserved;

	IEPE_voltage();
	IEPE_voltage(uint8_t const* in);
	IEPE_voltage(std::wstring const& argString);

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

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

struct INERTIA_API VmonBoardConfig
	: GenericConfig
{
	std::vector<IndustrialBoardNonDiff> nonDiffBoards;
	IEPE_voltage voltageIEPE;

	VmonBoardConfig();
	VmonBoardConfig(uint8_t const* in);
	VmonBoardConfig(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;
	ConfigType GetConfigType() const override;
	const std::wstring ToString() const override;
};

}
