#include "MemUtils.h"
#include "ProStructs.h"
#include "IC_Errors.h"
#include "ADFS_LogFile.h"
#include "CCopyFile_Tree.h"

/**********************************************/
OSErr			CCopyFile_Tree::ICopyFile_Tree(
	CCopyFile		*parent0, 
	Ptr				myData)
{
	OSErr				err		= noErr;
	
	err = _inherited::ICopyFile(parent0, CCT_Copy_TREE, myData);
	i_fileSizeL		= 0;
	i_curFilePosL	= 0;
	
	return err;
}

void	CCopyFile_Tree::Dispose(void)
{
	_inherited::Dispose();
}

CCT_MemFileRecH	CCopyFile_Tree::GetFileRecH(void)
{
	CCT_MemFileRecH		recH = (CCT_MemFileRecH)
		(i_myFileData == NULL ? i_myData : i_myFileData);

	ASSERT(recH && *recH && (**recH).nameAC[0] != 0);
	
	return recH;
}

OSErr	CCopyFile_Tree::GetFileInfo(CCT_MemFileRec *fileRecP)
{
	OSErr				err			= noErr;
	CCT_MemFileRecH		fileRecH	= GetFileRecH();
	
	*fileRecP		= **fileRecH;
	fileRecP->dataH	= NULL;
	fileRecP->resH	= NULL;

	return err;
}
	
/**********************************************/
OSErr	CCopyFile_Tree::IsFolder(Boolean *isFolderB)
{
	OSErr				err			= noErr;
	CCT_MemFileRecH		fileRecH	= GetFileRecH();

	*isFolderB = (**fileRecH).fileType == Pro_FileType_DIR;
	
	if (*isFolderB) {
		ASSERT((**fileRecH).dataH == NULL);
		
		if (i_copyType != CCT_Copy_TREE) {
			ASSERT(i_childP0);
		}
	}
	
	if (!(*isFolderB)) ASSERT(i_childP0 == NULL);
	
	return err;
}
	
OSErr	CCopyFile_Tree::CountFilesInFolder(ulong *numFilesL)
{
	OSErr		err			= noErr;
	CCopyFile	*copyFileP	= i_childP0;
	
	*numFilesL = 0;
	
	while (copyFileP) {
		(*numFilesL)++;
		copyFileP = copyFileP->i_sisterP0;
	};
	
	return err;
}

OSErr	CCopyFile_Tree::GetIndFileInFolder(ulong fileIndex, Ptr *fileDataP)
{
	OSErr		err = noErr;
	CCopyFile	*copyFileP	= i_childP0;
	
	while (fileIndex--) {
		copyFileP = copyFileP->i_sisterP0;
	}
	
	ASSERT(copyFileP);
	*fileDataP = (Ptr)copyFileP;
	
	return err;
}

/**********************************************/
OSErr		CCopyFile_Tree::CreateFile(Ptr parentFolderP, CCT_MemFileRec *fileRec)
{
	OSErr			err			= noErr;

	//	you can't write to a tree, you have to use a metatree
	ReportError(err = IC_Err_READ_ILLEGAL_FILE_BLOCK);

	return err;
}
	
OSErr		CCopyFile_Tree::SetFileInfo(CCT_MemFileRec *fileRecP)
{
	OSErr		err = noErr;

	//	you can't write to a tree, you have to use a metatree
	ReportError(err = IC_Err_READ_ILLEGAL_FILE_BLOCK);

	return err;
}

void		CCopyFile_Tree::DisposeData(void)
{
	CCT_MemFileRecH		dataH = GetFileRecH();
	
	if ((**dataH).dataH) {
		TrackDisposeHandle((**dataH).dataH);
	}
	
	if ((**dataH).resH) {
		TrackDisposeHandle((**dataH).resH);
	}
	
	TrackDisposeHandle((Handle)dataH);
	
	_inherited::DisposeData();
}
	
/**********************************************/
OSErr			CCopyFile_Tree::Open(ADFS_IOType ioType, Boolean resForkB)
{
	OSErr		err	= _inherited::Open(ioType, resForkB);
	
	if (!err) {
		CCT_MemFileRecH		fileRecH	= GetFileRecH();
		Handle				forkH		= resForkB ? (**fileRecH).resH : (**fileRecH).dataH;
		
		err = ASSERT(forkH && ioType == ADFS_IO_READ);
		
		if (!err) {
			i_fileSizeL		= GetHandleSize(forkH);
			i_curFilePosL	= 0;
		}
	}
		
	return err;
}

OSErr			CCopyFile_Tree::Close(void)
{
	OSErr		err = noErr;
	
	err = _inherited::Close();

	return err;
}

static	Boolean		Tree_IsEmptyBlock(ulong bytesL, char *bufP)
{
	Boolean				emptyB = TRUE;
	ulong				indexL;
	
	for (indexL = 0; emptyB && indexL < bytesL; indexL++) {
		emptyB = bufP[indexL] == 0;
	}
	
	return emptyB;
}

