#include"../../Maid/Setup/CompileMode.h"
#include"../../Maid/auxiliary/CString.h"
#include"../../Maid/auxiliary/CDataFileParser.h"
#include"../../Maid/auxiliary/FIleIO/CPackFileManager.h"
#include"../../Maid/auxiliary/FIleIO/CFileWrite.h"
#include"../../Maid/auxiliary/FIleIO/CFileRead.h"
#include"../../Maid/auxiliary/Windows/CShell.h"
#include"../../Maid/auxiliary/Windows/COpenFileName.h"
#include"../../Maid/auxiliary/CRand.h"

#include <commctrl.h>
#include"resource.h"

using namespace Maid;


static BOOL CALLBACK PackDlgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
static BOOL CALLBACK PackingProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );


mstring CurrentDirectory;	//	このアプリケーションがあるディレクトリ
HINSTANCE	  s_hInstance;
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
	s_hInstance = hInstance;

	{	//	カレントディレクトリの設定
		CurrentDirectory = CString::GetDirectory( CShell::GetExeFileName() );
		CShell::SetCurrentDirectory(CurrentDirectory);
	}

	CRand::SetSeed( ::GetTickCount() );


	//	テスト用コード
/*
	CFileRead::GetPackFile().Mount( MAIDTEXT("dat.dat"), MAIDTEXT("kk") );

	{
		MySTL::vector<unt08> tmp;
		CFileRead::Read( MAIDTEXT("kk\\sample.bmp"), tmp );
		CFileWrite::Write( MAIDTEXT("hoge__.bmp"), &(tmp[0]), tmp.size() );
	}
	{
		MySTL::vector<unt08> tmp;
		CFileRead::Read( MAIDTEXT("kk\\0byte.txt"), tmp );
		CFileWrite::Write( MAIDTEXT("0byte.txt"), &(tmp[0]), tmp.size() );
	}
//*/
	::DialogBox( hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, PackDlgProc );

	return 0;
}

static CPackFileCreater	s_PackFile;

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 指定したファイルから非圧縮ファイルリストを設定する
/*!	
 *	\param	hWnd		[i ]	設定するダイアログボックスのハンドル
 *	\param	DlgItem		[i ]	設定するリストボックスのＩＤ
 *	\param	FileName	[i ]	設定データが入ったファイル名
 *
 *	\return 設定できたら MRESULT_OK
\n			出来なかったら MRESULT_OK 以外
 */
