#include "stdafx.h"
#include "res/ResExtractData.h"
#include "Common.h"
#include "WindowBase.h"
#include "ExtractData.h"
#include "MainToolBar.h"
#include "Ctrl/StatusBar.h"
#include "Dialog/VersionInfo.h"
#include "Dialog/FileDialog.h"
#include "Dialog/FolderDialog.h"
//#include "DataBase/DataBase.h"
#include "MainListView.h"
#include "Option.h"
#include "LastDir.h"
#include "Susie.h"
#include "WinMain.h"

#pragma comment( lib, "ShLwApi.Lib" )
#pragma comment( lib, "ComCtl32.Lib" )
#pragma comment( lib, "imm32.lib" )

#ifdef	_DEBUG
#pragma	comment( lib, "zlibd.lib" )
#pragma	comment( lib, "libpngd.lib" )
#else
#pragma comment( lib, "zlib.lib" )
#pragma comment( lib, "libpng.lib" )
#endif

//#pragma comment (lib, "libjpeg.lib")

// メイン関数
int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpsCmdLine, int nCmdShow)
{
#ifdef	_DEBUG
	::_CrtSetDbgFlag( _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF );
#endif

	CWinMain main;
	return main.WinMain(hInst, hPrevInst, lpsCmdLine, nCmdShow);
}

#define	WINDOWCLASS_NAME								_T("ExtractDataClass")
#define	WINDOW_NAME										_T("ExtractData")

CWinMain::CWinMain()
{
	m_hWnd = NULL;
	ZeroMemory(&m_wc, sizeof(WNDCLASSEX));

	m_hInst = NULL;
	m_hPrevInst = NULL;
	m_lpsCmdLine = NULL;
	m_nCmdShow = 0;
}

CWinMain::~CWinMain()
{
}

int CWinMain::WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpsCmdLine, int nCmdShow)
{
	// プログラム本体のWinMain関数から引数を受け取り、メンバ変数へ代入
	m_hInst = hInst;
	m_hPrevInst = hPrevInst;
	m_lpsCmdLine = lpsCmdLine;
	m_nCmdShow = nCmdShow;

	OleInitialize(NULL);

	if (!InitApp())
		return FALSE;

	if (!InitInstance())
		return FALSE;

	HACCEL hAccel = LoadAccelerators(hInst, _T("MYACCEL"));
	if (!hAccel)
		return FALSE;

	COption option;
	MSG msg;
	int bRet;
	while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
		if (bRet == -1)
			break;
		else if (!TranslateAccelerator(m_hWnd, hAccel, &msg)) {
			//if (option.GetHandle() || !PropSheet_IsDialogMessage(option.GetHandle(), &msg)) {
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			//}
			//if (option.GetHandle() && PropSheet_GetCurrentPageHwnd(option.GetHandle()) == NULL) {
				// プロパティシートを終了する
			//	option.Close();
			//}
		}
	}

	OleUninitialize();
	return (int)msg.wParam;
}

// ウィンドウクラスの登録
ATOM CWinMain::InitApp()
{
	WNDCLASSEX wc;
	wc.cbSize			= sizeof(WNDCLASSEX);
	wc.style			= CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc		= (WNDPROC)CWindowBase::WndStaticProc; // プロシージャ名
	wc.cbClsExtra		= 0;
	wc.cbWndExtra		= 0;
	wc.hInstance		= m_hInst;	// インスタンス
	wc.hIcon			= LoadIcon( m_hInst, MAKEINTRESOURCE( IDI_ICON_APP ) );
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground	= (HBRUSH)(COLOR_BTNFACE+1);
	wc.lpszMenuName		= _T("MAINMENU"); // メニュー名
	wc.lpszClassName	= WINDOWCLASS_NAME;
	wc.hIconSm			= LoadIcon( m_hInst, MAKEINTRESOURCE( IDI_ICON_APP ) );

	m_wc = wc;
	return (RegisterClassEx(&m_wc));
}

// ウィンドウの生成
BOOL CWinMain::InitInstance()
{
	m_hWnd = CreateWindow(WINDOWCLASS_NAME,
		WINDOW_NAME,	// タイトルバーにこの名前が表示される
		WS_OVERLAPPEDWINDOW,	// ウィンドウの種類
		0,	// X座標
		0,	// Y座標
		0,	// 幅
		0,	// 高さ
		NULL,	// 親ウィンドウのハンドル、親を作るときはNULL
		NULL,	// メニューハンドル、クラスメニューを使うときはNULL
		m_hInst,	// インスタンスハンドル
		(LPVOID)this);
	if (!m_hWnd)
		return FALSE;

	Init(idsMainWindow, 640, 480);
	UpdateWindow(m_hWnd);

	return TRUE;
}

