// RYLLoginDlg.cpp : implementation file
//

#include "stdafx.h"
#include "RYLLogin.h"
#include "RYLLoginDlg.h"

#include "RenderOption.h"
#include "InitValue.h"

#include "../LoginRes/Resource.h"

#include <process.h>

#include <Network/Clientnetwork/ClientEventHandler.h>
#include <Network/Packet/PacketBase.h>

#include <SoundLib/SoundBuffer.h>
#include <SoundLib/SoundManager.h>

#include <mmsystem.h>
#include ".\ryllogindlg.h"

#pragma comment(lib, "winmm")

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define WM_RYL_LAUNCHER_SHUTDOWN	(WM_USER+0x7777)

#ifdef SAFE_DELETE
#undef SAFE_DELETE
#endif

#ifdef SAFE_DELETE_ARRAY
#undef SAFE_DELETE_ARRAY
#endif

#define SAFE_DELETE(p) { if(p) { delete (p); (p) = 0; } }
#define SAFE_DELETE_ARRAY(p) { if(p) { delete [] (p); (p) = 0; } }

class CLauncherEventHandler : public ClientNet::CClientEventHandler
{
public:

    CLauncherEventHandler(CRYLLoginDlg& rylLoginDlg) : m_RylLoginDlg(rylLoginDlg) { }

	virtual int OnDispatch(PktBase* lpPktBase, INET_Addr& peerAddr);
	virtual int OnOpen(int iErrorCode);
    virtual int OnClose();

private:

    CRYLLoginDlg& m_RylLoginDlg;
};

class CDelayedConnectCmd : public ILoginDlgCommand
{
public:

    static CDelayedConnectCmd* Create(CRYLLoginDlg& rylLoginDlg, DWORD dwDelayMilliseconds) 
    { return new CDelayedConnectCmd(rylLoginDlg, dwDelayMilliseconds); }

    virtual bool IsProcessNow(DWORD dwCurrentTime)
    { return m_dwDelayMilliseconds + m_dwStartTime < dwCurrentTime; }

    virtual bool ProcessCommand()
    { return m_RylLoginDlg.ConnectToLoginServer(); }

    virtual ~CDelayedConnectCmd() { }

private:

    CDelayedConnectCmd(CRYLLoginDlg& rylLoginDlg, DWORD dwDelayMilliseconds)
        :   m_RylLoginDlg(rylLoginDlg), 
            m_dwDelayMilliseconds(dwDelayMilliseconds), 
            m_dwStartTime(timeGetTime())
    {
    
    }

    CRYLLoginDlg& m_RylLoginDlg;
    DWORD m_dwDelayMilliseconds;
    DWORD m_dwStartTime;
};


bool GetHostIPByDomain(IN_ADDR &Addr, const char *szDomain)
{
	PHOSTENT pHost = gethostbyname(szDomain);
	if(NULL == pHost)
	{
		return false;
	}

	memcpy(&(Addr.S_un.S_addr), pHost->h_addr_list[0], sizeof(IN_ADDR));
	return true;
}


// CRYLLoginDlg message handlers
unsigned _stdcall UpdateProgress( void *p )
{
	CRYLLoginDlg *lpLogin = reinterpret_cast<CRYLLoginDlg*>(p);

	if (lpLogin->IsServerClosed())
	{
/*
#ifdef _NATION_KR_
		if( IDNO ==AfxMessageBox(
			"서버가 닫혀 있습니다.\n패치는 가능하나 게임 접속은 불가능합니다.\n"
			"패치를 진행하시겠습니까?",
			MB_YESNO ) )
		{
			PostQuitMessage(0);			
			lpLogin->EndDialog(0);
		}
#else
		if( IDNO ==AfxMessageBox(
			"Login Server is currently unavailable. But enable to patch. Patch now?", 
			MB_YESNO ) )
		{
			PostQuitMessage(0);
			lpLogin->EndDialog(0);
		}
#endif
*/
		return 0;
	}

    DWORD dwWaitResult = lpLogin->WaitForWebPageCreated();

    switch(dwWaitResult)
    {
    case WAIT_FAILED:
    case WAIT_TIMEOUT:
    case WAIT_ABANDONED:

        // TODO : make error message
        break;        

    case WAIT_OBJECT_0:

		if (!lpLogin->UpdateFile())
		{
			AfxMessageBox(
                RYLLoginGetMessage(LOGIN_MSG_FAIL_TO_APPLY_PATCH), 
                MB_OK|MB_ICONERROR);

			PostQuitMessage(0);
		}

		lpLogin->SetPatchComplete(true);		

		lpLogin->SetLoginDisplayText(
            RYLLoginGetMessage(LOGIN_MSG_CONNECTED_TO_LOGIN_SERVER_SUCCESSFULLY));

        break;
    }

	return 0;
}

unsigned _stdcall FileCheckProcess(void *p)
{
	CRYLLoginDlg *lpLogin = static_cast<CRYLLoginDlg*>(p);

	if (!lpLogin->UpdateFile(true))
	{
		AfxMessageBox(
            RYLLoginGetMessage( LOGIN_MSG_FAIL_TO_FILE_CHECK ),
            MB_OK|MB_ICONERROR );

		lpLogin->SetPatchComplete(true);

		PostQuitMessage(0);
	}

	return 0;
}

CRYLLoginDlg::CRYLLoginDlg(CWnd* pParent /*=NULL*/)
:	CDialog(CRYLLoginDlg::IDD, pParent), 
    m_szVersionSignature(STR_VERSION_SIGNATURE),
    m_dwLocalClientVersion(0),
    m_pLoginSocket(0)
{
	m_bServerClosed = false;
	m_bFileCheck = false;

#ifdef _NATION_GM_
	m_TMsgDlg = NULL;
#endif

    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_pStreamSound = NULL;
	
    m_hWebPageCreated = CreateEvent(0, TRUE, FALSE, NULL);

	m_fBlueProgressPercentage = 0.0f;
	m_fRedProgressPercentage = 0.0f;

	m_nFade = 0;

	m_bUpdating = FALSE;

	m_nUpdateAni = 0;	
	m_nUpdateLogoAni = 0;

    m_pLoginSocket  = new LoginSocket;    

	m_bShowServerSelectDlg = FALSE; 

	m_nShowRateServerSelectDlg = 0;
	m_bCheckSetup = FALSE;

	m_bCheckSucLoginData = FALSE;

	m_nServerClass = 1; // 0: InHouseServer // 1 : TestServer //2: RealServer //3: Taiwan 윽 개색 

	m_strLoginServerAddrFromRegistry = "";
	m_strPatchUrlFromRegistry = "";
    m_strDefaultLoginServerAddr = "";

	m_ConnectionState = CS_IDLE;	
}

void CRYLLoginDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_BUTTON_NEWACC, m_btnNewAcc);
	DDX_Control(pDX, IDC_BUTTON_PSW, m_btnPsw);
	DDX_Control(pDX, IDC_BUTTON_SETUP, m_btnSetup);
	DDX_Control(pDX, IDC_BUTTON_FILECHECK, m_btnFileCheck);
	DDX_Control(pDX, IDC_BUTTON_START,m_btnServerStart);
	DDX_Control(pDX, IDC_BUTTON_MUSIC, m_btnMusic);
	DDX_Control(pDX, IDC_BUTTON_END, m_btnEnd);
	DDX_Control(pDX, IDC_STATIC_LOGINTEXT, m_stcLoginDisplay);
	DDX_Control(pDX, IDC_STATIC_VERSIONVIEW, m_stcVersionView);
	DDX_Control(pDX, IDC_LIST_SERVER2, m_ServerList);
}

BEGIN_MESSAGE_MAP(CRYLLoginDlg, CDialog)
	//{{AFX_MSG_MAP(CRYLLoginDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_NEWACC, OnBnClickedButtonNewacc)
	ON_BN_CLICKED(IDC_BUTTON_PSW, OnBnClickedButtonPsw)
	ON_BN_CLICKED(IDC_BUTTON_END, OnBnClickedButtonEnd)
	ON_WM_MOVE()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_ERASEBKGND()
	ON_WM_CTLCOLOR()
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_BUTTON_MUSIC, OnBnClickedButtonMusic)
	ON_BN_CLICKED(IDC_BUTTON_FILECHECK, OnBnClickedButtonFilecheck)
	ON_BN_CLICKED(IDC_BUTTON_SETUP, OnBnClickedButtonSetup)
	ON_MESSAGE(WM_RYL_LAUNCHER_SHUTDOWN, OnRylLauncherShutdown)
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_BUTTON_START, OnBnClickedButtonStart)
	ON_LBN_SELCHANGE(IDC_LIST_SERVER2, OnLbnSelchangeListServer)
	ON_LBN_DBLCLK(IDC_LIST_SERVER2, OnLbnDblclkListServer)
	//}}AFX_MSG_MAP
	
END_MESSAGE_MAP()