void SetNoCompressList( HWND hWnd, int DlgItem, const mstring& FileName )
{
	CDataFileParser	Parser;

	Parser.Load(FileName);

	{
		SPDATATAG pTag = Parser.NextTag( MAIDTEXT("NoCompress") );

		if( pTag.get()==NULL )
		{
			::MessageBox( hWnd, "指定したファイルに #NoCompress タグがありません", NULL, MB_OK );
			return;
		}

		const HWND hListBox = ::GetDlgItem(hWnd,DlgItem);
		for( unt32 i=0; i<pTag->GetLength(); ++i )
		{
			const MySTL::string str = CString::ConvertMAIDtoSJIS(pTag->GetStr(i));

			::SendMessage(hListBox,LB_ADDSTRING,0,(LONG)str.c_str() );
		}

	}
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! パックファイル管理クラス
/*!	
 *	\param	hWnd	[i ]	呼び出し元のウィンドウハンドル
 *	\param	msg		[i ]	送られてきたメッセージ
 *	\param	wParam	[i ]	メッセージの詳細
 *	\param	lParam	
 */
static BOOL CALLBACK PackDlgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch( msg )
	{
	case WM_INITDIALOG:
		{
			RECT rc;
			::GetWindowRect( hWnd, &rc );

			const int w = rc.right  - rc.left;
			const int h = rc.bottom - rc.top;
			const int x = (::GetSystemMetrics(SM_CXSCREEN) - w) /2;
			const int y = (::GetSystemMetrics(SM_CYSCREEN) - h) /2;

			MoveWindow( hWnd, x, y, w, h, TRUE );

			SetNoCompressList( hWnd, LIST_NOCOMPLIST, MAIDTEXT("PackFileManager_config.txt") );

		}
		break;

	case WM_COMMAND:
		{
			switch( LOWORD(wParam) )
			{
			case BUTTON_BEGINARCHIVE:
				{
					const mstring FolderName = CShell::BrowseForFolder( hWnd, MAIDTEXT("パックするフォルダの選択"), CurrentDirectory );

					if( FolderName.empty() ) { break; }



					//	圧縮しない拡張子データをリストボックスから拾ってくる
					const HWND hListBox = GetDlgItem(hWnd,LIST_NOCOMPLIST);
					const unt32 ItemCount = (unt32)::SendMessage(hListBox,LB_GETCOUNT,0,0 );
					MySTL::vector<mstring>	FilterList;

					for( unt32 i=0; i<ItemCount; ++i )
					{
						const unt32 TextLen = (unt32)::SendMessage(hListBox,LB_GETTEXTLEN,i,0 );
						MySTL::string str;
						str.resize( TextLen );
						::SendMessage(hListBox,LB_GETTEXT,i,(LPARAM)(LPCTSTR)str.c_str() );

						FilterList.push_back( CString::ConvertSJIStoMAID(str) );
					}


					s_PackFile.SetNoCompressList( FilterList );
					s_PackFile.BeginArchive( FolderName, FolderName+MAIDTEXT(".dat") );

					::DialogBox( s_hInstance, MAKEINTRESOURCE(IDD_PROGRESS), hWnd, PackingProc );

				}
				break;

			case BUTTON_NOCOMPRESS:
				{
					COpenFileName	FileDialog;
					FileDialog.SetFileFilter( "定義ファイル(*.txt)\0*.txt\0すべてのファイル(*.*)\0*.*\0\0" );
					if( !FileDialog.ShowOpenDialog( hWnd, MAIDTEXT("非圧縮ファイルの設定"), MAIDTEXT(".txt") ) ) { break; }

					const mstring& str = FileDialog.GetFilePath();

					SetNoCompressList( hWnd, LIST_NOCOMPLIST, FileDialog.GetFilePath() );

				}break;


			case BUTTON_DIVIDE: { ::MessageBox( hWnd, "現在未実装", NULL, MB_OK ); } break;

			case IDCANCEL:
				{
					::SendMessage( hWnd, WM_CLOSE, 0, 0 );
				}
				break;
			}

		}
		break;	
	case WM_CLOSE:
		{
			::EndDialog( hWnd, 0 );
		}
		break;
	}

	return 0;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! パック状況を知らせるダイアログボックス
/*!	
 *	\param	hWnd	[i ]	呼び出し元のウィンドウハンドル
 *	\param	msg		[i ]	送られてきたメッセージ
 *	\param	wParam	[i ]	メッセージの詳細
 *	\param	lParam	
 */
static BOOL CALLBACK PackingProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	const int TIMERID = 100;

	switch(msg)
	{
	case WM_TIMER:
		{
			switch( wParam )
			{
			case TIMERID:
				{
					const CPackFileCreater::STATUS State = s_PackFile.GetStatus();

					switch( State.State )
					{
					case CPackFileCreater::STATUS::STATE_OK:
						{
							::SendMessage( GetDlgItem( hWnd, BAR_PROGRESS), PBM_SETPOS,   State.Progress,   0 );
							::SetDlgItemText( hWnd, TEXT_PROGRESS, CString::ConvertMAIDtoSJIS(State.Text).c_str() );
					
						}break;
					case CPackFileCreater::STATUS::STATE_ERROR:
						{
							::KillTimer( hWnd, TIMERID );
							::MessageBox( hWnd, CString::ConvertMAIDtoSJIS(State.Text).c_str(), "error", MB_OK );
							::EndDialog( hWnd, WM_TIMER );	
						}break;

					case CPackFileCreater::STATUS::STATE_SUCCESS:
						{
							{
								MySTL::string output_log;

								{
									const MySTL::vector<mstring>& log = s_PackFile.GetNoCompressFileList();
									mstring o;
									for( int i=0; i<(int)log.size(); ++i )
									{
										o += log[i] + MAIDTEXT("\r\n");
									}

									output_log = CString::ConvertMAIDtoSJIS(o);
								}
								CFileWrite hFile;
								hFile.Open( MAIDTEXT("archive_log.txt"), CFileWrite::OPENOPTION_NEW );
								hFile.Write( output_log.c_str(), (int)output_log.length() );
							}


							::SendMessage( GetDlgItem( hWnd, BAR_PROGRESS), PBM_SETPOS,   100,   0 );
							::KillTimer( hWnd, TIMERID );
							::MessageBox( hWnd, CString::ConvertMAIDtoSJIS(State.Text).c_str(), "確認", MB_OK );
							::EndDialog( hWnd, WM_TIMER );						
						}break;
					case CPackFileCreater::STATUS::STATE_CANCEL:
						{
							::KillTimer( hWnd, TIMERID );
							::MessageBox( hWnd, CString::ConvertMAIDtoSJIS(State.Text).c_str(), "確認", MB_OK );
							::EndDialog( hWnd, WM_TIMER );						
						}break;
					}
				}
				break;
			}

		}
		break;

	case WM_COMMAND:
		{
			switch( LOWORD(wParam) )
			{
				case BUTTON_STOP:
				{
					s_PackFile.OnCancel();
				}
				break;
		   }
		}
		break;

	case WM_INITDIALOG:
		{
			SendMessage( GetDlgItem( hWnd, BAR_PROGRESS), PBM_SETRANGE, 0, MAKELPARAM( 0, 100 ) );
			SendMessage( GetDlgItem( hWnd, BAR_PROGRESS), PBM_SETSTEP,  1,   0 );
			SendMessage( GetDlgItem( hWnd, BAR_PROGRESS), PBM_SETPOS,   0,   0 );

			SetTimer( hWnd, TIMERID, 100, NULL );
		}
		break;

	case WM_CLOSE:
		{
			::SendMessage( hWnd, WM_COMMAND, IDCANCEL, 0 );
		}
		break;
    }

	return 0;
}
