
#pragma		once

#include	"ProgressBar.h"
#include	"MD5.h"

class	CArcFile
{
public:

											CArcFile();
	virtual									~CArcFile();

	BOOL									Mount();
	BOOL									Decode();
	BOOL									Extract();

	// 書庫ファイル操作

	BOOL									Open( LPCTSTR pszPathToArc );
	void									Close();

	DWORD									Read( void* pvBuffer, DWORD dwReadSize );
	BYTE*									ReadHed();

	UINT64									Seek( INT64 n64Offset, DWORD dwSeekMode );
	UINT64									SeekHed( INT64 n64Offset = 0 );
	UINT64									SeekEnd( INT64 n64Offset = 0 );
	UINT64									SeekCur( INT64 n64Offset );

	UINT64									GetArcPointer();
	UINT64									GetArcSize();

	// 出力ファイル操作

	YCString								CreateFileName( LPCTSTR pszReFileExt = NULL );

	BOOL									OpenFile( LPCTSTR pszReFileExt = NULL );
	BOOL									OpenScriptFile();
	void									CloseFile();

	DWORD									WriteFile( const void* pvBuffer, DWORD dwWriteSize, DWORD dwSizeOrg = 0xFFFFFFFF );
	void									ReadWrite();
	void									ReadWrite(DWORD FileSize);

	// 簡易復号

	DWORD									InitDecrypt();
	DWORD									InitDecrypt( const void* pvData );
	DWORD									InitDecryptForText( const void* pvText, DWORD dwTextSize );
	void									Decrypt( void* pvBuffer, DWORD dwSize );

	// 書庫内ファイル情報をリストに追加する

	void									AddFileInfo( SFileInfo& infFile );
	void									AddFileInfo( SFileInfo& infFile, DWORD& ctFile, LPCTSTR pFileExt );

	YCString								SetFileFormat( const YCString& sFilePath );
	YCString								SetCommaFormat( DWORD dwSize );

	// マウント/デコード前に行なう初期化処理

	void SetFileInfo(DWORD num)					{ m_pInfFile = &(*m_pEnt)[num]; m_dwArcsID = m_pInfFile->arcsID; m_dwInfFileNum = num; }
	void SetArcID(DWORD dwArcID)				{ m_dwArcID = dwArcID; }
	void SetEnt(std::vector<SFileInfo>& rEnt)	{ m_pEnt = &rEnt; m_nStartEnt = rEnt.size(); }
	void SetProg(CProgBar& prog)				{ m_pProg = &prog; }
	void SetOpt(SOption* pOption)				{ m_pOption = pOption; }
	void SetSaveDir(LPCTSTR pSaveDir)			{ m_pSaveDir = pSaveDir; }

	// 対応ファイルならTRUE(未対応のファイルを即座に閉じられるようにする)

	void SetState(BOOL bState) { m_bState = bState; }

	// 分割ファイルをサポート

	void		SetFirstArc()	{ m_dwArcsID = 0; }
	void		SetNextArc()	{ m_dwArcsID++; }
	HANDLE		GetArcHandle()	{ return (m_hArcs[m_dwArcsID]); }
	void		SetArcsID( DWORD dwArcsID ) { m_dwArcsID = dwArcsID; }
	DWORD		GetArcsID()		{ return (m_dwArcsID); }
	size_t		GetArcCount()	{ return (m_hArcs.size()); }
	YCString&	GetArcPath()	{ return (m_pclArcPaths[m_dwArcsID]); }
	YCString&	GetArcName()	{ return (m_pclArcNames[m_dwArcsID]); }
	YCString&	GetArcExten()	{ return (m_pclArcExtens[m_dwArcsID]); }

	// あらかじめ読み込んでおいた書庫ファイルヘッダを返す

	LPBYTE GetHed() { return (m_pHeader); }