BOOL CRYLLoginDlg::OnInitDialog()
{
	//	RZipRapper::FileCompress( "C:\\Dev\\RYL\\Launcher\\PatchInfo", "C:\\Dev\\RYL\\Launcher\\PatchInfo.zip" );
/*#ifdef _NATION_JP_
	// 일본 G-CIA 런처에서 실행되었나 체크
	HWND hGCIA = ::FindWindow( NULL, "G-CIA" );
	if( NULL == hGCIA )
	{
		MessageBox( "Please run G-CIA launcher", "Error!", MB_ICONERROR|MB_OK );
		PostQuitMessage(0);
		EndDialog(0);
	}
#endif	// _NATION_JP_*/

	CDialog::OnInitDialog();

	InitClientFoloder();
	RYLLoginInitMessage(m_strRYLFolder);

	char szClassName[MAX_PATH];
	char szWindowTitle[MAX_PATH];

    ::GetClassName(*this, szClassName, MAX_PATH);
    szClassName[MAX_PATH - 1] = 0;

    GetWindowText(szWindowTitle, MAX_PATH);
    szWindowTitle[MAX_PATH - 1] = 0;
	
	CWnd *lpCheckSelfWnd= FindWindow( szClassName, "Login" );
	if (lpCheckSelfWnd)
	{	
		AfxMessageBox( RYLLoginGetMessage(LOGIN_MSG_LAUNCHER_ALREADY_RUNNING) );
		PostQuitMessage(0);
	}

	m_ConnectionState = CS_START;

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

#ifdef _NATION_GM_
	m_TMsgDlg = new CMSGDialog();
#endif
	// TODO: Add extra initialization here
	InitInterface();	


	PlayBGM();
	Sleep(1050);

	m_dlgSplash.DoModal();

	SetTimer( WM_FADETIMER, 10, NULL );
	SetTimer( WM_ANITIMER, 75, NULL );
	SetTimer( WM_LOGOANITIMER, 100, NULL );
    SetTimer( WM_EVENT_HANDLER_TIMER, 100, NULL);

	//PlayBGM();

	m_bPatchComplete    = false;
	m_nLoginProcess     = 0;

	m_stcLoginDisplay.SetCenterText(FALSE);
    SetWindowText("Login");


#ifdef _NATION_GM_
	if(m_TMsgDlg)
	{
		int iReturn = m_TMsgDlg->DoModal();
		if(iReturn == IDCANCEL)
		{
			PostQuitMessage(0);
			return FALSE;
		}
	}
#endif

	ConnectToLoginServer();
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CRYLLoginDlg::OnDestroy()
{
	SAFE_DELETE(m_pLoginSocket);    
    SAFE_DELETE(m_pBoldFont);

#ifdef _NATION_GM_
	SAFE_DELETE(m_TMsgDlg);
#endif

    LoginDlgCommandList::iterator pos = m_LoginDlgCommandList.begin();
    LoginDlgCommandList::iterator end = m_LoginDlgCommandList.end();

    for(; pos != end; ++pos)
    {
        ILoginDlgCommand* lpLoginDlgCommand = *pos;
        SAFE_DELETE(lpLoginDlgCommand);
    }

    m_LoginDlgCommandList.clear();


	if (CS_IDLE == m_ConnectionState || 
        CS_SERVERSELECT == m_ConnectionState)
	{
        if (0 != m_hWebPageCreated)
        {
            CloseHandle(m_hWebPageCreated);
            m_hWebPageCreated = 0;
        }

		CDialog::OnDestroy();
	}
	else
	{
		m_UpdateManager.Terminate();
		return;	// update manager가 중단되면서 패치실패시 강제종료가 이루어짐
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CRYLLoginDlg::OnPaint() 
{
    CPaintDC dc(this); // device context for painting

	if (IsIconic())
	{
		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon 
        // kidleon@kronet.net
		//dc.DrawIcon(x, y, m_hIcon);
    }
	else
	{
		CRect rect;
		GetClientRect(&rect);

		CMemDC	pDC( &dc, rect);

		RenderBack( pDC, m_btmBase, 0, 0 );

		BITMAP bmInfo;		
		m_btmFILE.GetBitmap(&bmInfo);	

		int nPixelSize = (int)( bmInfo.bmWidth * ( m_fBlueProgressPercentage * 0.01f ) );

		if( m_ConnectionState == CS_SERVERSELECT )
		{
			RenderBack( pDC, m_btmFILE, 31, 408 );
		}
		else
		{
			RenderBack( pDC, m_btmFILE, 31, 408, nPixelSize, bmInfo.bmHeight );
		}

		m_btmFTP.GetBitmap(&bmInfo);

		nPixelSize = (int)( bmInfo.bmWidth * ( m_fRedProgressPercentage * 0.01f ) );

		if( m_ConnectionState == CS_SERVERSELECT )
		{
			RenderBack( pDC, m_btmFTP, 31, 427 );		
		}
		else
		{
			RenderBack( pDC, m_btmFTP, 31, 427, nPixelSize, bmInfo.bmHeight );		
		}

		RenderAni( pDC, m_btmAlarmAni, 499, 408, 34, 34, m_nUpdateAni );

		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CRYLLoginDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CRYLLoginDlg::RenderBack( CDC &rDC, CBitmap &rBitmap, int Px, int Py , int SizeX, int SizeY )
{
	CDC memDC;
	memDC.CreateCompatibleDC(&rDC);

	CBitmap *pOldBitmap = memDC.SelectObject(&rBitmap);	
	CSize sBitmap = rBitmap.GetBitmapDimension();

	BITMAP bmInfo;
	rBitmap.GetBitmap(&bmInfo);	

	if( SizeX == -1 && SizeY == -1 )
    {
		rDC.BitBlt(Px,Py,bmInfo.bmWidth,bmInfo.bmHeight,&memDC,0,0,SRCCOPY);
    }
	else
    {
		rDC.BitBlt(Px,Py,SizeX,SizeY,&memDC,0,0,SRCCOPY);
    }

	memDC.SelectObject(pOldBitmap);

}


void CRYLLoginDlg::OnBnClickedButtonNewacc()
{
	// TODO: Add your control notification handler code here
#ifdef _NATION_JP_
	AfxMessageBox( "Not available now." );
	return;
#endif

	ShellExecute(NULL, "open", STR_NEW_ACCOUNT_URL, NULL, NULL, SW_SHOWNORMAL);
}


void CRYLLoginDlg::OnBnClickedButtonPsw()
{
	// TODO: Add your control notification handler code here
#ifdef _NATION_JP_
	AfxMessageBox( "Not available now." );
	return;
#endif

	ShellExecute(NULL, "open", STR_CHANGE_PASSWORD_URL, NULL, NULL, SW_SHOWNORMAL);	
}

void CRYLLoginDlg::OnBnClickedButtonEnd()
{
	// TODO: Add your control notification handler code here	
	OnOK();
}


LRESULT CRYLLoginDlg::OnRylLauncherShutdown(WPARAM,LPARAM)
{
	return SendMessage( WM_CLOSE );
}


void CRYLLoginDlg::PlayBGM(void)
{
	CString strSoundName;

	try
	{
		strSoundName = m_strRYLFolder + "/lc2.ogg";
		CSoundManager::GetInstance().Create( GetSafeHwnd() );	
		
        ISoundObject &sndBuf = CSoundManager::GetInstance().GetBuffer(
            strSoundName , false, true, 1, 0x0004000 );

		sndBuf.Play( true );	
		m_bBGMPlay = TRUE;
		m_pStreamSound = &sndBuf;
	}
	catch( exception & e )
	{
		MessageBox( e.what(), STR_PLAY_BGM_ERROR );

		m_pStreamSound = NULL;
	}	
}


void CRYLLoginDlg::InitClientFoloder(void)
{
	HKEY hMPClientReg = 0;

    char strPath[MAX_PATH]="";

	if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, STR_CLIENT_REGISTRY_SUBKEY, 
        0, KEY_READ, &hMPClientReg) == ERROR_SUCCESS)
	{
        DWORD dwReadType = 0;
	    DWORD dwReadLens = MAX_PATH;

        if (RegQueryValueEx(hMPClientReg, STR_CLIENT_REGISTRY_VALUE_NAME, 0, 
            &dwReadType, reinterpret_cast<unsigned char*>(strPath), &dwReadLens) == ERROR_SUCCESS)
        {
            strPath[MAX_PATH - 1] = 0;
		    m_strRYLFolder.SetString(strPath);
        }

        dwReadLens = MAX_PATH;
		if (RegQueryValueEx(hMPClientReg, "Server", 0, &dwReadType, 
            reinterpret_cast<unsigned char*>(strPath), &dwReadLens) == ERROR_SUCCESS)
		{
            strPath[MAX_PATH - 1] = 0;
			m_strLoginServerAddrFromRegistry.SetString(strPath);	
		}

        dwReadLens = MAX_PATH;
		if (RegQueryValueEx(hMPClientReg, "PatchServer", 0, &dwReadType, 
            reinterpret_cast<unsigned char*>(strPath), &dwReadLens) == ERROR_SUCCESS)
		{			
            strPath[MAX_PATH - 1] = 0;
			m_strPatchUrlFromRegistry.SetString(strPath);
		}

        RegCloseKey(hMPClientReg);
	}
	else
	{
		MessageBox(RYLLoginGetMessage(LOGIN_MSG_CLIENT_NOT_INSTALLED));
	}
}

void CRYLLoginDlg::InitInterface(void)
{
	SetWindowPos( NULL, 0,0, 662, 580, SWP_NOMOVE | SWP_NOZORDER );	

	//	HINSTANCE hDefault = AfxGetResourceHandle();
	//	m_hResDll = LoadLibrary( "LoginRes.dll" );

	SetDllResource();

	m_btmBase.LoadBitmap(IDB_BITMAP_BACK);
	m_btmFILE.LoadBitmap(IDB_BITMAP_PROGRESSFILE);
	m_btmFTP.LoadBitmap(IDB_BITMAP_PROGRESSTOTAL);

	m_btmAlarmAni.LoadBitmap(IDB_BITMAP_ALARMANI);

	BOOL bRet = m_btmPatching.LoadBitmap(IDB_BITMAP_PATCHING);
	bRet = m_btmComplete.LoadBitmap(IDB_BITMAP_ALARM);
	bRet = m_btmLoging.LoadBitmap(IDB_BITMAP_LOGINING);

	m_btnNewAcc.SetBitmap(IDB_BITMAP_NEWACC0, IDB_BITMAP_NEWACC1, IDB_BITMAP_NEWACC2);
	m_btnPsw.SetBitmap(IDB_BITMAP_PSW0, IDB_BITMAP_PSW1, IDB_BITMAP_PSW2);
	m_btnSetup.SetBitmap(IDB_BITMAP_SETUP0, IDB_BITMAP_SETUP1, IDB_BITMAP_SETUP2);
	m_btnFileCheck.SetBitmap(IDB_BITMAP_FILECHECK0, IDB_BITMAP_FILECHECK1, IDB_BITMAP_FILECHECK2);
	m_btnServerStart.SetBitmap(IDB_BITMAP_START0, IDB_BITMAP_START1, IDB_BITMAP_START2);
	m_btnMusic.SetBitmap(IDB_BITMAP_MUSIC0, IDB_BITMAP_MUSIC1, IDB_BITMAP_MUSIC2);
	m_btnEnd.SetBitmap(IDB_BITMAP_END0, IDB_BITMAP_END1, IDB_BITMAP_END2);	


	srand(time(NULL));

	switch(rand() % 3)
	{
	case 0: m_dlgSplash.m_btmSplash.LoadBitmap(IDB_BITMAP_BANNER1); break;
	case 1: m_dlgSplash.m_btmSplash.LoadBitmap(IDB_BITMAP_BANNER2); break;
	case 2: m_dlgSplash.m_btmSplash.LoadBitmap(IDB_BITMAP_BANNER3); break;
	}

#ifdef _NATION_GM_
	if(m_TMsgDlg)
		m_TMsgDlg->InitInterface();
#endif

	//	AfxSetResourceHandle( hDefault );		
	SetDefaultResource();

	m_ServerList.SetWindowPos( NULL, 510, 55, 135, 260, SWP_NOZORDER );			

	// 리뉴얼 버튼 좌표
	m_btnNewAcc.SetWindowPos(NULL, 20, 542, m_btnNewAcc.GetSizeX(), m_btnNewAcc.GetSizeY() , SWP_NOZORDER);
	m_btnPsw.SetWindowPos(NULL, 134, 542, m_btnPsw.GetSizeX(), m_btnPsw.GetSizeY(), SWP_NOZORDER) ;
	m_btnSetup.SetWindowPos(NULL, 245, 542, m_btnSetup.GetSizeX(), m_btnSetup.GetSizeY(), SWP_NOZORDER);
	m_btnFileCheck.SetWindowPos(NULL, 319, 542, m_btnFileCheck.GetSizeX(), m_btnFileCheck.GetSizeY(), SWP_NOZORDER);
	m_btnServerStart.SetWindowPos(NULL, 520, 320, m_btnServerStart.GetSizeX(), m_btnServerStart.GetSizeY(), SWP_NOZORDER);
	m_btnMusic.SetWindowPos(NULL, 429, 542, m_btnMusic.GetSizeX(), m_btnMusic.GetSizeY(), SWP_NOZORDER);
	m_btnEnd.SetWindowPos(NULL, 595, 542, m_btnEnd.GetSizeX(), m_btnEnd.GetSizeY(), SWP_NOZORDER);

	SetWindowText( "R.O.W Online" );

	m_pBoldFont = new CFont;
	m_pBoldFont->CreateFont(
        16,0,0,0,500,0,0,0,0,0,0,ANTIALIASED_QUALITY,0,"Arial");

	m_stcLoginDisplay.SetWindowPos( NULL, 34, 387, 494 - 41, 403 - 387, SWP_NOZORDER );	

	m_stcLoginDisplay.SetFont(m_pBoldFont);	
	m_stcLoginDisplay.SetCenterText();
	m_stcLoginDisplay.SetColor(RGB(29,29,29));
	m_stcLoginDisplay.SetGradientColor(RGB( 29,29, 29));
	m_stcLoginDisplay.SetTextColor(RGB(255,255,255));
	m_stcLoginDisplay.SetCenterText( FALSE );

	m_stcLoginDisplay.SetWindowText( RYLLoginGetMessage(LOGIN_MSG_CONNECTING_TO_LOGIN_SERVER) );


	m_stcVersionView.SetWindowPos( NULL, 16, 7, 20 * 6, 16, SWP_NOZORDER );

	m_stcVersionView.SetFont(m_pBoldFont);
	m_stcVersionView.SetCenterText();
	m_stcVersionView.SetColor(RGB(0xFF,0xFF,0xFF));
	m_stcVersionView.SetGradientColor(RGB( 0xDF,0xDF, 0xFF));
	m_stcVersionView.SetTextColor(RGB(55,55,55));
	//m_stcVersionView.SetCenterText( FALSE );

	m_stcVersionView.SetWindowText( "Client ver. : TEST" );	
}

void CRYLLoginDlg::InitWebBrowser(void)
{
	m_WebPage.Create(NULL, NULL, (WS_CHILD | WS_VISIBLE ),
        CRect(15, 30, 492, 369), this, IDR_WEBVIEW, NULL);	

	m_WebPage.Navigate(m_strRYLFolder + "/Notice/default.html");		

    SetEvent(m_hWebPageCreated);
}

void CRYLLoginDlg::OnMove(int x, int y)
{
	//Invalidate( FALSE );	
	CDialog::OnMove(x, y);
}

void CRYLLoginDlg::OnLButtonDown(UINT nFlags, CPoint point)
{	
	PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y) ); 
	CDialog::OnLButtonDown(nFlags, point);
}

void CRYLLoginDlg::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: Add your message handler code here and/or call default
	CDialog::OnMouseMove(nFlags, point);
}



