#include "KinectSDKSourcePlugin.h"
#include <QTimer>
#include <ritkDebugManager.h>
#include "ritkRImageIOManager.h"

KinectSDKSourcePlugin::KinectSDKSourcePlugin()
{
	// Create source
	m_Source = KinectSDKSourcePluginSourceType::New();
	
	std::cout << "Object initialized" << std::endl;

	// Initialize timer
	m_Timer = new QTimer();		
	m_Timer->stop();
	connect(m_Timer, SIGNAL(timeout()), this, SLOT(RequestFrame()));
 
	// Create GUI and connect player related buttons
	m_Widget = new KinectSDKSourcePluginWidget();
	
	// Connect elements from the widget
	connect(m_Widget->m_ConnectDisconnectPushButton,	SIGNAL(clicked()),	this,	SLOT(ConnectDisconnect())	);
	connect(m_Widget->m_PushButtonPause,		SIGNAL(clicked()),	this,	SLOT(Pause())			);
	connect(m_Widget->m_PushButtonPlayForward,	SIGNAL(clicked()),	this,	SLOT(Play())			);
	connect(m_Widget->m_PushButtonStepForward,	SIGNAL(clicked()),	this,	SLOT(RequestFrame())	);

	// Connect the UpdateGUI mechanism
	connect(this, SIGNAL(UpdateGUI()), m_Widget, SLOT(UpdateGUI()));

	// Default state
	SetState(Disconnected);

}


KinectSDKSourcePlugin::~KinectSDKSourcePlugin()
{
	// Clean up widget (this is mandatory!)
	if ( m_Widget )
		delete m_Widget;

	// Delete timer
	if ( m_Timer )
		delete m_Timer;

		// Disconnect reader
	if ( m_State == Playing )
		m_Source->Disconnect();


	//// Unregister the ImageIO
	//LOG_DEB("Unregistering KinectImageIO...");
	//ritk::RImageIOManager<ritk::RImageF2>::GetInstance().UnRegisterIOObject(m_KinectImageIO);
	//m_KinectImageIO = NULL;
}


//----------------------------------------------------------------------------
QWidget*
KinectSDKSourcePlugin::GetPluginGUI()
{
	return m_Widget;
}


//----------------------------------------------------------------------------
KinectSDKSourcePlugin::SourcePlugin::SourcePointer 
KinectSDKSourcePlugin::GetSource()
{	
	return (SourcePlugin::SourceType*)m_Source;
}


//----------------------------------------------------------------------------
void
KinectSDKSourcePlugin::SetState(StateType State)
{
	// Lock
	{
		QMutexLocker locker(&m_StateMutex);
		m_State = State;

		// Update widget
		if ( m_Widget )
		{
			switch ( m_State )
			{
			case Disconnected:
				//std::cout << "Setting state to disconnected..." << std::endl;
				m_Widget->m_PushButtonPause->setEnabled(false);
				m_Widget->m_PushButtonPlayForward->setEnabled(false);
				m_Widget->m_PushButtonStepForward->setEnabled(false);
				m_Widget->m_ConnectDisconnectPushButton->setText(tr("Connect"));
				break;
			case Connected:
				//std::cout << "Setting state to connected..." << std::endl;
				m_Widget->m_PushButtonPause->setEnabled(false);
				m_Widget->m_PushButtonPlayForward->setEnabled(true);
				m_Widget->m_PushButtonStepForward->setEnabled(true);
				m_Widget->m_ConnectDisconnectPushButton->setText(tr("Disconnect"));
				break;
			case Playing:
				//std::cout << "Setting state to playing..." << std::endl;
				m_Widget->m_PushButtonPause->setEnabled(true);
				m_Widget->m_PushButtonPlayForward->setEnabled(false);
				m_Widget->m_PushButtonStepForward->setEnabled(false);
				break;
			}
			emit UpdateGUI();
		}
	}
}

//----------------------------------------------------------------------------
void
KinectSDKSourcePlugin::ConnectDisconnect()
{

	
	// If we're connected we have to disconnect and vice versa
	if ( m_State == Connected || m_State == Playing )
	{
		// Disconnect Acquisition Pipeline
		if (m_State == Playing)
			Pause();

		std::cout << "Try to disconnect...";
		if ( m_State == Playing )
			m_Timer->stop();
		m_Source->Disconnect();
		SetState(Disconnected);
		std::cout << " disconnected!" << std::endl;
	}
	else
	{
		try
		{
			std::cout << "Try to connect...";
			m_Source->Connect();			
		}
		catch ( itk::ExceptionObject &e )
		{
			std::cerr << e << std::endl;
		}
		SetState(Connected);
		std::cout << " connected!" << std::endl;
	}
}

//----------------------------------------------------------------------------
void
KinectSDKSourcePlugin::Play()
{
	SetState(Playing);

	// Connecting to the pipeline's new frame signal will automaticall trigger a frame request
	connect(m_AcquisitionPipeline, SIGNAL(NewFrame()), this, SLOT(RequestFrame()) );

	// One initial request mandatory
	RequestFrame();
}


//----------------------------------------------------------------------------
void
KinectSDKSourcePlugin::Pause()
{
	disconnect(m_AcquisitionPipeline, SIGNAL(NewFrame()), this, SLOT(RequestFrame()) );
	SetState(Connected);
}


//----------------------------------------------------------------------------
void
KinectSDKSourcePlugin::RequestFrame()
{
	// ======================= //
	// Update your source here //
	// ======================= //
	// ...

	m_AcquisitionPipeline->Lock();

	// We need to modify the source
	m_Source->Modified();

	m_AcquisitionPipeline->Unlock();

	// Trigger pipeline execution
	m_AcquisitionPipeline->ExecuteOnce();
}