// ウィンドウプロシージャ
LRESULT CWinMain::WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
	static CMainToolBar MainToolBar;
	static CSearchToolBar SearchToolBar;
	static CMainListView listview;
	static CStatusBar statusbar;
	static CExtractData extract;
	static COption option;
	static CVersionInfo version;
	static CLastDir lastdir;
	static TCHAR ReadmeFileName[MAX_PATH], HistoryFileName[MAX_PATH], StateFileName[MAX_PATH];
	INITCOMMONCONTROLSEX ic;

	switch (msg) {
	case WM_CREATE:
		{
			// D&Dを許可
			DragAcceptFiles(hWnd, TRUE);

			option.Init(SearchToolBar, listview);

			// コモンコントールの初期化
			ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
			ic.dwICC = ICC_WIN95_CLASSES;
			InitCommonControlsEx(&ic);
			// ツールバー生成
			MainToolBar.Create(hWnd);
			SearchToolBar.Create(hWnd);
			// リストビュー生成
			listview.Create(hWnd, option.GetOpt());
			// ステータスバー生成
			statusbar.Create(hWnd, option.GetOpt(), listview);

			// フルパス取得
			TCHAR ModulePath[MAX_PATH];
			GetModuleFileName(NULL, ModulePath, MAX_PATH);
			PathRemoveFileSpec(ModulePath);
			// Readme.txtの場所をフルパスで取得
			lstrcpy(ReadmeFileName, ModulePath);
			PathAppend(ReadmeFileName, _T("Readme.txt"));
			// History.txtの場所をフルパスで取得
			lstrcpy(HistoryFileName, ModulePath);
			PathAppend(HistoryFileName, _T("History.txt"));
			// State.txtの場所をフルパスで取得
			lstrcpy(StateFileName, ModulePath);
			PathAppend(StateFileName, _T("State.txt"));

			extract.Init(hWnd, option.GetOpt(), listview);
			break;
		}

	case WM_DROPFILES:
		extract.OpenDrop(wp);
		MainToolBar.AddOpenHistory(extract.GetArcList());
		statusbar.SetCount();
		break;

	case WM_COMMAND:
		switch (LOWORD(wp)) {
		case IDM_OPEN: // 読み込むファイルを取得し、開く
			extract.Open(lastdir.GetOpen());
			MainToolBar.AddOpenHistory(extract.GetArcList());
			statusbar.SetCount();
			lastdir.SaveIni();
			break;

		case	IDM_CLOSE:
			// 開いているファイルを閉じる

			extract.Close();
			statusbar.SetCount();
			break;

		// 履歴からファイルを開く
		case ID_TOOLBAR_OPEN_HISTORY:
		case ID_TOOLBAR_OPEN_HISTORY+1:
		case ID_TOOLBAR_OPEN_HISTORY+2:
		case ID_TOOLBAR_OPEN_HISTORY+3:
		case ID_TOOLBAR_OPEN_HISTORY+4:
		case ID_TOOLBAR_OPEN_HISTORY+5:
		case ID_TOOLBAR_OPEN_HISTORY+6:
		case ID_TOOLBAR_OPEN_HISTORY+7:
		case ID_TOOLBAR_OPEN_HISTORY+8:
		case ID_TOOLBAR_OPEN_HISTORY+9:
			extract.OpenHistory(MainToolBar.GetHistory()[LOWORD(wp)-ID_TOOLBAR_OPEN_HISTORY]);
			MainToolBar.AddOpenHistory(extract.GetArcList());
			statusbar.SetCount();
			break;

		// 検索ファイル設定ボタン
		case IDM_AHX:
		case IDM_BMP:
		case IDM_JPG:
		case IDM_MID:
		case IDM_MPG:
		case IDM_OGG:
		case IDM_PNG:
		case IDM_WAV:
		case IDM_WMV:
			SearchToolBar.SetSearch(LOWORD(wp));
			break;

		// クイック設定
		case IDM_QUICKSET_STD_SEARCHOGG:
		case IDM_QUICKSET_EXTRACT_CREATEFOLDER:
		case IDM_QUICKSET_EXTRACT_FIXOGG:
		case IDM_QUICKSET_EXTRACT_EASYDECRYPT:
		case IDM_QUICKSET_EXTRACT_DSTPNG:
		case IDM_QUICKSET_EXTRACT_ALPHABLEND:
		case IDM_QUICKSET_SUSIE_USE:
		case IDM_QUICKSET_SUSIE_FIRST:
			SetQuickMenuItem(LOWORD(wp));
			break;

		case IDM_EXIT: // 終了
			SendMessage(hWnd, WM_CLOSE, 0, 0);
			break;

		case IDM_EXTRACT:
			// 選択範囲を抽出

			if( listview.GetCountSel() > 0 )
			{
				extract.SaveSel( lastdir.GetSave(), TRUE );
			}

			lastdir.SaveIni();
			break;

		case IDM_EXTRACTALL:
			// すべて抽出

			if( listview.GetCount() > 0 )
			{
				extract.SaveAll( lastdir.GetSave(), TRUE );
			}

			lastdir.SaveIni();
			break;

		case	IDM_EXTRACT_NOTCONVERT:
			// 変換せずに選択範囲を抽出

			if( listview.GetCountSel() > 0 )
			{
				extract.SaveSel( lastdir.GetSave(), FALSE );
			}

			lastdir.SaveIni();
			break;

		case	IDM_EXTRACTALL_NOTCONVERT:
			// 変換せずにすべて抽出

			if( listview.GetCount() > 0 )
			{
				extract.SaveAll( lastdir.GetSave(), FALSE );
			}

			lastdir.SaveIni();
			break;

		case IDM_SELECTALL: // すべて選択
			listview.SetItemSelAll(LVIS_SELECTED);
			break;

		case IDM_OPTION: // オプション
			option.DoModal(hWnd);
			break;

		case IDM_README: // Readme.txtを開く
			ShellExecute(NULL, _T("open"), ReadmeFileName, NULL, NULL, SW_SHOWNORMAL);
			break;

		case IDM_HISTORY: // History.txtを開く
			ShellExecute(NULL, _T("open"), HistoryFileName, NULL, NULL, SW_SHOWNORMAL);
			break;

		case IDM_STATE: // State.txtを開く
			ShellExecute(NULL, _T("open"), StateFileName, NULL, NULL, SW_SHOWNORMAL);
			break;

		case IDM_VERSION: // バージョン情報
			version.DoModal(hWnd);
			break;
		}
		break;

	// 右クリックメニュー
	case WM_CONTEXTMENU:
		CreateMenu(lp);
		break;

	case WM_MOUSEWHEEL:
		{
			POINT pos;
			GetCursorPos(&pos);
			HWND pWnd = WindowFromPoint(pos);
			if (pWnd == listview.GetHandle())
				SendMessage(pWnd, WM_MOUSEWHEEL, wp, lp);
			break;
		}

	case WM_NOTIFY:
		{
			// ツールバー
			if (wp == ID_TOOLBAR) {
				LPNMTOOLBAR pNM = (LPNMTOOLBAR)lp;
				switch (pNM->hdr.code) {
					// ファイル履歴
					case TBN_DROPDOWN:
						MainToolBar.CreateMenuHistory(pNM->iItem);
						break;
				}
			}

			// リストビュー
			if (wp == idsMainList) {
				LPNMLISTVIEW pNM = (LPNMLISTVIEW)lp;
				switch (pNM->hdr.code) {
				// ソート
				case LVN_COLUMNCLICK:
					listview.Sort(pNM->iSubItem);
					break;
				// ツールチップ表示
				case LVN_GETINFOTIP:
					listview.ShowTip((LPNMLVGETINFOTIP)lp);
					break;
				// 表示
				case LVN_GETDISPINFO:
					listview.Show((NMLVDISPINFO*)lp);
					break;
				// D&D
				case LVN_BEGINDRAG:
					//extract.SaveDrop();
					LRESULT				lResult;
					listview.OnBeginDrag( (NMHDR*)lp, &lResult );
					break;
				// ダブルクリックで閲覧/再生
				case NM_DBLCLK:
					if (listview.GetCountSel() > 0) {
						extract.DecodeTmp();
						extract.OpenRelate();
					}
					break;
				}
			}
			break;
		}

	case WM_SIZE:
		MainToolBar.SetWindowPos(0, 0, 100, 26);
		SearchToolBar.SetWindowPos(100, 0, LOWORD(lp), 26);
		listview.SetWindowPos(0, 28, LOWORD(lp), HIWORD(lp) - 48);
		statusbar.SetWindowPos(LOWORD(lp));
		break;

	case WM_CLOSE:
		// 保存
		SaveIni();
		listview.SaveIni();
		// 後始末
		extract.Close();
		DestroyWindow(hWnd);
		break;

	case WM_DESTROY:
		PostQuitMessage(0);
		break;

	default:
		return (DefWindowProc(hWnd, msg, wp, lp));
	}

	return 0;
}

