// FilePro.cpp: implementation of the CFilePro class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "PatchIT.h"
#include "FilePro.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

float SyncRank(DWORD pos,DWORD size,DWORD sloc,DWORD fsize)
{
DWORD recommend_size=fsize/1000;
if(size>recommend_size) return 0.00000001f;
if(recommend_size==0) recommend_size=1;	
float sweight,pweight;
if(size<=recommend_size) 
	sweight=(float)size/recommend_size;
else 
	sweight=(float)(fsize-(size-recommend_size))/(fsize-recommend_size);

//if(size<8 || size>(fsize*2.0)) sweight/=2.0; 


	pweight=(float)((fsize-sloc)-pos)/(fsize-sloc);
return pweight*sweight;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CFilePro::CFilePro()
{
	BlockLoc=BlockSize=0;
}


void CFilePro::ReadBlockAt(DWORD bl)
{
	BlockLoc=bl;
	if(GetPosition()!=BlockLoc) Seek(bl,CFile::begin);
	BlockSize=GetLength()-BlockLoc;
	if(BlockSize<=BUFFERSIZE) 
		LastBlock=true; 
	else {BlockSize=BUFFERSIZE; LastBlock=false;}
	
	Read(Buffer,BlockSize);
}

DWORD CFilePro::DifferAt(CFilePro &file,DWORD *floc)
{
	
	DWORD pos1,pos2;
	DWORD eof1,eof2;
	eof1=GetLength();
	eof2=file.GetLength();
	pos1=GetPosition();
	pos2=file.GetPosition();

	while(GetByte(pos1)==file.GetByte(pos2) && pos1<eof1 && pos2<eof2) {pos1++; pos2++;}
	Seek(pos1,CFile::begin);
	file.Seek(pos2,CFile::begin);
	*floc=pos2;
	return pos1;
}

BYTE CFilePro::GetByte(DWORD loc)
{
if((loc-BlockLoc)<BlockSize) 
	return Buffer[loc-BlockLoc];
else
	ReadBlockAt(loc);
return Buffer[0];
}


bool CFilePro::SyncedAt(CFilePro &file,DWORD *sloc,int earlyout)
{
	DWORD pos;
	DWORD cur_pos,old_pos,old_pos2,eof,eof2;
	DWORD hipos=0,hisize=0;
	float hirank=0.0f;
	DWORD cnt=1;
	float rank;

	eof=GetLength();
	eof2=file.GetLength();
	cur_pos=old_pos=GetPosition();
	old_pos2=file.GetPosition();
	

	if(old_pos2>=eof2 || old_pos>=eof) return false;

while(cur_pos<eof && (earlyout<0 || hisize<(DWORD)earlyout))
{
	pos=0;
	while(GetByte(cur_pos)!=file.GetByte(old_pos2) && cur_pos<eof) cur_pos++;
	
	if(cur_pos<eof) 
	{
	cnt=1;
	while(GetByte(cur_pos+cnt)==file.GetByte(old_pos2+cnt) && (cur_pos+cnt)<eof && (old_pos2+cnt)<eof2) cnt++;
	rank=SyncRank(cur_pos,cnt,old_pos,eof);
		
		 
		if(rank>hirank) //Best Sync Rank  
		{
		hirank=rank;
		hisize=cnt;
		hipos=cur_pos;
		}
		
		
		
		/* 
		if(cnt>hisize) //Largeest BLock
		{
		hisize=cnt;
		hipos=cur_pos;
		}
		*/
	cur_pos++;
	}
}
	
Seek(old_pos,CFile::begin);
file.Seek(old_pos2,CFile::begin);
*sloc=hipos;
return (hisize>0)?true:false;
}

unsigned __int64 CFilePro::CRC()
{
unsigned __int64 sum=0;
Seek(0,CFile::begin);
DWORD pos;
	do
	{
		ReadBlockAt(GetPosition());
		pos=0;
		while(pos<BlockSize) {sum+=(__int64)Buffer[pos]; pos++;}
	}
	while(BlockSize>=BUFFERSIZE);


return sum;
}

CFilePro::~CFilePro()
{
	
}

