// Raytrix API LF Progress Example 01
/*
	This example demonstrates how to define a progress class
	derived from IProgress to display the progress of a depth calculation.
*/

#include <SDKDDKVer.h>
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <conio.h>

// The Raytrix Core library
#include "Rx.Core\RxCore.h"

// The Raytrix Light Field API
#include "Rx.ApiLF\Rx.ApiLF.h"

// Include CLUViz Tool DLL to display/load/save images.
#include "Rx.CluViz.Core.CluVizTool\CvCluVizTool.h"


using namespace Rx;
using namespace Rx::ApiLF;


////////////////////////////////////////////////////////////
class CMyProgress
{
protected:
	std::string m_sName;
	int m_iValue, m_iMax;

public:
	CMyProgress( const char* pcName )
	{
		m_sName = pcName;
		m_iValue = m_iMax = 0;
	}

	// Override the abstract functions of IProgress
	bool Init( int iMax )
	{
		m_iMax = iMax;

		printf( "%s starting...\n", m_sName.c_str() );
		Display();
		return true;
	}

	bool Increment( int iValue )
	{
		m_iValue += iValue;
		Display();
		return true;
	}

	bool SetValue( int iValue )
	{
		m_iValue = iValue;
		Display();
		return true;
	}

	bool Finished()
	{
		m_iValue = m_iMax;
		Display();
		printf( "%s finished.\n", m_sName.c_str() );
		return true;
	}

	// Display the current progress
	void Display()
	{
		double dValue = double(m_iValue) / double(m_iMax) * 100.0;
		printf( "%s: %.2f%%\n", m_sName.c_str(), dValue );
	}
};


void __stdcall OnStatusMessage(Rx::ApiLF::EStatusSource::ID eSource, Rx::ApiLF::EStatusMessage::ID eMsg, const char* pcSourceName, const char* pcMessage, int iValue, void *pvContext)
{
	if ( (int(eMsg) & int(EStatusMsgGrp::Text)) != 0 )
	{
		printf("%s: %s\n", pcSourceName, pcMessage);
	}
	else if ( (int(eMsg) & int(EStatusMsgGrp::Progress)) != 0 )
	{
		if ( !pvContext )
			return;

		CMyProgress *pProg = (CMyProgress*) pvContext;

		switch(eMsg)
		{
		case EStatusMessage::Progress_Init:
			pProg->Init(iValue);
			break;

		case EStatusMessage::Progress_Step:
			pProg->Increment(iValue);
			break;

		case EStatusMessage::Progress_Value:
			pProg->SetValue(iValue);
			break;

		case EStatusMessage::Progress_Finished:
			pProg->Finished();
			break;
		}
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	int iView = 0;
	unsigned uImgID = 0;
	CRxString sxPath, sxFile;
	CRxImage xImage;
	CMyProgress xMyProg("Camera initialization");

	//// Initialize CLUVizTool
	//printf("Initializing CLUViz...\n");
	//CLUViz::Tool::Init();	

	//// Create an image view
	//printf("Create image view...\n");
	//CLUViz::Tool::CreateViewImage( iView, 600, 100, 800, 600, "Image" );

	try
	{
		// Initialize Raytrix Library
		printf("Initializing API...\n");
		RX_TRY( RxInit(true, "", "", 0) );

		// Automatic CUDA device selection if no device ID or a negative device ID is given.
		RX_TRY( RxCudaSelectDevice() );

		//// Construct path to ray image
		//sxFile = "..\\ExampleImages\\Demo_01.ray";

		//// Load a ray image
		//printf("Loading ray image: %s\n", sxFile.ToCString() );
		//RX_TRY( RxRayLoad(uImgID, sxFile) );

		//// Bind the loaded ray image. This copies the ray image to the CUDA device.
		//RX_TRY( RxRayBind( uImgID ) );

		//// Set the output depth image type to relative depth
		//// so that the depth values lie in the range [0,1]
		//RX_TRY( RxSetPar( EPar::Depth_ImageType, unsigned(EDepthImageType::Relative) ) );

		// Set progress interface for depth calculation
		RX_TRY( RxAddStatusMessageHandler( &OnStatusMessage, &xMyProg ) );

		//// Evaluate depth. Calls functions of progress interface.
		//RX_TRY( RxDepth( true ) );
		
		RX_TRY( RxCamDriverInit() );
		RX_TRY( RxCamRegister() );

		// Reset progress interface.
		RX_TRY( RxRemoveStatusMessageHandler( &OnStatusMessage, &xMyProg ) );

		//// Get execution total time of depth calculation (only CUDA kernel times)
		//double dT = RxGetLastExecTime();
		//printf("Depth evaluation execution time: %gms\n", dT );

		//// Get focused image from CUDA device
		//RX_TRY( RxGetImage( EImgID::Depth, xImage ) );

		//// Display the image
		//CLUViz::Tool::ViewSetImage( iView, &xImage );

		//// Save image
		//sxFile = "..\\ExampleImages\\Demo_Depth.png";
		//CLUViz::Tool::WriteImage( sxFile.ToCString(), &xImage );

		// Wait for user to press any key.
		printf("Press any key...\n");
		_getch();

	}
	catch( int iError )
	{
		printf("Press any key to end program...\n");
		_getch();
		return iError;
	}

	//// Close all CLUViz Windows and free internally used memory
	//CLUViz::Tool::Finalize();

	// Close Raytrix API, free all memory on host and CUDA device
	// and close all open cameras.
	RxFinalize();

	return 0;
}

