#include "stdafx.h"
#include "msg.h"

//#define _FILE_TRANSFER_DEBUG

#ifdef _FILE_TRANSFER_DEBUG

#include "tss.h"
#include "video.new\debug.h"

#endif

IMPLEMENT_SERIAL(Msg, CNetObject, 1)
IMPLEMENT_SERIAL(Event, Msg, 1)
IMPLEMENT_SERIAL(React, Msg, 1)
IMPLEMENT_SERIAL(MsgFile, CNetObject, 1)

void Msg::Serialize(CArchive& ar)
{
	CNetObject::Serialize(ar);

	if (ar.IsStoring())
	{
		ar << m_sSourceType;
		ar << m_sSourceId;
		ar << m_sAction;
	}
	else
	{
		ar >> m_sSourceType;
		ar >> m_sSourceId;
		ar >> m_sAction;
	}
	m_mapParams.Serialize(ar);
}

#define BUF_SIZE   1024*64
//BYTE buf[BUF_SIZE];

MsgFile::MsgFile(LPCTSTR file_from, LPCTSTR file_to) : CNetObject()
{
	m_sFileNameSrc = file_from;

	if (*file_to)
		m_sFileName	= file_to;
	else
		m_sFileName	= file_from + (strlen(file_from)>1 && file_from[1]==':' ? 2 : 0);

	HANDLE hFile = ::CreateFile(m_sFileNameSrc,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

	if (hFile!=INVALID_HANDLE_VALUE)
	{
		GetFileTime(hFile,&m_ftCreationTime,&m_ftLastAccessTime,&m_ftLastWriteTime);

		CloseHandle(hFile);

		m_bOK = TRUE;
	}
	else
		m_bOK = FALSE;
}

void MsgFile::Serialize(CArchive& ar)
{
	CNetObject::Serialize(ar);

	if (ar.IsLoading())
	{
		//only filename received, need to construct local path
		ar >> m_sFileName;

		ar >> m_dwSize;

		DWORD length = m_dwSize;

		CFile file;
		if (length && !m_sFileName.IsEmpty() && file.Open(m_sFileName, 
				CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite))
		{
			ar >> m_ftCreationTime.dwLowDateTime;
			ar >> m_ftCreationTime.dwHighDateTime;

			ar >> m_ftLastAccessTime.dwLowDateTime;
			ar >> m_ftLastAccessTime.dwHighDateTime;

			ar >> m_ftLastWriteTime.dwLowDateTime;
			ar >> m_ftLastWriteTime.dwHighDateTime;

#ifdef _FILE_TRANSFER_DEBUG
			CString sss;
			CTime time(m_ftLastWriteTime);
			TSS tss(time);
			tss.Time2Str(sss);
			debugMsg("Received file last write time: "+sss);
			CTime time2(m_ftCreationTime);
			TSS tss2(time2);
			tss2.Time2Str(sss);
			debugMsg("Received file creation   time: "+sss);
/*
			ar >> vvv;
			ar >> sss;

			tss.Str2Date(vvv);
			tss.Str2Time(sss);

			SYSTEMTIME st;
			st.wDayOfWeek = 0;
			st.wDay = tss.day;
			st.wMonth = tss.month;
			st.wYear = tss.year;
			st.wHour = tss.hour;
			st.wMinute = tss.minute;
			st.wSecond = tss.second;
			st.wMilliseconds = 0;

			SystemTimeToFileTime(&st,&m_ftCreationTime);
			SystemTimeToFileTime(&st,&m_ftLastAccessTime);
			SystemTimeToFileTime(&st,&m_ftLastWriteTime);

			CTime time3(m_ftCreationTime);
			TSS tss3(time3);

			CString s;
			tss3.Time2Str(s);

			s.Format("%u,%u - ",m_ftLastWriteTime.dwLowDateTime,m_ftLastWriteTime.dwHighDateTime);

			debugMsg("Received alternate write time: "+s+vvv+" "+sss);
*/
#endif

			CByteArray buf;
			buf.SetSize(BUF_SIZE); //prevent trashing min(length, BUF_SIZE));

			UINT bytes;

			do
			{
				bytes = ar.Read(buf.GetData(), min(length, BUF_SIZE));
				file.Write(buf.GetData(), bytes);

				length -= bytes;
			}
			while (length > 0);

			file.Close();

			HANDLE hFile = ::CreateFile(m_sFileName,GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

			if (!SetFileTime(hFile,&m_ftCreationTime,&m_ftLastAccessTime,&m_ftLastWriteTime))
			{
#ifdef _FILE_TRANSFER_DEBUG
				debugMsg("Can't set file time");
#endif
			}

			CloseHandle(hFile);
		}
	}
	else
	{
		m_dwSize = 0;

		ar << m_sFileName;

		HANDLE hFile = ::CreateFile(m_sFileNameSrc,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

		if (hFile!=INVALID_HANDLE_VALUE && !GetFileTime(hFile,&m_ftCreationTime,&m_ftLastAccessTime,&m_ftLastWriteTime))
		{
#ifdef _FILE_TRANSFER_DEBUG
			debugMsg("Can't get file time");
#endif
		}

		CloseHandle(hFile);

		CFile file;

		if (!m_sFileNameSrc.IsEmpty() && file.Open(m_sFileNameSrc, 
				CFile::modeRead|CFile::shareDenyWrite))
		{
			DWORD length = m_dwSize = file.GetLength();

			ar << m_dwSize;

			if (length)
			{
				ar << m_ftCreationTime.dwLowDateTime;
				ar << m_ftCreationTime.dwHighDateTime;

				ar << m_ftLastAccessTime.dwLowDateTime;
				ar << m_ftLastAccessTime.dwHighDateTime;

				ar << m_ftLastWriteTime.dwLowDateTime;
				ar << m_ftLastWriteTime.dwHighDateTime;

#ifdef _FILE_TRANSFER_DEBUG
				CString sss;
				CTime time(m_ftLastWriteTime);
				TSS tss(time);
				tss.Time2Str(sss);
				debugMsg("Transfered file last access time: "+sss);
				CTime time2(m_ftCreationTime);
				TSS tss2(time2);
				tss2.Time2Str(sss);
				debugMsg("Transfered file creation    time: "+sss);
#endif
				CByteArray buf;
				buf.SetSize(BUF_SIZE); //prevent trashing min(length, BUF_SIZE));

				UINT bytes;
				
				while((bytes = file.Read(buf.GetData(), 
					min(length, BUF_SIZE))) > 0)
				{
					ar.Write(buf.GetData(), bytes);

					length -= bytes;
				}
			}

			file.Close();

//			WIN32_FIND_DATA fd;
//			::FindClose(::FindFirstFile(m_sFileNameSrc, &fd));
/*
			HANDLE hFile = ::CreateFile(m_sFileNameSrc,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

			if (!GetFileTime(hFile,&m_ftCreationTime,&m_ftLastAccessTime,&m_ftLastWriteTime))
			{
#ifdef _FILE_TRANSFER_DEBUG
				debugMsg("Can't get file time");
#endif
			}

			CloseHandle(hFile);
*/
/*			ar << fd.ftCreationTime.dwLowDateTime;
			ar << fd.ftCreationTime.dwHighDateTime;

			ar << fd.ftLastAccessTime.dwLowDateTime;
			ar << fd.ftLastAccessTime.dwHighDateTime;

			ar << fd.ftLastWriteTime.dwLowDateTime;
			ar << fd.ftLastWriteTime.dwHighDateTime;
*/
		}
		else
			ar << m_dwSize;
	}
}
/*
    if (ar.IsStoring())
	{
		CFile file;
		if (!file.Open(m_sFileNameSrc, CFile::modeRead))
		{
			ar << CString();
			return;
		}
		DWORD size = file.GetLength();
		ar << m_sFileName;
		ar << m_sFileNameSrc;
		ar << size;
		ar.Flush();
		CFile* fp = ar.GetFile();
		UINT n;
		for (int i=0;i<size;i+=4096)
		{
			n = file.Read(buf,4096);
			fp->Write(buf,n);
		}
		n = file.Read(buf,size%4096);
		fp->Write(buf,n);
	}
	else
	{
		ar >> m_sFileName;
		if (!m_sFileName.IsEmpty())
		{
			DWORD size;
			ar >> m_sFileNameSrc;
			ar >> size;
			ar.Flush();
			CFile* fp = ar.GetFile();
			CFile file;
			file.Open(m_sFileName, CFile::modeCreate | CFile::modeWrite);
			UINT n;
			for (int i=0;i<size;i+=4096)
			{
				n = fp->Read(buf,4096);
				file.Write(buf,n);
			}
			n = fp->Read(buf,size%4096);
			file.Write(buf,n);
		}
	}
}
*/

/*
void React::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		ar << m_dwPlayTime;
		ar << m_dwStartDelay;
	}
	else
	{
		ar >> m_dwPlayTime;
		ar >> m_dwStartDelay;
	}

	Msg::Serialize(ar);
}
*/
