// XTFReader.cpp: implementation of the CXTFReader class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "6046dryend.h"
#include "XTFReader.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

/*
WORD SwapWord (WORD *src)
{
	BYTE tt[2] ;
	BYTE *t = (BYTE *)(src) ;

	tt[1] = t[0] ;
	tt[0] = t[1] ;

	return *((WORD*)tt) ;
}

DWORD SwapDword(void *src)
{
	BYTE tt[4] ;
	BYTE *t = (BYTE *)(src) ;
	
	tt[0] = t[3];
	tt[1] = t[2];
	tt[2] = t[1];
	tt[3] = t[0];

	return *((DWORD*)tt);

}
*/
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CXTFReader::CXTFReader()
{
	fileOpen	= FALSE;
	ip			= 0;
	numChannels = 0;

	m_pCIma			= NULL;
	fileHeader		= NULL;
	commonHeader	= NULL;
	pingHeader		= NULL;
	pingChanHeader	= NULL;
	m_pCIma			= NULL;

}

CXTFReader::~CXTFReader()
{

}

//Return TRUE if ping ready
BOOL CXTFReader::InitReader(CString path, HWND parent)
{
	if(path.GetLength() > 0)
		requestedFile = path;
	else
		return FALSE;  //empty path given

	if(parent)
		m_hParentWnd = parent;

	if(fileOpen)
		CloseFile();

	OpenXTF_File();

	if(fileOpen)
		return TRUE;

	return FALSE;

}

BOOL CXTFReader::Shutdown()
{
  if(fileHeader)
  {
	  delete fileHeader;
	  fileHeader = NULL;
  }
  if(commonHeader)
  {
	  delete commonHeader;
	  commonHeader = NULL;
  }
  if(pingHeader)
  {
	  delete pingHeader;
	  pingHeader = NULL;
  }
  if(pingChanHeader)
  {
	  delete pingChanHeader;
	  pingChanHeader = NULL;
  }
  if(m_pCIma)
  {
	  delete [] m_pCIma;
	  m_pCIma = NULL;
  }
  if(commonHeader)
  {
	  delete [] m_pSIma;
	  m_pSIma = NULL;
  }
	

  return TRUE;
}

//private
void CXTFReader::OpenXTF_File()
{
	if(fileHeader == NULL)
		fileHeader		= new SXtfFileHeader ;

	if(commonHeader == NULL)
		commonHeader	= new SXtfCommonPartHeader ;

	if(pingHeader == NULL)
		pingHeader		= new SXtfPingHeader ;

	if(pingChanHeader == NULL)
		pingChanHeader  = new SXtfPingChanHeader ;

	
	// open the source file for reading
   if (!m_File.Open(requestedFile, CFile::modeRead | CFile::shareDenyWrite | CFile::typeBinary , &ex))
   {
		fileOpen = FALSE;
		return;
   }

   fileOpen = TRUE;
   
   
   //Read in and check header validity
   int head = m_File.Read(fileHeader, sizeof(SXtfFileHeader)) ;
   if(head < sizeof(SXtfFileHeader))
   {
	   fileOpen = FALSE;
	   return;
   }
   
   // just in case of old 6042 v5 xtf, this value will be overwritten if available in pingchanheader
   nSamplesPerChan = ((fileHeader->ChanInfo[0]).Reserved) ;	
   m_BytesPerSamples = (int)((fileHeader->ChanInfo[0]).BytesPerSample) ; // Assume the same values for all channels

   
}