// patch 프로세스의 시작점
bool CRYLLoginDlg::UpdateFile( bool bFileCheck )
{
	//#if defined _NATION_JP_
	//	m_ConnectionState = CS_SERVERSELECT;
	//	return true;
	//#endif

	m_bUpdating = TRUE;
	m_ConnectionState = CS_FILEINFOGATHERING;	

	m_UpdateManager.SetRootPath( m_strRYLFolder );

	if( m_strPatchUrlFromRegistry != "" )
	{
		m_UpdateManager.m_strServerPath = m_strPatchUrlFromRegistry;
	}
	else
	{
		m_UpdateManager.m_strServerPath = m_strPatchUrlFromLoginServer;
	}

	m_UpdateManager.SetProgressInfo(
		&m_fBlueProgressPercentage, &m_fRedProgressPercentage,
		&m_stcLoginDisplay, this );

	m_UpdateManager.Init();

	if( !bFileCheck )
	{
#if (defined(_NATION_MY_) && defined(_P1_)) // 국내와 말레이시아만 패치때마다 Notice 다운로드방식임(나머지 해외는 전부 웹방식 notice)
		// 공지사항 파일 전송 및 압축해제
		if( false == m_UpdateManager.ProcessNoticeFiles() )
		{
			return false;
		}
#endif
		m_WebPage.Navigate( m_strRYLFolder + "/Notice/default.html" );	
	}

	// 서버측 patchinfo 다운로드 및 로딩
	if( false == m_UpdateManager.LoadServerPatchInfo() )
	{
		return false;
	}

	//	// 로컬측 patchinfo 로딩(없으면 생성)
	//	if( false == m_UpdateManager.LoadLocalPatchInfoCache() )
	//	{
	//		return false;
	//	}

	// 서버측과 로컬측 patchinfo 를 비교해 전송받아야 할 패키지 파일목록 생성
	if( false == m_UpdateManager.CollectDownloadFileList(bFileCheck) )
	{
		return false;
	}

	m_ConnectionState = CS_PATCHDOWN;	

	// 전송받을 패키지 파일들을 다운로드
	if( false == m_UpdateManager.DownloadUpdateFile() )
	{
		return false;
	}

	// 전송받은 패키지 파일에서 필요한 파일들의 
	if( false == m_UpdateManager.ExtractPatchFiles() )
	{
		return false;
	}

	m_UpdateManager.CleanUp();

	CRect rcUpdate;
	rcUpdate.left = 12;
	rcUpdate.right = 655;
	rcUpdate.top = 381;
	rcUpdate.bottom = 528;
	InvalidateRect( rcUpdate, FALSE );	
	if( m_UpdateManager.m_bUpdateLogin != TRUE )
	{
		m_ConnectionState = CS_SERVERSELECT;
	}
	InvalidateRect( rcUpdate, FALSE );

	m_bUpdating = FALSE;

	int nVersion = m_UpdateManager.GetVersion(); // 패치후므로 버전번호가 PatchInfoV2 에서 받은 것으로 업데이트 되었다

	if( nVersion != -1 )
	{
#ifdef _P1_	// By Belldandy(2005.02.02) 파트1과 파트2 통합 작업
		nVersion -= 100;
#endif
		SetClientVer( nVersion );
	}

	m_bCheckSetup = TRUE;

	if( m_UpdateManager.m_bUpdateLogin == TRUE )
	{		
		AfxMessageBox( RYLLoginGetMessage(LOGIN_MSG_LAUNCHER_RESTART) );
		PostQuitMessage(0);
		EndDialog(0);
	}

	if( m_bFileCheck )
	{
		AfxMessageBox( RYLLoginGetMessage(LOGIN_MSG_FILE_CHECK_FINISHED) );
	}

	return true;
}