void CWinMain::CreateMenu(LPARAM lp)
{
	POINT pt;
	pt.x = LOWORD(lp);
	pt.y = HIWORD(lp);

	HMENU rMenu = LoadMenu(m_hInst, _T("RMENU"));
	HMENU rSubMenu = GetSubMenu(rMenu, 0);

	SetQuickMenu(rMenu);

	TrackPopupMenu(rSubMenu, TPM_LEFTALIGN | TPM_TOPALIGN, pt.x, pt.y, 0, m_hWnd, NULL);
	DestroyMenu(rMenu);
}

void CWinMain::SetQuickMenu(HMENU hMenu)
{
	COption clOption;
	SOption& stOption = clOption.GetOpt();

	struct SQuickSet {
		LPBOOL pbOption;
		int nID;
	} stQuickSet[] = {
		{&stOption.bHighSearchOgg,	IDM_QUICKSET_STD_SEARCHOGG},
		{&stOption.bCreateFolder,	IDM_QUICKSET_EXTRACT_CREATEFOLDER},
		{&stOption.bFixOgg,			IDM_QUICKSET_EXTRACT_FIXOGG},
		{&stOption.bEasyDecrypt,	IDM_QUICKSET_EXTRACT_EASYDECRYPT},
		{&stOption.bDstPNG,			IDM_QUICKSET_EXTRACT_DSTPNG},
		{&stOption.bAlphaBlend,		IDM_QUICKSET_EXTRACT_ALPHABLEND},
		{&stOption.bSusieUse,		IDM_QUICKSET_SUSIE_USE},
		{&stOption.bSusieFirst,		IDM_QUICKSET_SUSIE_FIRST}
	};

	for (int i = 0; i < ARRAYSIZE(stQuickSet); i++) {
		UINT uCheck = MF_BYCOMMAND | (*stQuickSet[i].pbOption == TRUE) ? MF_CHECKED : MF_UNCHECKED;
		CheckMenuItem(hMenu, stQuickSet[i].nID, uCheck);
	}
}

