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

	Program:		Range Imaging Toolkit (RITK)
	Module:			ritkRImageFileSource.txx
	Version:		$Revision: 1846 $
	Date:			$Date: 2011-10-11 18:56:25 +0200 (Di, 11 Okt 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 "ritkRImageFileSource.h"

#include "ritkRImageIOManager.h"

#include <fstream>

namespace ritk
{

//----------------------------------------------------------------------------
template<class TRImage>
RImageFileSource<TRImage>
::RImageFileSource()
{
	// By default no file name and dirty flag
	m_FileName = "";
	m_FileNameDirtyFlag = true;

	// By default the first frame and dirty flag
	m_FrameID = 0;
	
	// The IO object is created dynamically
	m_IOPointer = 0;
}


//----------------------------------------------------------------------------
template<class TRImage>
RImageFileSource<TRImage>	
::~RImageFileSource()
{
	m_IOPointer = NULL;
}


//----------------------------------------------------------------------------
template<class TRImage>
void
RImageFileSource<TRImage>
::SetFileName(const char* FileName)
{
	if ( FileName && (FileName == m_FileName ) )
		return;
	if ( !FileName )
	{
		m_FileName = "";
	}
	else
	{
		m_FileName = FileName;
	}

	// Reset the frame
	SetFrameIndex(0);

	// Set dirty flags
	m_FileNameDirtyFlag = true;
	this->Modified();

	// The first line in the file determines the IO type
	std::ifstream InputStream;
	InputStream.open(m_FileName.c_str(),std::ios::in); //|std::ios::binary
	if ( !InputStream.is_open() )
		itkExceptionMacro(<<"Could not open input file!");
	std::string ImageType;
	InputStream >> ImageType;
	InputStream.close();
	
	// Delete old IO object.
	m_IOPointer = NULL;

	// Request the appropriate IO object
	m_IOPointer = RImageIOManager<TRImage>::GetInstance().RequestIOObject(ImageType.c_str());

	// Check if we can handle this image
	if ( !m_IOPointer )
	{
		itkExceptionMacro(<<"Could not determine IO mode for <" << ImageType << ">");
	}


	// Update the IO object
	m_IOPointer->SetFileName(FileName);
}


//----------------------------------------------------------------------------
template<class TRImage>
const char*
RImageFileSource<TRImage>
::GetFileName() const
{
	return m_FileName.c_str();
}



//----------------------------------------------------------------------------
template<class TRImage>
void
RImageFileSource<TRImage>
::SetFrameIndex(unsigned int id)
{
	if ( id == m_FrameID )
		return;
	m_FrameID = id;
	this->Modified();
}


//----------------------------------------------------------------------------
template<class TRImage>
unsigned int
RImageFileSource<TRImage>
::GetFrameIndex() const
{
	return m_FrameID;
}


//----------------------------------------------------------------------------
template<class TRImage>
unsigned int
RImageFileSource<TRImage>
::GetNumberOfFrames()
{
	return m_IOPointer->GetNumberOfFrames();
}

//----------------------------------------------------------------------------
template<class TRImage>
const std::vector<typename RImageFileSource<TRImage>::RImageType::TimeStampType>&
RImageFileSource<TRImage> 
::GetTimeStamps() const
{
	return m_IOPointer->GetTimeStamps();
}


//----------------------------------------------------------------------------
template<class TRImage>
void
RImageFileSource<TRImage>
::GetResolution(unsigned int *SX, unsigned int *SY)
{
	m_IOPointer->GetResolution(SX,SY);
}


//----------------------------------------------------------------------------
template<class TRImage>
void
RImageFileSource<TRImage>
::GenerateRImage()
{
	// Hold handle to the old output
	typename Superclass::OutputImagePointer OldOutput = this->GetOutput();

	// Set the new output
	if ( !m_IOPointer )
		itkExceptionMacro(<<"No IO object found! Did you forget to set the file name?");
	this->ProcessObject::SetNthOutput(0,m_IOPointer->ReadFrame(m_FrameID).GetPointer());
	this->GetOutput()->SetRequestedRegion(OldOutput->GetRequestedRegion());

	// Remember old output
	this->ProcessObject::SetNthOutput(1,OldOutput);
}


} // end namespace ritk