BOOL CRYLLoginDlg::OnEraseBkgnd(CDC* pDC)
{
	// TODO: Add your message handler code here and/or call default
	return TRUE;
	//return CDialog::OnEraseBkgnd(pDC);
}

void CRYLLoginDlg::OnTimer(UINT nIDEvent)
{
	// TODO: Add your message handler code here and/or call default

	switch( nIDEvent )
	{
	case WM_FADESERVERSELECT:
		{			
		}
		break;
	case WM_FADETIMER:
		{
			m_nFade+=3;

			if( m_nFade >= 100 )
			{
				KillTimer( nIDEvent );		
				InitWebBrowser();
			}
		}
		break;

	case WM_ANITIMER:
		{
			if( m_bUpdating == TRUE )
			{
				m_nUpdateAni++;
				if( m_nUpdateAni == 21 )
				{
					m_nUpdateAni = 0;
				}

				/*m_nUpdateLogoAni++;
				if( m_nUpdateLogoAni == 21 )
				{
				m_nUpdateLogoAni = 0;
				}*/
			}
			else
			{				
			}

			CRect rcUpdate;

			// 전기구슬-_-애니
			rcUpdate.left = 499;
			rcUpdate.top = 408;
			rcUpdate.right = 499 + 32;
			rcUpdate.bottom = 408 + 32;
			InvalidateRect( rcUpdate, FALSE );

			// 게이지 위
			rcUpdate.left = 31;
			rcUpdate.top = 408;
			rcUpdate.right = 31 + 464;
			rcUpdate.bottom = 408 + 16;
			InvalidateRect( rcUpdate, FALSE );

			// 게이지 아래
			rcUpdate.left = 31;
			rcUpdate.top = 427;
			rcUpdate.right = 31 + 464;
			rcUpdate.bottom = 427 + 16;
			InvalidateRect( rcUpdate, FALSE );

			// 좌하단 로고 애니 -> 없어짐
			//rcUpdate.left = 23;
			//rcUpdate.top = 446;
			//rcUpdate.right = 23 + 163;
			//rcUpdate.bottom = 446 + 94;
			//InvalidateRect( rcUpdate, FALSE );
		}
		break;

	case WM_LOGOANITIMER:
		{
			m_nUpdateLogoAni++;
			if( m_nUpdateLogoAni >= 21 )
				m_nUpdateLogoAni = 0;
		}

    case WM_EVENT_HANDLER_TIMER:

        if (0 != m_pLoginSocket)
        {
            m_pLoginSocket->HandleEvents(30);
        }

        {
            LoginDlgCommandList::iterator pos = m_LoginDlgCommandList.begin();
            LoginDlgCommandList::iterator end = m_LoginDlgCommandList.end();
        
            DWORD dwCurrentTime = timeGetTime();

            for(; pos != end; )
            {
                ILoginDlgCommand* lpLoginDlgCommand = *pos;

                if (0 == lpLoginDlgCommand)
                {
                    pos = m_LoginDlgCommandList.erase(pos);
                }
                else if (lpLoginDlgCommand->IsProcessNow(dwCurrentTime))
                {
                    lpLoginDlgCommand->ProcessCommand();
                    delete lpLoginDlgCommand;

                    pos = m_LoginDlgCommandList.erase(pos);
                }
                else
                {
                    ++pos;
                }
            }
        }
		break;
	}

	CDialog::OnTimer(nIDEvent);
}

void CRYLLoginDlg::OnBnClickedButtonMusic()
{
	// TODO: Add your control notification handler code here

	if( m_bBGMPlay == TRUE && m_pStreamSound )
	{
		m_bBGMPlay = FALSE;
		m_pStreamSound->Stop( 1 );
	}
	else if( m_pStreamSound )
	{		
		m_bBGMPlay = TRUE;
		m_pStreamSound->Play( true );
	}

}