OSErr			CCopyFile_Tree::Read(ulong *bytesIO, char *bufP)
{
	OSErr				err			= noErr;
	CCT_MemFileRecH		fileRecH	= GetFileRecH();
	char				*forkP		= i_res_forkB ? *((**fileRecH).resH) : *((**fileRecH).dataH);
	
	if (*bytesIO >= i_fileSizeL - i_curFilePosL) {
		*bytesIO	= i_fileSizeL - i_curFilePosL;
		err			= eofErr;
	}

	memcpy(bufP, &forkP[i_curFilePosL], *bytesIO);
	i_curFilePosL += *bytesIO;
	
	return err;
}

OSErr			CCopyFile_Tree::Write(ulong *bytesIO, char *bufP)
{
	OSErr		err = noErr;
	
	//	you can't write to a tree, you have to use a metatree
	ReportError(err = IC_Err_READ_ILLEGAL_FILE_BLOCK);

	return err;
}

OSErr			CCopyFile_Tree::VerifyFreeSpace(CCT_CopyRec *copyRecP)
{
	OSErr		err = noErr;
	
	//	you can't write to a tree, you have to use a metatree
	ReportError(err = IC_Err_READ_ILLEGAL_FILE_BLOCK);

	return err;
}

OSErr			CCopyFile_Tree::VerifyFileSize(CCopyFile *sourceP, ulong fileSizeL)
{
	return _inherited::VerifyFileSize(sourceP, fileSizeL);
}

OSErr			CCopyFile_Tree::GetSizeSelf(CCT_CopyRec *copyRecP)
{
	OSErr				err			= noErr;
	CCT_MemFileRecH		fileRecH	= GetFileRecH();
	Handle				dataH		= (**fileRecH).dataH;
	Handle				resH		= (**fileRecH).resH;
	
	if (dataH || resH) {
		copyRecP->totalItemsS++;
	}
	
	if (dataH) {
		copyRecP->totalSizeL += GetHandleSize(dataH);
	}
	
	if (resH) {
		copyRecP->totalSizeL += GetHandleSize(resH);
	}
	
	err = _inherited::GetSizeSelf(copyRecP);

	return err;
}

OSErr			CCopyFile_Tree::ScanForCopySelf(Ptr myDataP, CCopyFile **fileExistsH)
{
	OSErr				err			= noErr;
	CCT_MemFileRecH		fileRecH	= GetFileRecH();
	CCT_MemFileRecH		testRecH	= (CCT_MemFileRecH)myDataP;
	
	if (
		memcmp((*fileRecH)->nameAC, (*testRecH)->nameAC, (*testRecH)->nameAC[0]) == 0
		&& (*fileRecH)->fileType == (*testRecH)->fileType
		&& (*fileRecH)->auxType == (*testRecH)->auxType
		&& memcmp(&(*fileRecH)->creDate, &(*testRecH)->creDate, sizeof(DateTimeRec)) == 0
		&& memcmp(&(*fileRecH)->modDate, &(*testRecH)->modDate, sizeof(DateTimeRec)) == 0
	) {
		*fileExistsH = this;
	}
	
	return err;
}

OSErr			CCopyFile_Tree::GetParentRef(Ptr *parentFolderH)
{
	OSErr		err		= noErr;

	*parentFolderH	= (Ptr)i_parentP0;

	return err;
}

OSErr			CCopyFile_Tree::GetVolumeRef(Ptr *volumeH)
{
	OSErr		err		= noErr;
	
	*volumeH		= (Ptr)i_copyTreeP;
	
	return err;
}

void			CCopyFile_Tree::LogCopyFileType(void)
{
	ADFS_Log("a tree");
}

Boolean			CCopyFile_Tree::IsForked(void)
{
	CCT_MemFileRecH		fileRecH	= GetFileRecH();

	return (**fileRecH).forkedB;
}

Boolean			CCopyFile_Tree::SupportsForks(void)
{
	//	you can't write to a tree, you have to use a metatree
	ReportError(IC_Err_READ_ILLEGAL_FILE_BLOCK);
	
	return TRUE;
}

OSErr			CCopyFile_Tree::GetForkInfo(CCT_ForkInfo *forkInfoP)
{
	OSErr				err			= noErr;
	CCT_MemFileRecH		fileRecH	= GetFileRecH();
	
	*forkInfoP = (**fileRecH).forkInfo;

	return err;
}

OSErr			CCopyFile_Tree::SetForkInfo(CCT_ForkInfo *forkInfoP)
{
	OSErr		err		= noErr;

	//	you can't write to a tree, you have to use a metatree
	ReportError(err = IC_Err_READ_ILLEGAL_FILE_BLOCK);

	return err;
}



