#ifndef VOLUMELOADER_H
#define VOLUMELOADER_H

#include <QObject>

/*!
\file
This file includes the \ref VolumeLoader class, as well as the \ref VolumeMetaData structure.
*/

/*!
This class contains metadata for volumes, like dimensions and the file where the data can be found.
*/
struct VolumeMetaData
{
	/*!
	Derived from the metadata file name
	*/
	QString name;

	/*!
	Defines the supported data types.
	The actual range of values is found during gradient calculation.
	*/
	enum class VolumeDataType
	{
		/*!
		8-bit unsigned integer
		*/
		uchar=8,
		/*!
		16-bit unsigned integer
		*/
		ushort=16
	} type;

	//the actual amount of data used for each voxel, if different from the data type
	//if zero, means that the full value range is used
	uchar actualBits;

	//maps to x, y, z coordinates
	uint width;
	uint height;
	uint depth;

	//aspect ratios, currently not used
	float aspectX;
	float aspectY;
	float aspectZ;

	//how many bytes to skip in the datafile (removing custom headers)
	uint skipBytes;
	QString dataFile;

	//identification of volume source
	QString source;

	inline static QString enumToString(const VolumeDataType type)
	{
		switch (type)
		{
		case VolumeDataType::uchar:
			return "uchar";
		case VolumeDataType::ushort:
			return "ushort";
		default:
			return "unknown";
		}
	}

	inline static VolumeDataType stringToEnum(const QString& str)
	{
		if(str.compare("ushort",Qt::CaseInsensitive)==0)
			return VolumeDataType::ushort;
		else
			return VolumeDataType::uchar;
	}
};

/*!
Class for loading volume meta data (\ref VolumeMetaData) as well as the raw volume data itself.
This uses a simple custom format for metadata, which is built on the Qt .ini file functionality provided
by the \c QSettings class. Look at the example volumes to see the format, it is pretty straightforward.
The loader supports reading gzipped volumes, through the gzip-library provided by Qt.
*/
class VolumeLoader : public QObject
{
	Q_OBJECT
public:
	explicit VolumeLoader(QObject *parent = nullptr);
	~VolumeLoader();

	/*!
	Reads the metadata of a file.
	\param metadataFile The file which contains the metadata.
	\param metadata The structure in which to store the return value
	\return true if loading ok, false if error
	*/
	bool getMetadata(const QFile& metadataFile,VolumeMetaData& metadata) const;

	/*!
	Reads the volume represented by this metadata.
	Can handle gzipped data files.
	\return a byte array of the volume data, or an empty one on error
	*/
	QByteArray readVolume(const VolumeMetaData& d) const;
private:
	bool readGZippedVolume(QFile& src,QByteArray& dest) const;
};

QDebug operator<<(QDebug dbg, const VolumeMetaData& c);

#endif // VOLUMELOADER_H
