/*======================================================================================

	Program:		Range Imaging Toolkit (RITK)
	Module:			ritkMain.cxx
	Version:		$Revision: 1761 $
	Date:			$Date: 2011-09-23 17:25:41 +0200 (Fr, 23 Sep 2011) $

	Copyright (c) 2010-2011
	Pattern Recognition Lab, 
    University Erlangen-Nuremberg, Germany
    All rights reserved.

	This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
	See RITKCopyright.txt for more information.

	http://www5.informatik.uni-erlangen.de/research/software/ritk

========================================================================================*/


#include <QApplication>

#include "ritkManager.h"
#include "ritkDebugManager.h"
#include <fstream>

#include <itkRescaleIntensityImageFilter.h>
#include <itkImageFileWriter.h>

#include <QTextStream>

#define PROGRESSBAR(Progress,TotalBars)					\
	std::cout << "\r0% [";								\
	int ActualBars = Progress*TotalBars;				\
	for ( int i = 0; i < ActualBars; i++ )				\
		std::cout << "=";								\
	for ( int i = ActualBars; i < TotalBars; i++ )		\
		std::cout << " ";								\
	std::cout << "] " << ((int)(Progress*100)) << "%";


/// Parse options; returns true if app should start afterwards
bool OptionsParser(int argc, char *argv[]);

/// Convert old TOF data to the new format (fileVersion: e.g. tof10, ritk1, ...)
void ConvertData(char *InputFile, char *OutputFile, char *FileVersion);

// Convert TOFKit v10 data to RITK v1 data
void ConvertTOFKit10ToRITK1(const char *InputFile, const char *OutputFile);

// Convert TOFKit v10 data to RITK v1 data
void ConvertTOFKit9ToTOFKit10(const char *InputFile, const char *OutputFile);


int main(int argc, char *argv[])
{
	// Parse options
	bool start = OptionsParser(argc, argv);

	//Q_INIT_RESOURCE(Resources);
	QApplication app(argc, argv);

	
  if(start)
  {
	  // Initialize the manager;
    ritk::Manager::GetInstance().Initialize();

      return app.exec();
  }
  else
    return 0;
}

bool OptionsParser(int argc, char *argv[])
{
    for ( int i = 0; i < argc; i++ )
    {
        if ( !strncmp(argv[i], "-d", 2) )
        {
          ritk::DebugManager::GetInstance().SetDebugMode(ritk::DebugManager::Disabled);
        } 
		    if ( !strncmp(argv[i], "-c", 2) )
		    {
			    if ( argc < i+4 )
			    {
				    std::cerr << "Invalid arguments for option -c" << std::endl;
				    exit(EXIT_FAILURE);
			    }
			    ConvertData(argv[i+1],argv[i+2],argv[i+3]);
         return false;
		    }
    }
    return true;
}

void ConvertData(char *InputFile, char *OutputFile, char *FileVersion)
{
  std::string tempDir = std::getenv("TEMP");
  tempDir += "\\temp.ris";

  if( !strcmp(FileVersion, "tof10") )
  {
    ConvertTOFKit10ToRITK1(InputFile, OutputFile);
  }

  if( !strcmp(FileVersion, "tof9") )
  {
    ConvertTOFKit9ToTOFKit10(InputFile, tempDir.c_str());
    ConvertTOFKit10ToRITK1(tempDir.c_str(), OutputFile);
  }

  // other versions need to be added with a second temp.ris


/*
	// Open input stream
	std::ifstream InStream;
	InStream.open(InputFile,std::ios::in|std::ios::binary);
	if ( !InStream.is_open() )
	{
		std::cerr << "Could not open input file <" << InputFile << ">" << std::endl;
		exit(EXIT_FAILURE);
	}

	// Open output stream
	std::ofstream OutStream;
	OutStream.open(OutputFile,std::ios::out|std::ios::trunc|std::ios::binary);
	if ( !OutStream.is_open() )
	{
		std::cerr << "Could not open output file <" << OutputFile << ">" << std::endl;
		exit(EXIT_FAILURE);
	}

	std::cout << "Converting <" << InputFile << ">..." << std::endl;

	// Buffer
	std::string Buffer;

	// First thing to do: write the identifier
	OutStream << "TOFImage" << std::endl;

	// Write the header. Start with the format version
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "FormatVersion		" << "1.0" << std::endl;

	// Image size
	unsigned int SizeX;
	unsigned int SizeY;
	InStream >> Buffer;
	InStream >> SizeX;
	InStream >> Buffer;
	InStream >> SizeY;
	OutStream << "SizeX		" << SizeX << std::endl;
	OutStream << "SizeY		" << SizeY << std::endl;

	// Camera model
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "CameraModel	" << Buffer << std::endl;

	// Integration time
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "IntegrationTime	" << Buffer << std::endl;

	// Modulation frequency
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "ModulationFrequency	" << Buffer << std::endl;

	// Focal point
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "FX	" << Buffer << std::endl;
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "FY	" << Buffer << std::endl;

	// Detector center
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "CX	" << Buffer << std::endl;
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "CY	" << Buffer << std::endl;

	// Undistortion parameters
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "K1	" << Buffer << std::endl;
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "K2	" << Buffer << std::endl;
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "K3	" << Buffer << std::endl;
	OutStream << std::endl;

	// Number of frames
	long NumFrames = 0;
	InStream >> Buffer;
	InStream >> NumFrames;
	OutStream << "NumFrames	";
	if ( NumFrames < 10 )
		OutStream << "00000";
	else if ( NumFrames < 100 )
		OutStream << "0000";
	else if ( NumFrames < 1000 )
		OutStream << "000";
	else if ( NumFrames < 10000 )
		OutStream << "00";
	else if ( NumFrames < 100000 )
		OutStream << "0";
	OutStream << NumFrames << std::endl;	

	// Set the stream position to the beginning of the data section
	InStream.seekg(((unsigned long)InStream.tellg())+1);
	

	// Now copy the actual data and insert a time stamp
	double TimeStamp = 0.;
	long BufferSize = SizeX*SizeY*sizeof(float)*2;
	char *DataBuffer = new char[BufferSize]; // Amplitudes and range values
	for ( long l = 0; l < NumFrames; l++ )
	{
		PROGRESSBAR(l/((float) NumFrames-1),20)

		InStream.read(DataBuffer,BufferSize);
		OutStream.write((char*)&TimeStamp,sizeof(double));
		OutStream.write(DataBuffer,BufferSize);
		TimeStamp += 0.04; // 25 fps
	}

	delete[] DataBuffer;

	// Close stream
	InStream.close();
	OutStream.close();
	std::cout << std::endl;
*/

}