void CRYLLoginDlg::OnBnClickedButtonFilecheck()
{
	//#if defined _NATION_JP_
	//	return;
	//#endif

	// TODO: Add your control notification handler code here

	if( m_bCheckSucLoginData == FALSE )
		return;

	if( m_bUpdating )
	{
		AfxMessageBox( RYLLoginGetMessage(LOGIN_MSG_CANNOT_FILECHECK_PATCH_IN_PROGRESS) );
	}
	else
	{
		//		CString strChecker;
		//		strChecker = m_strRYLFolder + "/FileChecker.exe";
		//		Execute( strChecker , FALSE );


		if( IDOK ==  AfxMessageBox( RYLLoginGetMessage(LOGIN_MSG_CONFIRM_FILECHECK), MB_ICONQUESTION|MB_OKCANCEL ) )
		{
			//			CString strPatchInfoCache;
			//			strPatchInfoCache = m_strRYLFolder + "\\PatchInfo.cache";
			//			DeleteFile( strPatchInfoCache );

			DWORD dwThread;
			unsigned ThreadID;
			m_bFileCheck = true;	// 파일체크모드
			dwThread = _beginthreadex( NULL, 0, FileCheckProcess, this, 0, &ThreadID );		

			SetPatchComplete(false);
		}
	}
}

void CRYLLoginDlg::OnBnClickedButtonSetup()
{
	// TODO: Add your control notification handler code here	
	CString strSetup;
	strSetup = m_strRYLFolder + "\\clientsetup.exe";	
	Execute( strSetup , TRUE );
}

void CRYLLoginDlg::Execute( CString strExec , BOOL bWait )
{
	if( m_bUpdating )
		return;
	STARTUPINFO si={sizeof(STARTUPINFO),0,};
	PROCESS_INFORMATION pi;	

	BOOL bReturn = CreateProcess( strExec,NULL, NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);
	//if( r == FALSE )
	//	CreateProcess( "Clientsetup.exe",NULL, NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);
	if( bReturn == TRUE && bWait == TRUE)
		WaitForSingleObject( pi.hProcess, INFINITE );
}

void CRYLLoginDlg::RenderAni( CDC &rDC, CBitmap &rBitmap, int Px, int Py , int SizeX, int SizeY, int nAniNum )
{

	CBitmap *pOldBitmap;
	CDC memDC;
	memDC.CreateCompatibleDC(&rDC);
	pOldBitmap=memDC.SelectObject(&rBitmap);	
	CSize sBitmap=rBitmap.GetBitmapDimension();

	BITMAP bmInfo;
	rBitmap.GetBitmap(&bmInfo);	

	int nAniX = bmInfo.bmWidth / SizeX;
	int nAniY = bmInfo.bmHeight / SizeY;	

	int nSX = ( nAniNum % nAniX ) * SizeX;
	int nSY = ( nAniNum / nAniX ) * SizeY;

	rDC.BitBlt( Px, Py, SizeX, SizeY, &memDC, nSX, nSY, SRCCOPY );

	memDC.SelectObject(pOldBitmap);
}

DWORD CRYLLoginDlg::GetLocalClientVersion()
{
    if (0 == m_dwLocalClientVersion)
    {
        CString strVerFile(m_strRYLFolder);
        strVerFile.Append("/versioninfo.dat");

	    FILE *fp = fopen(strVerFile.GetBuffer(0), "r");

        if (0 != fp)
        {
            fscanf(fp, "%ul", &m_dwLocalClientVersion);

        #ifdef _P1_	// By Belldandy (2005.02.02) 파트1과 파트2 통합 작업
	        m_dwLocalClientVersion += 100;
        #endif

	        fclose(fp);
        }
    }

	return m_dwLocalClientVersion;
}

void CRYLLoginDlg::SetClientVer(DWORD dwVer)
{	
	CString strVerFile(m_strRYLFolder);
    strVerFile.Append("/versioninfo.dat");

	FILE *fp = fopen(strVerFile.GetBuffer(0), "w");

    if (fp)
    {
        fprintf(fp, "%ul", dwVer);
	    fclose(fp);
    }
}

void CRYLLoginDlg::ExecuteClient( int nServer ) 
{
#ifdef _P1_
	CString strSetupFilename;
	strSetupFilename = m_strRYLFolder + "\\MP.Ini";
	FILE *fp = fopen( strSetupFilename.GetBuffer( 0 ), "rb" );
	if( fp == NULL )
	{
		m_bCheckSetup = TRUE;
	}
	else
	{
		fclose( fp );
	}

	strSetupFilename = m_strRYLFolder + "\\RenderOption.dat";
	fp = fopen( strSetupFilename.GetBuffer( 0 ), "rb" );
	if( fp == NULL )
	{
		m_bCheckSetup = TRUE;
	}
	else
	{
		fclose( fp );
	}

#else
	HKEY hKey = NULL;

	if(
		RegOpenKeyEx( HKEY_LOCAL_MACHINE, STR_CLIENT_REGISTRY_SUBKEY, 0, KEY_READ, &hKey ) !=
		ERROR_SUCCESS )
	{
		MessageBox( RYLLoginGetMessage(LOGIN_MSG_CLIENT_NOT_INSTALLED) );
		PostQuitMessage(0);
		EndDialog(0);
	}
	else
	{
		CInitValue ci;
		ci.Init();
		if( false == ci.Load( hKey ) )
		{
			m_bCheckSetup = TRUE;
		}

		if( false == CRenderOption::Load( hKey ) )
		{
			m_bCheckSetup = TRUE;
		}
	}
#endif

	if( m_bCheckSetup )
	{
		OnBnClickedButtonSetup();
	}

	if( m_bBGMPlay == TRUE && m_pStreamSound )
	{
		m_bBGMPlay = FALSE;
		m_pStreamSound->Stop( 1 );
	}	

#if defined(_NATION_KR_)

	CString strDRParam;
	STARTUPINFO dr_si={sizeof(STARTUPINFO),0,};
	PROCESS_INFORMATION dr_pi;

	//	strDRParam.Format( "\"%s\\DumpReporter.exe\" %s %d",
	//		m_strRYLFolder.GetBuffer(0),
	strDRParam.Format( "\"%s\" %s %d",
		m_strRYLFolder+"\\DumpReporter.exe",
#if defined(_TEST_)
		"0",
#elif defined(_REGULAR_)
		"1",
#elif defined(_BG_)
		"2",
#endif
		GetLocalClientVersion());


#if defined(_TEST_)

	// DumpReporter 실행을 테섭클라이언트에서만 하도록 바뀌었음

	/*BOOL bDRRet = CreateProcess( m_strRYLFolder + "\\DumpReporter.exe", strDRParam.GetBuffer( 0 ), NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,m_strRYLFolder,&dr_si,&dr_pi);

	if( bDRRet == TRUE )
	{
		WaitForSingleObject( dr_pi.hProcess, INFINITE );
	}*/

	//system( strDRParam.GetBuffer(0) );

#endif // defined(_TEST_)

#endif // defined(_NATION_KR_)

	CString strParam;
	STARTUPINFO si={sizeof(STARTUPINFO),0,};
	PROCESS_INFORMATION pi;

	strParam.Format( "%s %d %s",
		inet_ntoa(m_ServerListData.m_ServerGroup[nServer].m_Address),
		m_ServerListData.m_ServerGroup[nServer].m_Group,
		AfxGetApp()->m_lpCmdLine);

	BOOL bRet = CreateProcess( m_strRYLFolder + "\\Client.exe", 
        strParam.GetBuffer( 0 ), NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);

	DWORD dwErr = GetLastError();
}