	SFileInfo*				GetFileInfo( DWORD num )	{ return (&(*m_pEnt)[num]); }
	SFileInfo*				GetFileInfo( PCTSTR pszFileName, BOOL bCmpFileNameOnly = FALSE );
	const SFileInfo*			GetFileInfoForBinarySearch( LPCTSTR pszFileName );
	std::vector<SFileInfo>&	GetFileInfo()			{ return (*m_pEnt); }
	SFileInfo*				GetOpenFileInfo()		{ return (m_pInfFile); }
	DWORD					GetOpenFileInfoNum()	{ return (m_dwInfFileNum); }

	DWORD		GetArcID()		{ return (m_dwArcID); }
	size_t		GetStartEnt()	{ return (m_nStartEnt); }
	size_t		GetCtEnt()		{ return (m_ctEnt); }
	CProgBar*	GetProg()		{ return (m_pProg); }
	SOption*		GetOpt()		{ return (m_pOption); }

	BOOL		GetState()		{ return (m_bState); }

	DWORD	GetBufSize();
	void	SetBufSize(LPDWORD BufSize, DWORD WriteSize);
	void	SetBufSize(LPDWORD BufSize, DWORD WriteSize, DWORD FileSize);

	void ReplaceBackslash(LPTSTR pFileName);
	void MakeDirectory(LPCTSTR wFileName);

	// エンディアン変換

	DWORD	ConvEndian(DWORD value);
	WORD	ConvEndian(WORD value);
	void	ConvEndian(LPDWORD value);
	void	ConvEndian(LPWORD value);

	BOOL CheckExe(LPCTSTR pExeName);
	BOOL CheckDir(LPCTSTR pDirName);

	// Susieプラグインによるマウント

	void				SetMountSusie() { m_bMountWasSusie = TRUE; }
	BOOL				GetMountSusie() { return m_bMountWasSusie; }

	// MD5値のセット

	void				SetMD5(SMD5 stmd5File);

	// MD5値のセットフラグ

	void				SetMD5OfFlag(BOOL bSetMD5) { m_bSetMD5 = bSetMD5; }

	// MD5値の参照

	std::vector<SMD5>	GetMD5() { return m_vtstmd5File; }

	// MD5値をセットしたかどうか

	BOOL				CheckMD5OfSet() { return m_bSetMD5; }

	// MD5値のクリア

	void				ClearMD5();

	// ワークフラグの設定

	void				SetFlag(BOOL bFlag) { m_bWork = bFlag; }

	// ワークフラグの取得

	BOOL				GetFlag() { return m_bWork; }

	// ソート用比較関数

	static BOOL								CompareForFileInfo( const SFileInfo& rstfiTarget1, const SFileInfo& rstfiTarget2 );

	// 二分探索

	static SFileInfo*						SearchForFileInfo( std::vector<SFileInfo>& rvcFileInfo, LPCTSTR pszFileName );


protected:



private:

	YCMultiFile								m_clmfArc;
	YCFile									m_clfOutput;

	// 書庫内ファイル情報

	std::vector<SFileInfo>*	m_pEnt;
	SFileInfo*				m_pInfFile;

	std::vector<SFileInfo>	m_vcFileInfoOfFileNameSorted;

	// 分割書庫ファイルをサポート

	DWORD					m_dwArcsID;
	std::vector<HANDLE>		m_hArcs;
	std::vector<YCString>	m_pclArcPaths;
	std::vector<YCString>	m_pclArcNames;
	std::vector<YCString>	m_pclArcExtens;

	BYTE	m_pHeader[2048];
	DWORD	m_dwArcID;
	size_t	m_nStartEnt;	// このアーカイブのファイル情報開始インデックス
	size_t	m_ctEnt;		// このアーカイブのファイル情報数
	DWORD	m_dwInfFileNum;

	BOOL	m_bState;

	CProgBar*	m_pProg;
	SOption*		m_pOption;

	HANDLE	m_hFile;
	YCString								m_clsPathToFile;
	LPCTSTR	m_pSaveDir;

	DWORD	m_deckey;

	BOOL				m_bMountWasSusie;				// Susieプラグインによるマウント

	// MD5値

	std::vector<SMD5>	m_vtstmd5File;

	// MD5値セットフラグ

	BOOL				m_bSetMD5;

	// アーカイブごとに設定可能なフラグ変数

	BOOL				m_bWork;
};
