/* ==========================================================================
* 작 성 자 : 이순규
* 작 성 일 : 2007.06.21
* 내    용 : 패처
* 주의사항 : 
*===========================================================================*/
#pragma once

#include "PatcherDlg.h"
#include "BSTreeLinkedList.h"
#include "HttpDownLoader.h"

#define MAX_PACKS	128

class cPatcherDlg;

/// .pack 파일로 저장이 안되야 하는 폴더들.
const char* const gUnpackFolder[]  = { "sound", "launcher", "guildmark", "script" };
/// 클라이언트의 파일 정보를 모을 때 필요없는 폴더(비교가 안되는 폴더)들.
const char* const gSkipFolder[]    = { "ScreenShot", "Option" };
const char* const SCRIPT_DIRECTORY = "script";
const DWORD       g16KBYTE         = 16384;

enum eUnpackFolder
{
	FOLDER_SOUND = 0,
	FOLDER_LAUNCHER,
	FOLDER_GUILDMARK,
	FOLDER_SCRIPT,
	UNPACK_FOLDER_COUNT,
};

enum eSkipFolder
{
	FOLDER_SCREENSHOT = 0,
	FOLDER_OPTION,
	SKIP_FOLDER_COUNT,
};


struct Packfile
{
 	char directory[ 1024 ];			// 디렉토리
};
 
struct Packlist
{
 	Packfile* pack;
 	ULONG     offset;				// 오프셋
 	ULONG     length;				// 전체갯수
};
 
 struct Patchfile
 {
 	char     fileName[ 1024 ];		// 파일이름
 	DWORD    sizeHigh;				// 파일크기
 	DWORD    sizeLow;				// 파일크기
 	FILETIME writeTime;				// 파일날짜
 };
 
 struct Patchlist
 {
 	Patchfile* file;				// 업데이트 파일 구조체
 	ULONG      offset;				// 오프셋
 	ULONG      length;				// 전체갯수
 };

/// 패처
class cPatcher
{
public:
	cPatcher( cPatcherDlg* dlg );
	~cPatcher();

	void Clear();
	void Init( HWND wnd, HINSTANCE instance );

	DWORD ThreadProc();
	void StopWorking();
	bool IsWorking() const;
	bool IsEndIO() const;

protected:
	bool MakeList(char* buffer);

	void SetProgressMax( ePatchStatus status, int max );
	void SetProgressPos( const char* fileName, int pos );

private:
	/// [12/9/2008 Jo] load.dll파일 로드 및 해체.
	int  GetString(int id, char* buffer, int bufferSize ); 
	bool UnpackPatchList( char** buffer, DWORD *bufferLen );
	void FileTimeToDOS(FILETIME* filetime);

	bool VerifyFile(Patchfile* patchfile);
	bool UpdateFile(Patchfile* patchfile, char* buffer, DWORD bufferLen);
	void ErrorPrint(char *msg);
	int  Search(char* root, char* sub, int& files, int& directories, bool opcode);
	void EventWrite(LPCTSTR format, ...);
	HANDLE GetProcessList( bool* bFuncFailed );
private:
	/// 다이얼로그
	cPatcherDlg* mDlg;
	HWND	     mWnd;
	HINSTANCE    mInstance;
	bool         mEndApp;
	bool         mEndIO;

	char         m_currentDirectory[ MAX_PATH ];

	Packlist   m_packlist;
	Patchlist  m_patchlist;

	/// 클라이언트가 가지고 있는 파일들 리스트
	CBSTreeLinkedList m_compressedFileList; 
	CBSTreeLinkedList m_UnCompressedFileList;

	vector< Patchfile >  m_updateList;

	/// 진행바
	unsigned int mNumPatchFiles;

	/// loader
	ClassDesc* m_libClassDesc;

public:
	static DWORD WINAPI LoaderProgressRoutine( DWORD totalFileSize, DWORD totalBytesTransferred, void* data );

};

inline
void cPatcher::Init( HWND wnd, HINSTANCE instance)
{
	assert( wnd );

	mWnd = wnd;
	mInstance = instance;

	// 현재 폴더 저장.
	GetCurrentDirectory( sizeof(m_currentDirectory), m_currentDirectory );
	//strcpy( m_currentDirectory, "D:\\IrisOnline" );

	/// [12/9/2008 Jo] Dll 로드
	m_libClassDesc = new Loader;
	if ( m_libClassDesc == NULL )
	{
		MessageBox( wnd, "LOADER Memory allocation Fail", "Error", MB_OK | MB_ICONERROR );
		PostMessage( wnd, WM_CLOSE, 0, 0 );
	}
}

inline
void cPatcher::SetProgressMax( ePatchStatus status, int max )
{
	if( mDlg != NULL )
		mDlg->SetProgressMax( status, max );
}

inline
void cPatcher::SetProgressPos( const char* fileName, int pos )
{
	if( mDlg != NULL )
		mDlg->SetProgressPos( fileName, pos );
}

inline
bool cPatcher::IsWorking() const
{
	return !mEndApp;
}

inline
bool cPatcher::IsEndIO() const
{
	return mEndIO;
}
