#pragma once

namespace inertia
{

/** The value type of a ChannelSpec, corresponds with for example a sensor. */
enum ValueType : unsigned {
	VALUE_TYPE_DISABLED = 0, ///< Disabled.
	VALUE_TYPE_ACCEL,        ///< Accelerometer: index 0=X, 1=Y, 2=Z.
	VALUE_TYPE_COMPASS,      ///< Compass: index 0=X, 1=Y, 2=Z.
	VALUE_TYPE_GYRO,         ///< Gyroscope: index 0=X, 1=Y, 2=Z.
	VALUE_TYPE_TEMP,         ///< Temperature: index 0.
	VALUE_TYPE_ACCEL_HIGH_G, ///< High-G Accelerometer: index 0=X, 1=Y, 2=Z.
	VALUE_TYPE_PRESSURE,     ///< Pressure: index 0.
	VALUE_TYPE_IMA,          ///< IMA: represents the index within the IMA values.
	VALUE_TYPE_ADC,          ///< ADC: represents the analog input index.
	VALUE_TYPE_ORIENTATION,  ///< Orientation: index 0 to 3 represent the quaternion values.
	VALUE_TYPE_STATUS,       ///< Status values: 0=bat, 1=cpuTemp, 2=extIn, 3=rssi, 4=N.A., 5=lostSamples.
	VALUE_TYPE_GPS,          ///< GPS values: same order as GPS header.
	VALUE_TYPE_CUSTOM,       ///< Custom values.
	MAX_VALUE_TYPES
};


/** Available indexes for VALUE_TYPE_STATUS. */
enum ValueIndexStatus : unsigned {
	VALUE_INDEX_STATUS_BAT_VOLTAGE = 0,         ///< Battery voltage.
	VALUE_INDEX_STATUS_TEMP_INSIDE,             ///< Inside temperature / CPU temperature.
	VALUE_INDEX_STATUS_POWER_INPUT_PRESENT,     ///< Power Voltage / External input.
	VALUE_INDEX_STATUS_RSSI,                    ///< Radio Signal Strength (RSSI).
	VALUE_INDEX_STATUS_LOST_SAMPLES_PERCENTAGE, ///< Lost samples percentage.
	VALUE_INDEX_STATUS_LOST_SAMPLES,            ///< Lost samples.
	VALUE_INDEX_STATUS_BAT_SOC,                 ///< Battery percentage.
	VALUE_INDEX_STATUS_TEMP_AMBIENT,            ///< Ambient temperature.
	VALUE_INDEX_STATUS_POWER_INPUT_VOLTAGE,     ///< Power input voltage.
	VALUE_INDEX_STATUS_POWER_CONSUMPTION,       ///< Power consumption.
	VALUE_INDEX_STATUS_BAT_PERCENTAGE,          ///< Battery percentage. Not used anymore, use VALUE_INDEX_STATUS_BAT_SOC instead.
	VALUE_INDEX_STATUS_CHARGE_CURRENT,          ///< Charge current.
	MAX_VALUE_INDEX_STATUS
};


/** A function that is performed over all values in a group of a ChannelSpec. */
enum GroupFunction : unsigned {
	GROUP_FUNCTION_NONE = 0, ///< No group function.
	GROUP_FUNCTION_NORM,     ///< Apply normalization function. The resulting value is at index 0.
	GROUP_FUNCTION_EULER,    ///< Get Euler angles of ::VALUE_TYPE_ORIENTATION, use index 0=roll, 1=pitch, 2=yaw.
	MAX_GROUP_FUNCTIONS
};


/** A function that is performed over a single value in a ChannelSpec. */
enum ValueFunction : unsigned {
	VALUE_FUNCTION_NONE = 0, ///< No value function.
	VALUE_FUNCTION_FFT,      ///< Fast Fourier Transform of value.
	MAX_VALUE_FUNCTIONS
};


/** @brief %Channel Specification.
 *
 *  A struct for a sensor channel type. Can be used to specify a specific (combination of) sensor value(s).
 */
struct INERTIA_API ChannelSpec
{
	ValueType valueType;         ///< The type is used to target a specific sensor type.
	unsigned index;              ///< The index is used to target a specific axis or index of a sensor.
	unsigned group;              ///< The group that the index belongs to, always 0 expect for ::VALUE_TYPE_CUSTOM were it is the used sampling channel.
	ValueFunction valueFunction; ///< A function that is applied to the targeted value.
	GroupFunction groupFunction; ///< A function that is applied to all values in a group.

	/** Default constructor. */
	ChannelSpec();

	/** Constructor with individual arguments.
	 *  @param valueType the valueType
	 *  @param index the index
	 *  @param group the group
	 *  @param groupFunction the groupFunction
	 *  @param valueFunction the valueFunction
	 */
	ChannelSpec(const ValueType valueType, const unsigned index = 0, const unsigned group = 0, const GroupFunction groupFunction = GROUP_FUNCTION_NONE, const ValueFunction valueFunction = VALUE_FUNCTION_NONE);

	/** Get a description of the settings.
	 *  @return a string description
	 */
	const std::wstring ToString() const;

	/** Less than operator.
	 *  @param rhs object to compare to
	 *  @return true when this is less than rhs.
	 */
	bool operator < (ChannelSpec const& rhs) const;
};

}
