#pragma once

#include "volumeshop.h"

#include "Environment.h"
#include "Exporter.h"
#include "Volume.h"
#include "DataVoxel.h"
#include "Exception.h"

class ExporterSelectionVolumeDat : public Exporter
{
public:

	ExporterSelectionVolumeDat(Environment & envEnvironment) : m_envEnvironment(envEnvironment), m_fProgress(0.0f)
	{
	};

	virtual ~ExporterSelectionVolumeDat()
	{
	};

	Environment & GetEnvironment()
	{
		return m_envEnvironment;
	};

	virtual const bool IsAccepted(const std::string & strFilename)
	{		
		std::string strLower(strFilename);
		std::transform(strFilename.begin(), strFilename.end(), strLower.begin(), tolower);

		std::vector<std::string> vecExtensions;
		vecExtensions.push_back("dat");

		for (unsigned int i=0;i<vecExtensions.size();i++)
			if (strLower.substr(strLower.size()-vecExtensions[i].size()) == vecExtensions[i])
				return true;

		return false;
	};

	virtual void save(const std::string & strFilename)
	{
		m_fProgress = 0.0f;

		std::cout << "Saving file: " << strFilename << " ... " << std::endl;
		FILE *fp = fopen(strFilename.c_str(),"wb");

		if (!fp)
		{
			std::cerr << "Error saving file." << std::endl << std::endl;
			throw Exception("Error saving file '%s'.",strFilename.c_str());
		}

		const unsigned short uSizeX = GetEnvironment().GetSelectionVolume().GetSizeX();
		const unsigned short uSizeY = GetEnvironment().GetSelectionVolume().GetSizeY();
		const unsigned short uSizeZ = GetEnvironment().GetSelectionVolume().GetSizeZ();

		std::cout << "Volume dimensions: (" << uSizeX << "," << uSizeY << "," << uSizeZ << ")" << std::endl;

		fwrite(&uSizeX,sizeof(unsigned short),1,fp);
		fwrite(&uSizeY,sizeof(unsigned short),1,fp);
		fwrite(&uSizeZ,sizeof(unsigned short),1,fp);

		const unsigned int uSlice = GetEnvironment().GetSelectionVolume().GetSizeX() * GetEnvironment().GetSelectionVolume().GetSizeY();
		const unsigned int uSize = uSlice * GetEnvironment().GetSelectionVolume().GetSizeZ();
		short *pData = new short[uSlice];

		for (unsigned int uZ=0;uZ<GetEnvironment().GetSelectionVolume().GetSizeZ();uZ++)
		{
			std::cout << "  " << (100 * uZ) / GetEnvironment().GetSelectionVolume().GetSizeZ() << " %" << "\r";
			m_fProgress = float(uZ) / float(GetEnvironment().GetSelectionVolume().GetSizeZ());

			for (unsigned int uY=0;uY<GetEnvironment().GetSelectionVolume().GetSizeY();uY++)
			{
				for (unsigned int uX=0;uX<GetEnvironment().GetSelectionVolume().GetSizeX();uX++)
				{
					short & sValue = pData[uX+uY*GetEnvironment().GetSelectionVolume().GetSizeX()];
					sValue = short(GetEnvironment().GetSelectionVolume().Get(uX,uY,uZ).Get() * 4095.0f);
				}
			}

			fwrite(pData,sizeof(short),uSlice,fp);
		}

		delete[] pData;

		fclose(fp);

		std::string strAdditionalFilename;
		size_t uIndex = strFilename.find_last_of('.');
		strAdditionalFilename = strFilename.substr(0,uIndex);
		strAdditionalFilename += std::string(".ini");

		char vpAdditionalFilepath[1024];
		char *pAdditionalFilename;
		GetFullPathName(strAdditionalFilename.c_str(),1024,vpAdditionalFilepath,&pAdditionalFilename);

		WritePrivateProfileString("DatFile","oldDat Spacing X",toString(GetEnvironment().GetSelectionVolume().GetScale().GetX()).c_str(),vpAdditionalFilepath);
		WritePrivateProfileString("DatFile","oldDat Spacing Y",toString(GetEnvironment().GetSelectionVolume().GetScale().GetY()).c_str(),vpAdditionalFilepath);
		WritePrivateProfileString("DatFile","oldDat Spacing Z",toString(GetEnvironment().GetSelectionVolume().GetScale().GetZ()).c_str(),vpAdditionalFilepath);

		std::cout << "Success saving file." << std::endl << std::endl;
		
		m_fProgress = 1.0f;
	};

	virtual const float GetProgress()
	{
		return m_fProgress;
	};

private:

	Environment & m_envEnvironment;
	float m_fProgress;
};