/*
 *	Modified by ICHIMARU Takeshi(ayakawa.m@gmail.com)
 */

#include "stdafx.h"
#include "dlg.h"
#include "tar32res.h"
#include "tar32api.h" // EXTRACTINGINFOEX
#include "util.h"

CTar32StatusDialog::CTar32StatusDialog()
{
	m_cancel = false;
	m_hWnd = NULL;
	m_hThread = NULL;
}
CTar32StatusDialog::~CTar32StatusDialog()
{
	Destroy();
}
HWND CTar32StatusDialog::Create(HWND hParent)
{
	m_hParentWnd = hParent;
	HANDLE  hThread = (HANDLE)_beginthread(ThreadFunc,0,this);
	m_hThread = hThread;
	while(m_hWnd == NULL){
		Sleep(1);	// XXX busy wait....mmm
	}
	return m_hWnd;
}

void _cdecl CTar32StatusDialog::ThreadFunc(LPVOID param)
{
	CTar32StatusDialog *pDlg = (CTar32StatusDialog *)param;
	extern HINSTANCE dll_instance;
	HWND hWnd = CreateDialogParam(dll_instance, MAKEINTRESOURCE(IDD_DIALOG_STATUS),pDlg->m_hParentWnd, WindowFunc, (LPARAM)pDlg);
	//HWND hWnd = CreateDialogParam(dll_instance, MAKEINTRESOURCE(IDD_DIALOG_STATUS),NULL, WindowFunc, (long)pDlg);
	int ret;
	ret = ShowWindow(hWnd, SW_SHOW);
	ret = UpdateWindow(hWnd);
	pDlg->m_hWnd = hWnd;

	{
		MSG msg;
		while(GetMessage(&msg, 0, 0, 0)){
			if(hWnd==NULL || !IsDialogMessage(hWnd,&msg)){
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
	}
	Sleep(0);
	//return 0;
}

INT_PTR CALLBACK CTar32StatusDialog::WindowFunc(HWND hWnd, UINT mes, WPARAM wParam, LPARAM lParam)
{
	extern UINT wm_arcextract;
	CTar32StatusDialog *pDlg = (CTar32StatusDialog*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
	switch(mes){
	case WM_INITDIALOG:
		SetWindowLongPtr(hWnd,GWLP_USERDATA,lParam);
		::SendDlgItemMessage(hWnd,IDC_PROGRESS_FILE,PBM_SETRANGE32,0,100);
		EnableMenuItem(GetSystemMenu(hWnd,FALSE),SC_CLOSE, MF_GRAYED);	//閉じるボタンを無効に
		return 1;
	case WM_DESTROY:
//		return 0;
//		EndDialog(hWnd,0);
//		return 0;
		PostQuitMessage(0);
		return 1;
	case WM_CLOSE:
		DestroyWindow(hWnd);
		return 1;
	case WM_COMMAND:
		switch(LOWORD(wParam)){
		case IDCANCEL:
			if(pDlg)pDlg->m_cancel = true;
			return 1;
			break;	
		}
		break;
	default:
		if(mes == wm_arcextract){
			EXTRACTINGINFOEX64 *pExtractingInfoEx64 = (EXTRACTINGINFOEX64*)lParam;
			switch(wParam){
			case ARCEXTRACT_BEGIN:		//該当ファイルの処理の開始
				::SetDlgItemText(hWnd, IDC_STATIC_FILENAME, pExtractingInfoEx64->szDestFileName);
				{
					size64 size=pExtractingInfoEx64->llFileSize;
					HWND hProg=::GetDlgItem(hWnd,IDC_PROGRESS_FILE);
					LONG_PTR style=::GetWindowLongPtr(hProg,GWL_STYLE);
					if(size==(size64)-1){	//filesize unknown
						//プログレスバーをmarqueeスタイルに
						::SetWindowLongPtr(hProg,GWL_STYLE,style|PBS_MARQUEE);
						::SendMessage(hProg,PBM_SETMARQUEE,TRUE,30);
					}else{
						//プログレスバーを通常スタイルに
						::SetWindowLongPtr(hProg,GWL_STYLE,style&(~PBS_MARQUEE));
					}
				}
				break;
			case ARCEXTRACT_INPROCESS:	//該当ファイルの展開中
				//展開状況の設定
				{
					size64 size=pExtractingInfoEx64->llFileSize;
					size64 wrote=pExtractingInfoEx64->llWriteSize;
					if(size==(size64)-1){	//filesize unknown
						std::string strwrote=fsizeToString(wrote);
						char buf[256];
						_snprintf(buf,COUNTOF(buf),"wrote %s",strwrote.c_str());
						::SetDlgItemText(hWnd, IDC_STATIC_PROGRESS, buf);
						//::SendDlgItemMessage(hWnd,IDC_PROGRESS_FILE,PBM_SETPOS,10,0);
					}else{
						DWORD percent=(DWORD)(wrote*100/size);

						char buf[256];
						std::string strwrote=fsizeToString(wrote);
						std::string strsize=fsizeToString(size);
						_snprintf(buf,COUNTOF(buf),"%d%% (%s / %s)",percent,strwrote.c_str(),strsize.c_str());
						::SetDlgItemText(hWnd, IDC_STATIC_PROGRESS, buf);
						::SendDlgItemMessage(hWnd,IDC_PROGRESS_FILE,PBM_SETPOS,percent,0);
					}
				}
				break;
			case ARCEXTRACT_END:		//処理終了、関連メモリを開放
			case ARCEXTRACT_OPEN:		//該当書庫の処理の開始
			case ARCEXTRACT_COPY:		//ワークファイルの書き戻し
				//nothing to do
				break;
			}

#if 0
			// move to SendArcMessage() by tsuneo at 2001.11.20
			extern HWND g_hwndOwnerWindow;
			extern ARCHIVERPROC *g_pArcProc;
			if(g_hwndOwnerWindow){
				LRESULT wndret = ::SendMessage(g_hwndOwnerWindow,mes,wParam,lParam);
				if(wndret != 0){
					pDlg->m_cancel = true;
				}
			}
			if(g_pArcProc){
				BOOL ProcRet = (*g_pArcProc)(g_hwndOwnerWindow, mes, wParam, pExtractingInfoEx);
				if(!ProcRet){
					pDlg->m_cancel = true;
				}
			}
#endif
			if(pDlg->m_cancel){
				ReplyMessage(1);
				return 1;
			}else{
				return 0;
			}
		}
	}
	return 0;
}

void CTar32StatusDialog::Destroy()
{
	if(m_hThread == NULL){return;}
	LRESULT ret;

	// WM_DESTROYの変わりにDestroyWindowを呼び出さないといけない。
	//ret = SendMessage(m_hWnd, WM_DESTROY, 0, 0);
	// しかしDestroyWindowは別スレッドからは送れない...
	//ret = DestroyWindow(m_hWnd);
	ret = SendMessage(m_hWnd, WM_CLOSE, 0, 0);	// 2000/03/03 by tsuneo
	DWORD code;
	// WaitForSingleObject() must call when m_hThread is alive.
	//ret = WaitForSingleObject(m_hThread,INFINITE);
	while(GetExitCodeThread(m_hThread,&code) && (code == STILL_ACTIVE)){
		Sleep(1);
	}
	//ret = WaitForSingleObject(m_hThread,INFINITE);
	m_hWnd = NULL;
	m_hThread = NULL;
}


//--------------
INT_PTR CALLBACK Tar32ConfirmOverwriteDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg){
	case WM_INITDIALOG:
		{
			LPCTSTR pMsg=(LPCTSTR)lParam;
			if(pMsg){
				SetWindowText(GetDlgItem(hWnd,IDC_EDIT_STATUS),pMsg);
			}
		}
		return FALSE;
	case WM_COMMAND:
		switch(LOWORD(wParam)){
		case IDOK:
			//nothing to do
			break;
		case IDC_BUTTON_OVERWRITE:
		case IDC_BUTTON_OVERWRITE_ALL:
		case IDCANCEL:
			EndDialog(hWnd, LOWORD(wParam));
			break;
		default:
			return FALSE;
		}
	default:
		return FALSE;
	}
	return TRUE;
}