BOOL CXTFReader::AnalyzeFile()
{
	//Read in and check header validity
   int head = m_File.Read(fileHeader, sizeof(SXtfFileHeader)) ;
   if(head < sizeof(SXtfFileHeader))
	   return FALSE;
   
   // just in case of old 6042 v5 xtf, this value will be overwritten if available in pingchanheader
   nSamplesPerChan = ((fileHeader->ChanInfo[0]).Reserved) ;	
   m_BytesPerSamples = (int)((fileHeader->ChanInfo[0]).BytesPerSample) ; // Assume the same values for all channels

   //Read in and check common header validity
   int read = m_File.Read(commonHeader, sizeof(SXtfCommonPartHeader));
   if(read < sizeof(SXtfCommonPartHeader))
		return FALSE;

	
    int currentOffset = m_File.GetPosition();

	if ( commonHeader->HeaderType == 0)
	{
		currOff = 0 ;
		m_File.Seek(-(LONG)sizeof(SXtfCommonPartHeader),CFile::current) ;
		startPos = m_File.GetPosition() ;
		m_File.Read(pingHeader,sizeof(SXtfPingHeader)) ;

		numChannels = pingHeader->NumChansToFollow;
	}
	
	m_File.Seek(currentOffset, CFile::begin);

	return TRUE;
}

void CXTFReader::CloseFile()
{
	int x = -1;
	if(m_File.m_hFile != (UINT)x)
		m_File.Close();
	
	numChannels = 0;
}


BYTE* CXTFReader::GetPing()
{
	if(m_pCIma)
	{
		delete [] m_pCIma;
		m_pCIma = NULL;
	}
	m_pCIma	= new unsigned char  [500000] ;
	
	int read = m_File.Read(commonHeader, sizeof(SXtfCommonPartHeader));
	if(read < sizeof(SXtfCommonPartHeader))
	{	
		//EOF
		PostMessage(m_hParentWnd, FILE_READ_DONE, 0, 0);
		return NULL;
	}

	if ( commonHeader->HeaderType == 0)
	{
		currOff = 0 ;
		m_File.Seek(-(LONG)sizeof(SXtfCommonPartHeader),CFile::current) ;
		startPos = m_File.GetPosition() ;
		read = m_File.Read(pingHeader,sizeof(SXtfPingHeader)) ;
		if(read < sizeof(SXtfPingHeader))
		{	
		//EOF
		PostMessage(m_hParentWnd, FILE_READ_DONE, 0, 0);
		return NULL;
		}

		// makes this assumption that one sss file contains only 2 channels
		// First two channels
		for (int ic=0;ic<2;ic++)
		{
			read = m_File.Read(pingChanHeader,sizeof(SXtfPingChanHeader)) ;
			if(read < sizeof(SXtfPingChanHeader))
			{	
				//EOF
				PostMessage(m_hParentWnd, FILE_READ_DONE, 0, 0);
				return NULL;
			}
			
			if (pingChanHeader->NumSamples != 0)
			{
				nSamplesPerChan = pingChanHeader->NumSamples ;
				if(nSamplesPerChan > (500000-currOff))
					return NULL;
			}
			// we make the assumption that the channels are in proper order: PORT then STARBOARD
			if (m_BytesPerSamples == 1)
				m_File.Read(m_pCIma+currOff, m_BytesPerSamples*nSamplesPerChan) ;
			else
				m_File.Read(m_pSIma+currOff, m_BytesPerSamples*nSamplesPerChan) ;

			currOff += nSamplesPerChan;
		}
		m_File.Seek( startPos+(pingHeader->NumBytesThisRecord)-(m_File.GetPosition()), CFile::current) ;
	}
	else{
		m_File.Seek(commonHeader->NumBytesThisRecord - sizeof(SXtfCommonPartHeader), CFile::current) ;
		return NULL;
	}

	return m_pCIma;
}

void CXTFReader::ResetFile()
{
	CloseFile();
	Shutdown();
	InitReader(requestedFile,m_hParentWnd);

}

DWORD CXTFReader::GetSamples()
{
	return nSamplesPerChan*2;
}

DWORD CXTFReader::GetRoll()
{
	return pingHeader->SensorRoll;

}
DWORD CXTFReader::GetPitch()
{
	return pingHeader->SensorPitch;
}

DWORD CXTFReader::GetHeave()
{
	return pingHeader->SensorPrimaryAltitude;
}

DWORD CXTFReader::GetHeading()
{
	return pingHeader->SensorHeading;
}