static CString s_strMessage[ LOGIN_MSG_MAX_COUNT ];

void RYLLoginInitMessage(const char* szFolder)
{
	s_strMessage[ LOGIN_MSG_SELECT_SERVER ]
#ifdef _NATION_KR_
	= "서버를 선택해 주세요.";
#else
	= "Select a server.";
#endif

	s_strMessage[ LOGIN_MSG_LAUNCHER_ALREADY_RUNNING ]
#ifdef _NATION_KR_
	= "이미 실행중입니다.";
#else
	= "Launcher is already running.";
#endif

	s_strMessage[ LOGIN_MSG_LAUNCHER_RESTART ]
#ifdef _NATION_KR_
	= "런처 업데이트를 위해 종료합니다. 다시 실행해주세요.";
#else
	= "Please restart launcher in order to update.";
#endif

	s_strMessage[ LOGIN_MSG_FAIL_TO_CONNECT_TO_LOGIN_SERVER ]
#ifdef _NATION_KR_
	= "로그인서버에 연결할 수 없습니다. 다시 시도하시겠습니까?";
#else
	= "Failed to connect to login server. Try again ?";
#endif

	s_strMessage[ LOGIN_MSG_FAIL_TO_GET_PATCHINFO ]
#ifdef _NATION_KR_
	= "패치정보 파일을 받지 못했습니다.";
#else
	= "Failed to get Patchinfo file.";
#endif

	s_strMessage[ LOGIN_MSG_CLIENT_NOT_INSTALLED ]
#ifdef _NATION_KR_
	= "ROW Online이 설치되어있지 않습니다.";
#else
	= "Program is not installed correctly.";
#endif

	s_strMessage[ LOGIN_MSG_CANNOT_FILECHECK_PATCH_IN_PROGRESS ]
#ifdef _NATION_KR_
	= "현재 패치중입니다. 패치 종료후 오류검사를 실행해주시기 바랍니다.";
#else
	= "Cannot perform filecheck. File check in progress.";
#endif

	s_strMessage[ LOGIN_MSG_CONFIRM_FILECHECK ]
#ifdef _NATION_KR_
	= "파일 오류 검사를 실행하시겠습니까?";
#else
	= "Proceed file check ?";
#endif

	s_strMessage[ LOGIN_MSG_CONNECTING_TO_LOGIN_SERVER ]
	= "Connecting to Login Server";

	s_strMessage[ LOGIN_MSG_CONNECTED_TO_LOGIN_SERVER_SUCCESSFULLY ]
	= "Connected to Login Server successfully";

	s_strMessage[ LOGIN_MSG_FAIL_TO_GET_SERVER_LIST ]
	= "Failed to Get Server List";

	s_strMessage[ LOGIN_MSG_LOADING_PATCHINFO_CACHE ]
	= "Reading Patch info cache";

	s_strMessage[ LOGIN_MSG_FAIL_TO_APPLY_PATCH ]
#ifdef _NATION_KR_
	= "패치에 실패했습니다.";
#else
	= "Failed to apply patch. Error occured during patch process.";
#endif

	s_strMessage[ LOGIN_MSG_FAIL_TO_GET_NOTICEINFO ]
#ifdef _NATION_KR_
	= "NoticeInfo.dat 파일을 전송받는데 실패했습니다.";
#else
	= "Failed to receive NoticeInfo.dat";
#endif

	s_strMessage[ LOGIN_MSG_FAIL_TO_FILE_CHECK ]
#ifdef _NATION_KR_
	= "파일 오류 검사에 실패했습니다.";
#else
	= "Error occured during file check.";
#endif

	s_strMessage[ LOGIN_MSG_FILE_CHECK_FINISHED ]
#ifdef _NATION_KR_
	= "파일 오류 검사가 완료되었습니다.";
#else
	= "File check completed successfully.";
#endif


	CString strMessageFilename;
	strMessageFilename.Format( "%s%s", szFolder, "\\Message.dat" );

	FILE *fp = fopen( strMessageFilename.GetBuffer( 0 ), "r" );

	char strBuffer[ 1024 ];

	if( fp )
	{
		for( int i=0; i < LOGIN_MSG_MAX_COUNT; i++ )
		{
			strBuffer[0] = '\0';
			fgets( strBuffer, 1024, fp );		
			s_strMessage[ i ] = strBuffer;
		}
	}
}

const CString &RYLLoginGetMessage(int nMessage)
{
	return s_strMessage[ nMessage ];
}

bool CRYLLoginDlg::ConnectToLoginServer()
{	    
    char szAddress[MAX_PATH];
    memset(szAddress, 0, sizeof(char) * MAX_PATH);

	if( m_strLoginServerAddrFromRegistry != "" )
	{
        strncpy(szAddress, m_strLoginServerAddrFromRegistry, MAX_PATH);        
	}
	else
	{
    #ifdef _INHOUSE_SERVER_
        strncpy(szAddress, "220.73.177.155", MAX_PATH);
    #else
	    IN_ADDR LoginAddress;
        if (GetHostIPByDomain(LoginAddress, m_strDefaultLoginServerAddr))
	    { strncpy(szAddress, inet_ntoa(LoginAddress), MAX_PATH); }
    #endif		
	}

    szAddress[MAX_PATH - 1] = 0;

    CLauncherEventHandler* lpHandler = new CLauncherEventHandler(*this);
	if (!m_pLoginSocket->ConnectToLoginServer(lpHandler, szAddress))
    {
        delete lpHandler;
        return false;
    }

    return true;
}

bool CRYLLoginDlg::RequestServerList()
{
    return (0 != m_pLoginSocket) 
        ? m_pLoginSocket->ServerList(GetLocalClientVersion()) : false;
}