void CWinMain::SetQuickMenuItem(int nID)
{
	COption clOption;
	SOption& stOption = clOption.GetOpt();

	struct SQuickSet {
		LPBOOL pbOption;
		int nID;
	} stQuickSet[] = {
		{&stOption.bHighSearchOgg,	IDM_QUICKSET_STD_SEARCHOGG},
		{&stOption.bCreateFolder,	IDM_QUICKSET_EXTRACT_CREATEFOLDER},
		{&stOption.bFixOgg,			IDM_QUICKSET_EXTRACT_FIXOGG},
		{&stOption.bEasyDecrypt,	IDM_QUICKSET_EXTRACT_EASYDECRYPT},
		{&stOption.bDstPNG,			IDM_QUICKSET_EXTRACT_DSTPNG},
		{&stOption.bAlphaBlend,		IDM_QUICKSET_EXTRACT_ALPHABLEND},
		{&stOption.bSusieUse,		IDM_QUICKSET_SUSIE_USE},
		{&stOption.bSusieFirst,		IDM_QUICKSET_SUSIE_FIRST}
	};

	for (int i = 0; i < ARRAYSIZE(stQuickSet); i++) {
		if (stQuickSet[i].nID == nID)
			*stQuickSet[i].pbOption ^= 1;
	}

	if (nID == IDM_QUICKSET_EXTRACT_DSTPNG) {
		// PNG設定が変更されたらBMPも変更する
		stOption.bDstBMP ^= 1;
	}
	else if (nID == IDM_QUICKSET_SUSIE_USE && stOption.bSusieUse == TRUE) {
		// Susieプラグインを読み込む
		CSusie clSusie;
		clSusie.LoadSpi(stOption.SusieDir);
	}

	clOption.SaveIni();
}