void ConvertTOFKit10ToRITK1(const char *InputFile, const char *OutputFile)
{
	// Open input stream
	std::ifstream InStream;
	InStream.open(InputFile,std::ios::in|std::ios::binary);
	if ( !InStream.is_open() )
	{
		std::cerr << "Could not open input file <" << InputFile << ">" << std::endl;
		exit(EXIT_FAILURE);
	}

	// Open output stream
	std::ofstream OutStream;
	OutStream.open(OutputFile,std::ios::out|std::ios::trunc|std::ios::binary);
	if ( !OutStream.is_open() )
	{
		std::cerr << "Could not open output file <" << OutputFile << ">" << std::endl;
		exit(EXIT_FAILURE);
	}

	std::cout << "Converting <" << InputFile << ">..." << std::endl;

	// Buffer
	std::string Buffer;

	// First thing to do: write the identifier
	OutStream << "RImage" << std::endl;

	// Write the header. Start with the format version
	InStream >> Buffer;
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "FormatVersion		" << "1.0" << std::endl;
  	InStream >> Buffer;
    std::cout << Buffer << std::endl;
  	InStream >> Buffer;
    std::cout << Buffer << std::endl;
  	InStream >> Buffer;
    std::cout << Buffer << std::endl;
  	InStream >> Buffer;
    std::cout << Buffer << std::endl;

/*
	// Image size
	unsigned int SizeX;
	unsigned int SizeY;
	InStream >> Buffer;
	InStream >> SizeX;
	InStream >> Buffer;
	InStream >> SizeY;
	OutStream << "SizeX		" << SizeX << std::endl;
	OutStream << "SizeY		" << SizeY << std::endl;

	// Camera model
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "CameraModel	" << Buffer << std::endl;

	// Integration time
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "IntegrationTime	" << Buffer << std::endl;

	// Modulation frequency
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "ModulationFrequency	" << Buffer << std::endl;

	// Focal point
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "FX	" << Buffer << std::endl;
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "FY	" << Buffer << std::endl;

	// Detector center
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "CX	" << Buffer << std::endl;
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "CY	" << Buffer << std::endl;

	// Undistortion parameters
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "K1	" << Buffer << std::endl;
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "K2	" << Buffer << std::endl;
	InStream >> Buffer;
	InStream >> Buffer;
	OutStream << "K3	" << Buffer << std::endl;
	OutStream << std::endl;

	// Number of frames
	long NumFrames = 0;
	InStream >> Buffer;
	InStream >> NumFrames;
	OutStream << "NumFrames	";
	if ( NumFrames < 10 )
		OutStream << "00000";
	else if ( NumFrames < 100 )
		OutStream << "0000";
	else if ( NumFrames < 1000 )
		OutStream << "000";
	else if ( NumFrames < 10000 )
		OutStream << "00";
	else if ( NumFrames < 100000 )
		OutStream << "0";
	OutStream << NumFrames << std::endl;	

	// Set the stream position to the beginning of the data section
	InStream.seekg(((unsigned long)InStream.tellg())+1);
	

	// Now copy the actual data and insert a time stamp
	double TimeStamp = 0.;
	long BufferSize = SizeX*SizeY*sizeof(float)*2;
	char *DataBuffer = new char[BufferSize]; // Amplitudes and range values
	for ( long l = 0; l < NumFrames; l++ )
	{
		PROGRESSBAR(l/((float) NumFrames-1),20)

		InStream.read(DataBuffer,BufferSize);
		OutStream.write((char*)&TimeStamp,sizeof(double));
		OutStream.write(DataBuffer,BufferSize);
		TimeStamp += 0.04; // 25 fps
	}

	delete[] DataBuffer;
*/
	// Close stream
	InStream.close();
	OutStream.close();
	std::cout << std::endl;
}


void ConvertTOFKit9ToTOFKit10(const char *InputFile, const char *OutputFile)
{

}