bool CRYLLoginDlg::ProcessServerList(DWORD dwClientVersionFromServer, 
                                     const char* szPatchAddressFromLoginServer, const SERVER_LIST& serverList)
{
    m_ServerListData = serverList;
    m_bServerClosed  = (0 == m_ServerListData.m_ServerNum);  // 서버 수가 0개면 서버가 닫혀 있음

    m_strPatchUrlFromLoginServer.SetString(szPatchAddressFromLoginServer);

	// 서버 리스트 받기에 에러가 없으면..이하진행
	m_bCheckSucLoginData = TRUE;

	// 패치 받기 전 버전정보를 update manager에 세팅
    DWORD dwLocalClientVersion = GetLocalClientVersion();
	m_UpdateManager.SetVersion(dwLocalClientVersion);

	for(int nServer = 0; nServer < m_ServerListData.m_ServerNum; ++nServer)
	{
		m_ServerList.AddString(
            m_ServerListData.m_ServerGroup[nServer].m_Name);
	}	

	// 로컬 클라이언트 버전과 서버에서 얻은 버전을 비교
	if (dwLocalClientVersion < dwClientVersionFromServer)
	{
		// 로컬 클라이언트 버전이 낮을 경우 -> 패치 시작
		m_dwServerClientVersion = dwClientVersionFromServer;

        // 자동패치모드로 설정
        m_bFileCheck = false;
        unsigned int ThreadID = 0;
		DWORD dwThread = _beginthreadex( NULL, 0, UpdateProgress, this, 0, &ThreadID );
	}
	else									
	{
		// 패치 불필요 -> 애니메이션들 완료 상태
		m_ConnectionState = CS_SERVERSELECT;		
		InvalidateRect(CRect(12, 655, 381, 528), FALSE);	

		SetPatchComplete(true);
	}

    m_pLoginSocket->Disconnect();
    return true;
}

int CLauncherEventHandler::OnOpen(int iErrorCode)
{
	if( 0 != iErrorCode)
	{
		// 로그인 서버에 접속시도 실패. 재접속을 시도할지 물어봅니다.
		m_RylLoginDlg.SetLoginDisplayText("Connect to Login Server Failed");

		if( IDCANCEL ==
			AfxMessageBox( RYLLoginGetMessage(LOGIN_MSG_FAIL_TO_CONNECT_TO_LOGIN_SERVER), MB_OKCANCEL ) )
		{
			// edith
			// PostQuitMessage(0);
		}
        else
        {
            // TODO : 재접속 시도. 타이머 큐로 바꾸는 작업을 해야 함.
            m_RylLoginDlg.PutCommand(CDelayedConnectCmd::Create(m_RylLoginDlg, 5000));
        }
	}
	else
	{
        LoginSocket* lpLoginSocket = m_RylLoginDlg.GetLoginSocket();

        if(0 != lpLoginSocket)
        {
            lpLoginSocket->SetHandler(this);
        }

		m_RylLoginDlg.SetLoginDisplayText(
            RYLLoginGetMessage(LOGIN_MSG_CONNECTED_TO_LOGIN_SERVER_SUCCESSFULLY));

        // 서버리스트를 요청합니다.
		m_RylLoginDlg.RequestServerList();
	}

    return 0;
}

int CLauncherEventHandler::OnClose()
{
    // 연결이 끊겼을 때를 처리합니다.
    LoginSocket* lpLoginSocket = m_RylLoginDlg.GetLoginSocket();

    if(0 != lpLoginSocket)
    {
        lpLoginSocket->ResetHandler(this);
    }

    return 0;
}

int CLauncherEventHandler::OnDispatch(PktBase* lpPktBase, INET_Addr& peerAddr)
{
    if( lpPktBase->GetCmd() == 0x56 )
	{								
        char szPatchURLFromLoginServer[MAX_PATH];
        memset(szPatchURLFromLoginServer, 0, sizeof(char) * MAX_PATH);

        SERVER_LIST serverList;
        memset(&serverList, 0, sizeof(SERVER_LIST));

		DWORD dwClientVersionFromServer = 0;
        DWORD dwError = LoginSocket::HandleServerList(lpPktBase, 
            &dwClientVersionFromServer, szPatchURLFromLoginServer, &serverList);

		if (0 == dwError && 0 != dwClientVersionFromServer)
		{
            szPatchURLFromLoginServer[MAX_PATH - 1] = 0;

            m_RylLoginDlg.ProcessServerList(dwClientVersionFromServer, 
                szPatchURLFromLoginServer, serverList);        
        }
		else if (10 == dwError)
		{
			// edith
			// 서버가 닫혀있습니다.
//          AfxMessageBox( "Login Server is currently unavailable. \nPlease visit http://www.returnofwarrior.com for more information.");
//			PostQuitMessage(0);
			m_RylLoginDlg.SetLoginDisplayText(RYLLoginGetMessage(LOGIN_MSG_FAIL_TO_GET_SERVER_LIST));			
		}
		else
		{
			// 서버 리스트 받기 실패
			m_RylLoginDlg.SetLoginDisplayText(RYLLoginGetMessage(LOGIN_MSG_FAIL_TO_GET_SERVER_LIST));			
		}
	}

    return 0;
}


void CRYLLoginDlg::OnBnClickedButtonStart()
{
	if( m_ServerList.GetCurSel() == -1 )
	{
		AfxMessageBox( RYLLoginGetMessage( 0 ) );
		return;
	}

	// 패치 파일을 다운받고 있는지 확인
	if(GetPatchComplete())
	{
		ShowWindow( SW_HIDE );

		ExecuteClient( m_ServerList.GetCurSel() );
	}
}

void CRYLLoginDlg::OnLbnDblclkListServer()
{
	if( m_ServerList.GetCurSel() == -1 )
	{
		AfxMessageBox( RYLLoginGetMessage( 0 ) );
		return;
	}

	// 패치 파일을 다운받고 있는지 확인.
	if(GetPatchComplete())
	{
		ShowWindow( SW_HIDE );

		ExecuteClient( m_ServerList.GetCurSel() );
	}	
}


void CRYLLoginDlg::OnLbnSelchangeListServer()
{
	m_ServerList.Invalidate(FALSE);	

	m_ServerList.SetWindowPos( NULL, 510, 55, 135, 260, SWP_NOZORDER );		

	CRect rt;
	rt.left		= 510;
	rt.right	= 510+135;
	rt.top		= 55;
	rt.bottom	= 55+260;

	InvalidateRect(&rt, FALSE);	
}

HBRUSH CRYLLoginDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

	switch(nCtlColor)
	{
	case CTLCOLOR_LISTBOX:
		pDC->SetBkMode(TRANSPARENT);
		pDC->SetTextColor(RGB( 200,200,200 ));
		return (HBRUSH)GetStockObject(NULL_BRUSH);
		break;
	}
	
	return hbr;
}