
// RemoteView.cpp : 구현 파일입니다.
//

#include "stdafx.h"
#include "ConsoleApp.h"
#include "RemoteView.h"
#include "WaitMessageDlg.h"
#include "MainFrm.h"
#include "LocalView.h"


CString BYTE2KMBYTE(__int64 nBytes, int nFlag, bool bShowDecimalPoint);
CString NumericFormat(__int64 nNumeric);
CString GetValidFileName(LPCTSTR pszFileName);

typedef struct
{
	HCOMMLIB		hcl;
	CString			sPath;
	UINT			nFileCount;
	PCLFILE_STRUCT	pclf;
}THREAD_PARAM,*LPTHREAD_PARAM;

DWORD WINAPI GetFileListThread(LPVOID lpParam);

// CRemoteView

IMPLEMENT_DYNCREATE(CRemoteView, CFormView)

CRemoteView::CRemoteView()
	: CFormView(CRemoteView::IDD)
{
	m_bClosing = false;

	m_bDragSplitter = FALSE;
	m_cxSplitter    = COptions::GetOptionVal(OPTION_REMOTETREESIZE);

	m_nTotalCount    = 0;
	m_nTotalBytes    = 0;
	m_nTotalFiles    = 0;
	m_nSelectedCount = 0;
	m_nSelectedBytes = 0;
	m_nSelectedFiles = 0;

	m_bUpdating = FALSE;
	m_nTimer = 0;
}

CRemoteView::~CRemoteView()
{
	COptions::SetOption(OPTION_REMOTETREESIZE, m_cxSplitter);
}

BEGIN_MESSAGE_MAP(CRemoteView, CFormView)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
	ON_WM_TIMER()

	ON_BN_CLICKED(IDC_REMOTE_TITLE, OnRemoteTitle)
	ON_BN_CLICKED(IDC_REMOTE_BTN_UP_ADDR, OnRemoteBtnUpAddr)
	ON_BN_CLICKED(IDC_REMOTE_BTN_LISTSTYLE, OnRemoteBtnListStyle)
	ON_NOTIFY(TVN_SELCHANGED, IDC_REMOTE_TREE, OnTreeSelchanged)
	ON_NOTIFY(TVN_ITEMEXPANDING, IDC_REMOTE_TREE, OnTreeItemexpanding)
	ON_NOTIFY(TVN_ITEMEXPANDED, IDC_REMOTE_TREE, OnTreeItemexpanded)
	ON_NOTIFY(TVN_BEGINLABELEDIT, IDC_REMOTE_TREE, OnTreeBeginlabeledit)
	ON_NOTIFY(TVN_ENDLABELEDIT, IDC_REMOTE_TREE, OnTreeEndlabeledit)
	ON_NOTIFY(LVN_BEGINLABELEDIT, IDC_REMOTE_LIST, OnListBeginlabeledit)
	ON_NOTIFY(LVN_ENDLABELEDIT, IDC_REMOTE_LIST, OnListEndlabeledit)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_REMOTE_LIST, OnListItemChanged)
	ON_NOTIFY(NM_CLICK, IDC_REMOTE_LIST, OnListNMClick)

	ON_MESSAGE(WMU_SHOW_VOLUMELIST, OnShowVolumelist)
	ON_MESSAGE(WMU_EXPAND_FOLDERLIST, OnExpandFolderlist)
	ON_MESSAGE(WMU_SHOW_FOLDERLIST, OnShowFolderlist)
	ON_MESSAGE(WMU_SHOW_OBJECTLIST, OnShowObjectlist)
END_MESSAGE_MAP()


void CRemoteView::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_REMOTE_CBO_ADDR, m_cboAddr);
	DDX_Control(pDX, IDC_REMOTE_TREE, m_tree);
	DDX_Control(pDX, IDC_REMOTE_LIST, m_list);
}

void CRemoteView::OnInitialUpdate()
{
	static BOOL bInited = FALSE;

	CFormView::OnInitialUpdate();

	if (!bInited) {
		m_cboAddr.OnCreate(NULL);
		m_tree.OnCreate(NULL);
		m_list.OnCreate(NULL);
		bInited = TRUE;
	}

	ApplyListStyle();

	SetControlStatus(FALSE);
}

// CRemoteView 진단입니다.

#ifdef _DEBUG
void CRemoteView::AssertValid() const
{
	CFormView::AssertValid();
}

void CRemoteView::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}
#endif //_DEBUG


// CRemoteView 그리기

void CRemoteView::OnDraw(CDC* pDC)
{
	RECT   rc, rcClient;
	CBrush br;

	GetClientRect(&rcClient);

	///////////////////////////////////////////////////////////////////////////////
	// 3D 음영

	// 최상단
	br.CreateSysColorBrush(COLOR_BTNHIGHLIGHT);
	rc        = rcClient;
	rc.top    = 0;
	rc.bottom = HIGHLIGHT_SIZE;
	pDC->FillRect(&rc, &br);

	// 맨좌측
	rc       = rcClient;
	rc.left  = 0;
	rc.right = HIGHLIGHT_SIZE;
	pDC->FillRect(&rc, &br);
	br.DeleteObject();

	// 맨우측
	br.CreateSysColorBrush(COLOR_BTNSHADOW);
	rc      = rcClient;
	rc.left = rc.right - 1;
	pDC->FillRect(&rc, &br);
	br.DeleteObject();

	RedrawFocus();
}

/////////////////////////////////////////////////////////////////////////////
// CRemoteView 메시지 처리기입니다.

BOOL CRemoteView::PreTranslateMessage(MSG* pMsg)
{
	static int xOldSplitter = -77;

	int x, y;

	switch (pMsg->message) {
	case WM_MOUSEMOVE:
		x = LOWORD(pMsg->lParam);
		y = HIWORD(pMsg->lParam);

		if (m_bDragSplitter) {
			if (xOldSplitter != -77)
				InvertTracker(xOldSplitter);

			InvertTracker(xOldSplitter = x + 2);

			return TRUE;
		}
		else if (pMsg->hwnd == GetSafeHwnd()) {
			RECT rc;
			GetClientRect(&rc);

			rc.left    = m_cxSplitter;
			rc.right   = m_cxSplitter + SPLITTER_SIZE;
			rc.top     = CAPTION_HEIGHT;
			rc.bottom -= STATUS_HEIGHT;

			if (x >= rc.left && x <= rc.right && y >= rc.top && y <= rc.bottom)
				SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
		}

		break;
	case WM_LBUTTONDOWN:
		((CMainFrame *)AfxGetMainWnd())->SetFocus(this);

		x = LOWORD(pMsg->lParam);
		y = HIWORD(pMsg->lParam);

		if (pMsg->hwnd == m_hWnd) {
			RECT rc;
			GetClientRect(&rc);

			rc.left    = m_cxSplitter;
			rc.right   = m_cxSplitter + SPLITTER_SIZE;
			rc.top     = CAPTION_HEIGHT;
			rc.bottom -= STATUS_HEIGHT;

			if (x >= rc.left && x <= rc.right && y >= rc.top && y <= rc.bottom) {
				GetWindowRect(&rc);
				ClipCursor(&rc);

				SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
				SetCapture();

				m_bDragSplitter = TRUE;

				xOldSplitter = -77;

				return TRUE;
			}
		}
		break;
	case WM_LBUTTONUP:
		((CMainFrame *)AfxGetMainWnd())->SetFocus(this);

		if (m_bDragSplitter) {
			InvertTracker(xOldSplitter);

			ClipCursor(NULL);
			ReleaseCapture();
			SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));

			m_bDragSplitter = FALSE;

			RECT rc;
			GetClientRect(&rc);

			x = LOWORD(pMsg->lParam);
			if (x < MIN_TREE_WIDTH)
				x = MIN_TREE_WIDTH;
			else if (x > rc.right - MIN_LIST_WIDTH)
				x = rc.right - MIN_LIST_WIDTH;

			m_cxSplitter = x;
			RedrawControl(rc.right, rc.bottom);

			return TRUE;
		}
		break;
	case WM_RBUTTONDOWN:
		((CMainFrame *)AfxGetMainWnd())->SetFocus(this);
		break;
	}

	return CFormView::PreTranslateMessage(pMsg);
}

BOOL CRemoteView::PreCreateWindow(CREATESTRUCT& cs)
{
	cs.style     |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
	cs.dwExStyle |= WS_EX_STATICEDGE;

	return CFormView::PreCreateWindow(cs);
}

int CRemoteView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFormView::OnCreate(lpCreateStruct) == -1)
		return -1;

	CMainFrame *pmf = (CMainFrame *)AfxGetMainWnd();

	CString sCaption;

	// 트리 생성
	if (!m_capTitleIcon.Create("", WS_VISIBLE | BS_OWNERDRAW, CRect(4,4,20,20), this, 0)) {
		AfxMessageBox("IDC_REMOTE_TITLEICON 생성 실패.\n");
		return -1;
	}
	m_capTitleIcon.LoadBitmaps(IDB_CAP_REMOTE);

#ifdef _LGU
	// 2014.07.16
	// LG U+ 
	sCaption = "X-CDN";
#else // KTICS 
	sCaption = "ICS";
#endif // 

	if (!m_capTitle.Create(this, "     " + sCaption, CPWS_EX_CLOSEBUTTON, WS_VISIBLE, CRect(0, 0, 0, 0), IDC_REMOTE_TITLE)) {
		AfxMessageBox("IDC_REMOTE_TITLE 생성 실패.\n");
		return -1;
	}
	m_capTitle.SetFont(&pmf->m_font);
/*
	if (!m_tree.CreateEx(WS_EX_CLIENTEDGE, WS_VISIBLE | WS_CLIPCHILDREN | WS_CHILD | TVS_HASBUTTONS | TVS_HASLINES | TVS_SHOWSELALWAYS | TVS_EDITLABELS | TVS_TRACKSELECT, CRect(0,0,0,0), this, IDC_REMOTE_TREE)) {
		AfxMessageBox( "IDC_REMOTE_TREE 생성 실패.\n" );
		return -1;
	}
	m_tree.SetFont(&pmf->m_font);
*/
	// 리스트 생성
	sCaption = "위치";
	if (!m_capAddr.Create(sCaption, WS_VISIBLE | SS_CENTER | SS_CENTERIMAGE, CRect(0,0,0,0), this, IDC_REMOTE_STC_ADDR)) {
		AfxMessageBox("IDC_REMOTE_STC_ADDR 생성 실패.\n");
		return -1;
	}
	m_capAddr.SetFont(&pmf->m_font);
/*
	if (!m_cboAddr.Create(WS_VISIBLE | CBS_DROPDOWN, CRect(0,0,0,200), this, IDC_REMOTE_CBO_ADDR)) {
		AfxMessageBox("IDC_REMOTE_CBO_ADDR 생성 실패.\n");
		return -1;
	}
	m_cboAddr.SetFont(&pmf->m_font);
*/
	if (!m_btnGoAddr.Create("", WS_VISIBLE | BS_OWNERDRAW, CRect(0,0,0,0), this, IDC_REMOTE_BTN_GO_ADDR)) {
		AfxMessageBox("IDC_REMOTE_BTN_GO_ADDR 생성 실패.\n");
		return -1;
	}
	m_btnGoAddr.SetXButtonStyle(BS_XT_WINXP_COMPAT);
	m_btnGoAddr.SetBitmap(0, IDB_BTN_GO);

	if (!m_btnUpAddr.Create("", WS_VISIBLE | BS_OWNERDRAW, CRect(0,0,0,0), this, IDC_REMOTE_BTN_UP_ADDR)) {
		AfxMessageBox("IDC_REMOTE_BTN_UP_ADDR 생성 실패.\n");
		return -1;
	}
	m_btnUpAddr.SetXButtonStyle(BS_XT_WINXP_COMPAT);
	m_btnUpAddr.SetBitmap(0, IDB_BTN_UP);

	if (!m_btnListStyle.Create("", WS_VISIBLE | BS_OWNERDRAW, CRect(0,0,0,0), this, IDC_REMOTE_BTN_LISTSTYLE)) {
		AfxMessageBox("IDC_REMOTE_BTN_LISTSTYLE 생성 실패.\n");
		return -1;
	}
	m_btnListStyle.SetXButtonStyle(BS_XT_WINXP_COMPAT);
	m_btnListStyle.SetBitmap(0, IDB_BTN_LISTSTYLE);
/*
	if (!m_list.CreateEx(WS_EX_CLIENTEDGE, WS_VISIBLE | LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_SHOWSELALWAYS, CRect(0,0,0,0), this, IDC_REMOTE_LIST)) {
		AfxMessageBox("IDC_REMOTE_LIST 생성 실패.\n");
		return -1;
	}
	m_list.SetFont(&pmf->m_font);
*/
	if (!m_capStatus.Create(this, "", CPWS_EX_RAISED_EDGE, WS_VISIBLE, CRect(0, 0, 0, 0), 0)) {
		AfxMessageBox("IDC_LOCAL_TITLE 생성 실패.\n");
		return -1;
	}
	m_capStatus.SetFont(&pmf->m_font);

	if (!m_prgStatusSpace.Create(WS_VISIBLE, CRect(0, 0, 0, 0), this, 0)) {
		AfxMessageBox("IDC_LOCAL_STATUS_SPACE 생성 실패.\n");
		return -1;
	}
	m_prgStatusSpace.SetFont(&pmf->m_font);
	m_prgStatusSpace.SetRange(0, 100);
	m_prgStatusSpace.SetText(" ");
	m_prgStatusSpace.SetStep(1);
	m_prgStatusSpace.ShowWindow(SW_HIDE);

	if (!m_stcStatusSpace.Create("", WS_VISIBLE, CRect(0, 0, 0, 0), this)) {
		AfxMessageBox("IDC_LOCAL_STATUS_SPACE 생성 실패.\n");
		return -1;
	}
	m_stcStatusSpace.SetFont(&pmf->m_font);

	if (!m_stcStatusObject.Create("", WS_VISIBLE, CRect(0, 0, 0, 0), this)) {
		AfxMessageBox("IDC_LOCAL_STATUS_OBJECT 생성 실패.\n");
		return -1;
	}
	m_stcStatusObject.SetFont(&pmf->m_font);

	if (!m_stcStatusMsg.Create("", WS_VISIBLE, CRect(0, 0, 0, 0), this)) {
		AfxMessageBox("IDC_LOCAL_STATUS_MSG 생성 실패.\n");
		return -1;
	}
	m_stcStatusMsg.SetFont(&pmf->m_font);

	if (!m_stcSeparator1.Create("", WS_VISIBLE | WS_BORDER, CRect(0, 0, 1, STATUS_HEIGHT - 2), this)) {
		AfxMessageBox("IDC_LOCAL_STATUS_SEPARATOR 생성 실패.\n");
		return -1;
	}
	m_stcSeparator1.ModifyStyleEx(NULL, WS_EX_STATICEDGE);

	if (!m_stcSeparator2.Create("", WS_VISIBLE | WS_BORDER, CRect(0, 0, 1, STATUS_HEIGHT - 2), this)) {
		AfxMessageBox("IDC_LOCAL_STATUS_SEPARATOR 생성 실패.\n");
		return -1;
	}
	m_stcSeparator2.ModifyStyleEx(NULL, WS_EX_STATICEDGE);

	// 무인증 폴더 아이콘 설정
	SHFILEINFO shfi;
	HIMAGELIST hil = (HIMAGELIST)SHGetFileInfo("", 0, &shfi, sizeof(shfi), SHGFI_ICON | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
	m_pilSmall = CImageList::FromHandle(hil);

	hil = (HIMAGELIST)SHGetFileInfo("", 0, &shfi, sizeof(shfi), SHGFI_ICON | SHGFI_SYSICONINDEX | SHGFI_LARGEICON);
	m_pilLarge = CImageList::FromHandle(hil);

	// 반드시 bOpen == false 먼저 호출
	InsertAnonyFolderIcon(true, false);
	InsertAnonyFolderIcon(true, true);
	InsertAnonyFolderIcon(false, false);
	InsertAnonyFolderIcon(false, true);

	return 0;
}

void CRemoteView::OnDestroy()
{
	m_bClosing = true;

	m_tree.DeleteAllItems();
	m_list.DeleteAllItems();

	CFormView::OnDestroy();
}

void CRemoteView::OnSize(UINT nType, int cx, int cy)
{
	CFormView::OnSize(nType, cx, cy);

	int nTreeWidth = m_cxSplitter > 0 ? m_cxSplitter : 250;

	m_cxSplitter = nTreeWidth;

	RedrawControl(cx, cy);
}

BOOL CRemoteView::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}

void CRemoteView::OnRemoteTitle()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();
	ASSERT_VALID(pmf);

	pmf->OnViewRtree();

	RedrawControl();
}

void CRemoteView::OnRemoteBtnUpAddr()
{
	HTREEITEM hti = m_tree.GetSelectedItem();

	if (m_tree.GetRootItem() == hti)
		return;

	hti = m_tree.GetParentItem(hti);

	m_tree.SelectItem(hti);
}

void CRemoteView::OnRemoteBtnListStyle()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	pmf->m_nRemoteListType++;
	if (pmf->m_nRemoteListType == 5)
		pmf->m_nRemoteListType = 1;

	ApplyListStyle();
}

void CRemoteView::OnTreeSelchanged(NMHDR *pNMHDR, LRESULT *pResult)
{
	if (m_bClosing)
		return;

	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);

	AfxGetMainWnd()->PostMessage(WMU_UPDATE_CONTROL_STATUS);

	PRTREEITEM_STRUCT prti = (PRTREEITEM_STRUCT)m_tree.GetItemData(pNMTreeView->itemNew.hItem);
	ASSERT(prti);

	PostMessage(prti->nClass == TNS_ROOT ? WMU_SHOW_VOLUMELIST : WMU_SHOW_FOLDERLIST,
		(WPARAM)pNMTreeView->itemNew.hItem, (LPARAM)FALSE);

	*pResult = 0;
}

void CRemoteView::OnTreeItemexpanding(NMHDR *pNMHDR, LRESULT *pResult)
{
	if (m_bClosing)
		return;

	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
	if (pNMTreeView->action == TVE_COLLAPSE)
		return;

	PRTREEITEM_STRUCT prti = (PRTREEITEM_STRUCT)m_tree.GetItemData(pNMTreeView->itemNew.hItem);
	ASSERT(prti);

	if (prti->paObject.GetCount() == 0 && prti->nClass != TNS_ROOT)
		PostMessage(WMU_EXPAND_FOLDERLIST, (WPARAM)pNMTreeView->itemNew.hItem, (LPARAM)FALSE);

	*pResult = 0;
}

void CRemoteView::OnTreeItemexpanded(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);

	PRTREEITEM_STRUCT prti = (PRTREEITEM_STRUCT)m_tree.GetItemData(pNMTreeView->itemNew.hItem);
	ASSERT(prti);

	if (prti->nClass == TNS_FOLDER) {
		SHFILEINFO shfi;
		if (prti->saAttr[1] == "1") {
			shfi.iIcon = ((CMainFrame*)AfxGetMainWnd())->m_iAnonyAuthIcon;
			if (pNMTreeView->itemNew.state & TVIS_EXPANDED)
				shfi.iIcon++;
		}
		else
			SHGetFileInfo("", FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_SYSICONINDEX | (pNMTreeView->itemNew.state & TVIS_EXPANDED ? SHGFI_OPENICON : NULL));

		m_tree.SetItemImage(pNMTreeView->itemNew.hItem, shfi.iIcon, shfi.iIcon);
	}

	HTREEITEM hti = m_tree.GetChildItem(pNMTreeView->itemNew.hItem);
	if (hti && !m_tree.GetItemData(hti) && m_tree.GetItemText(hti) == "")
		m_tree.DeleteItem(hti);

	*pResult = 0;
}

void CRemoteView::OnTreeBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);

	PRTREEITEM_STRUCT prti = (PRTREEITEM_STRUCT)m_tree.GetItemData(pTVDispInfo->item.hItem);
	if (prti->nClass == TNS_ROOT || prti->nClass == TNS_VOLUME) {
		*pResult = -1;
		return;
	}

	m_sOldFileName = pTVDispInfo->item.pszText;

	*pResult = 0;
}

void CRemoteView::OnTreeEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);

	if (!pTVDispInfo->item.pszText)
		return;

	CString sNewFileName = GetValidFileName(pTVDispInfo->item.pszText);
	if (sNewFileName == "" || IsExistsFileName(m_tree.GetParentItem(pTVDispInfo->item.hItem), m_sOldFileName, sNewFileName)) {
		*pResult = FALSE;
		m_tree.SetFocus();
		m_tree.EditLabel(pTVDispInfo->item.hItem);
		return;
	}

	HTREEITEM hti = m_tree.GetParentItem(pTVDispInfo->item.hItem);
	CString sPath = m_tree.GetPath(hti);

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();
	if (!pmf->Move1RemoteObject(m_tree.GetVolumeItem(hti), sPath + "/" + m_sOldFileName, sPath + "/" + sNewFileName))
		return;

	strcpy(pTVDispInfo->item.pszText, sNewFileName);

	m_tree.SetItemText(pTVDispInfo->item.hItem, sNewFileName);
	m_tree.Sort(m_tree.GetParentItem(pTVDispInfo->item.hItem));

	pmf->PostMessage(WMU_UPDATE_CONTROL_STATUS);

	*pResult = TRUE;
}

void CRemoteView::OnListBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
{
	LV_DISPINFO* pLVDispInfo = (LV_DISPINFO*)pNMHDR;

	if (m_tree.GetRootItem() == m_tree.GetSelectedItem()) {
		*pResult = -1;
		return;
	}

	m_sOldFileName = m_list.GetItemText(pLVDispInfo->item.iItem, 0);

	*pResult = 0;
}

void CRemoteView::OnListEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
{
	LV_DISPINFO* pLVDispInfo = (LV_DISPINFO*)pNMHDR;

	if (!pLVDispInfo->item.pszText)
		return;

	CString sNewFileName = GetValidFileName(pLVDispInfo->item.pszText);
	if (sNewFileName == "" || IsExistsFileName(m_tree.GetSelectedItem(), m_sOldFileName, sNewFileName))
	{
		*pResult = -1;
		m_list.SetFocus();
		lstrcpy(pLVDispInfo->item.pszText,m_sOldFileName);
		m_list.EditLabel(pLVDispInfo->item.iItem);
		return;
	}

	HTREEITEM htiSelected = m_tree.GetSelectedItem();
	CString   sPath       = m_tree.GetPath(htiSelected);

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();
	if (!pmf->Move1RemoteObject(m_tree.GetVolumeItem(htiSelected), sPath + "/" + m_sOldFileName, sPath + "/" + sNewFileName))
		return;

	strcpy(pLVDispInfo->item.pszText, sNewFileName);

	m_list.SetItemText(pLVDispInfo->item.iItem, 0, sNewFileName);

	if (((PRLISTITEM_STRUCT)m_list.GetItemData(pLVDispInfo->item.iItem))->bFolder) {
		HTREEITEM hti = m_tree.GetChildItem(htiSelected);
		while (hti) {
			if (m_tree.GetItemText(hti) == m_sOldFileName) {
				m_tree.SetItemText(hti, sNewFileName);
				break;
			}
			hti = m_tree.GetNextSiblingItem(hti);
		}
		m_tree.Sort(htiSelected);
	}
	else
	{
		SHFILEINFO shfi;
		DWORD      dwAttr = FILE_ATTRIBUTE_NORMAL;

		if (!SHGetFileInfo(sNewFileName.Mid(sNewFileName.ReverseFind('.')), dwAttr, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME))
		{
			shfi.iIcon         = -1;
			shfi.szTypeName[0] = NULL;
		}

		m_list.SetItem(pLVDispInfo->item.iItem,0,LVIF_IMAGE,NULL,shfi.iIcon,LVIS_SELECTED ,LVIS_SELECTED,0);
	}

	m_list.Sort();

	pmf->PostMessage(WMU_UPDATE_CONTROL_STATUS);

	*pResult = 0;
}

void CRemoteView::OnListItemChanged(NMHDR *pNMHDR, LRESULT *pResult)
{
	if (m_bUpdating)
		return;

	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	if (!(pNMLV->uChanged & LVIS_DROPHILITED))
		return;

	if (pNMLV->uNewState & LVIS_SELECTED && !(pNMLV->uOldState & LVIS_SELECTED)) {
		m_nSelectedCount++;

		PRLISTITEM_STRUCT prli = (PRLISTITEM_STRUCT)m_list.GetItemData(pNMLV->iItem);
		if (!prli->bFolder) {
			m_nSelectedBytes += prli->nSize;
			m_nSelectedFiles++;
		}
	}
	else if (!(pNMLV->uNewState & LVIS_SELECTED) && pNMLV->uOldState & LVIS_SELECTED) {
		m_nSelectedCount--;

		PRLISTITEM_STRUCT prli = (PRLISTITEM_STRUCT)m_list.GetItemData(pNMLV->iItem);
		if (!prli->bFolder) {
			m_nSelectedBytes -= prli->nSize;
			m_nSelectedFiles--;
		}
	}

	if (m_nTimer != 0)
		KillTimer(m_nTimer);

	if (m_nSelectedCount > 0)
		m_nTimer = (UINT)SetTimer(TIMER_ID_UPDATESTATUS, 20, 0);
	else
		ShowStatusObject(FALSE, FALSE);

	*pResult = 0;
}

void CRemoteView::OnListNMClick(NMHDR *pNMHDR, LRESULT *pResult)
{
	((CMainFrame *)AfxGetMainWnd())->SetFocus(this);

	*pResult = 0;
}

void CRemoteView::OnTimer(UINT nIDEvent)
{
	KillTimer(m_nTimer);
	m_nTimer = 0;

	if (nIDEvent == TIMER_ID_UPDATESTATUS) {
		if (m_nSelectedFiles > 0)
			m_stcStatusObject.SetWindowText(NumericFormat(m_nSelectedCount) + " 개체가 선택됨, " + BYTE2KMBYTE(m_nSelectedBytes, 0, TRUE));
		else
			m_stcStatusObject.SetWindowText(NumericFormat(m_nSelectedCount) + " 개체가 선택됨");
		AfxGetMainWnd()->PostMessage(WMU_UPDATE_CONTROL_STATUS);
	}

	CFormView::OnTimer(nIDEvent);
}

LRESULT CRemoteView::OnShowVolumelist(WPARAM wParam, LPARAM lParam)
{
	if (m_bClosing)
		return S_OK;

	HTREEITEM htiRoot  = (HTREEITEM)wParam;
	BOOL      bRefresh = (BOOL)lParam;

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	if (!bRefresh && htiRoot) {
		PostMessage(WMU_SHOW_OBJECTLIST, (WPARAM)htiRoot);
		return S_OK;
	}

	pmf->BeginWaitMessage();

	HCOMMLIB hcl = pmf->m_mapHcl[NULL];
	ASSERT(hcl);

	UINT nServiceCount;
	OutputDebugString("XXX RemoteView : cl_get_service_list\n");

	PCLSERVICE_STRUCT pcls = cl_get_service_list(hcl, &nServiceCount);
	if (!pcls || nServiceCount == 0) {
		cl_free_service_list(hcl, pcls);

		pmf->EndWaitMessage();
		AfxMessageBox(cl_get_error_message(hcl), MB_ICONERROR);

		pmf->Disconnect();
		pmf->ShowLoginDialog();
		return S_FALSE;
	}

	m_tree.DeleteAllItems();

	PRTREEITEM_STRUCT prtiRoot = new RTREEITEM_STRUCT;
	prtiRoot->nClass  = TNS_ROOT;
	prtiRoot->bCached = true;
	prtiRoot->sName   = pmf->m_sUserId;

	htiRoot = m_tree.InsertItem(pmf->m_sUserId, pmf->m_iNetworkIcon, pmf->m_iNetworkIcon);
	m_tree.SetItemData(htiRoot, (DWORD_PTR)prtiRoot);

	for (UINT i = 0; i < nServiceCount; i++) {
		CString sName = (LPCSTR)pcls[i].id;
		HTREEITEM hti = m_tree.InsertItem(sName, pmf->m_iDriveIcon, pmf->m_iDriveIcon, htiRoot);

		PRTREEITEM_STRUCT prti = new RTREEITEM_STRUCT;
		prti->bCached = false;
		prti->nClass  = TNS_VOLUME;
		prti->sName   = sName;
		prti->saAttr.Add("");						// datetime
		prti->saAttr.Add((LPCSTR)pcls[i].domain2);	// url
		prti->saAttr.Add("");						// total bytes
		prti->saAttr.Add("");						// used bytes
		m_tree.SetItemData(hti, (DWORD_PTR)prti);

		m_tree.InsertItem("", -1, -1, hti);

		PRLISTITEM_STRUCT prli = new RLISTITEM_STRUCT;
		prli->bFolder = true;
		prli->sName   = sName;
		prli->nSize   = -1;
		prli->saAttr.Add(sName.MakeUpper());
		prli->saAttr.Add("");
		prli->saAttr.Add("서비스");
		prli->saAttr.Add("");

		prtiRoot->paObject.Add(prli);

		CString sURL = (LPCSTR)pcls[i].domain2;

		sURL += "/dav";
		CString sUserId = (LPCSTR)pcls[i].id;
		sUserId += "@" + pmf->m_sUserId;
		HCOMMLIB hcl = cl_init(sURL,pcls[i].domain,sUserId, pmf->m_sPassword, pmf->GetProxyHost(), pmf->GetProxyPort());
		ASSERT(hcl);
		pmf->m_mapHcl.SetAt(hti, hcl);
		
//		TRACE("%x : %s : %s\n",hcl,sURL,pcls[i].domain);

		pmf->UpdateVolumeInfo(hti);
	}
	cl_free_service_list(hcl, pcls);

	m_tree.SelectItem(htiRoot);
	m_tree.Expand(htiRoot, TVE_EXPAND);

	SetControlStatus(TRUE);
	m_cboAddr.Init();

	pmf->PostMessage(WMU_UPDATE_CONTROL_STATUS);
	pmf->EndWaitMessage();

	return S_OK;
}

LRESULT CRemoteView::OnExpandFolderlist(WPARAM wParam, LPARAM lParam)
{
	if (!RefreshObjectlist((HTREEITEM)wParam, (BOOL)lParam))
		return S_FALSE;

	return S_OK;
}

LRESULT CRemoteView::OnShowFolderlist(WPARAM wParam, LPARAM lParam)
{
	if (!RefreshObjectlist((HTREEITEM)wParam, (BOOL)lParam))
		return S_FALSE;

	PostMessage(WMU_SHOW_OBJECTLIST, wParam);

	return S_OK;
}

bool CRemoteView::RefreshObjectlist(HTREEITEM htiFolder, BOOL bRefresh)
{
	PRTREEITEM_STRUCT prtiX = (PRTREEITEM_STRUCT)m_tree.GetItemData(htiFolder);
	ASSERT(prtiX);

	if (m_bClosing)
		return S_OK;

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	HTREEITEM htiVolume = m_tree.GetVolumeItem(htiFolder);

	ASSERT(htiVolume);

	HCOMMLIB hcl = pmf->m_mapHcl[htiVolume];
	ASSERT(hcl);

	CString sPath = m_tree.GetPath(htiFolder);

	pmf->BeginWaitMessage();

	PRTREEITEM_STRUCT prtiFolder = (PRTREEITEM_STRUCT)m_tree.GetItemData(htiFolder);

	CWaitMessageDlg* pdlg;

	pdlg = new CWaitMessageDlg;
	pdlg->Create(IDD_WAITMESSAGE);
	pdlg->ShowWindow(TRUE);
	pdlg->CenterWindow();
	pdlg->SetForegroundWindow();
	pdlg->GetDlgItem(IDC_CANCEL_BTN)->ShowWindow(FALSE);
	pdlg->m_prg1.ShowWindow(FALSE);

	pdlg->m_stc1.SetWindowText("폴더 목록을 받아오는중...");

	THREAD_PARAM tp;

	tp.hcl = hcl;
	tp.sPath = sPath;

	HANDLE ht = ::CreateThread(NULL,0,GetFileListThread,(LPVOID)&tp,0,NULL);
	
	pdlg->m_nMode = 0;

	while(1)
	{
		MSG					msg;
			
		if(PeekMessage(&msg, NULL, 0, WM_PAINT, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		if (WaitForSingleObject(ht,1) == WAIT_OBJECT_0)
			break;
	}

	if (!tp.pclf || tp.nFileCount == 0) {
		cl_free_file_list(hcl, tp.pclf);
		pdlg->ShowWindow(FALSE);
		::DestroyWindow(pdlg->m_hWnd);
		delete pdlg;
		pmf->EndWaitMessage();
		CString strmsg = cl_get_error_message(hcl);
		if(!strmsg.IsEmpty())
			AfxMessageBox(strmsg, MB_ICONERROR);
		m_tree.SelectItem(m_tree.GetRootItem());
		return false;
	}

	prtiFolder->saAttr[0] = tp.pclf->lastModified;


	m_tree.DeleteChildItem(htiFolder);

	pdlg->m_prg1.ShowWindow(TRUE);

	pdlg->m_prg1.SetRange(0,tp.nFileCount);
	
	pdlg->m_nMode =1;

	pdlg->GetDlgItem(IDC_CANCEL_BTN)->ShowWindow(TRUE);

	for (UINT i = 1; i < tp.nFileCount; i++)
	{
		MSG					msg;
			
		if(PeekMessage(&msg, NULL, 0, WM_PAINT, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		if(PeekMessage(&msg, pdlg->m_hWnd, 0,0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);

			if(msg.message == WM_CANCEL_MAKETREE)
			{
				DWORD dwCode;
				GetExitCodeThread(ht,&dwCode);
				TerminateThread(ht,dwCode);
				break;
			}
		}

		CString strTemp;
		strTemp.Format("폴더트리 구성중:(%d/%d)",i,tp.nFileCount);
		pdlg->m_stc1.SetWindowText(strTemp);
		pdlg->m_prg1.SetPos(i);

		AppendObject(htiFolder, tp.pclf[i].attr & CLFILEATTR_FOLDER, tp.pclf[i].path, tp.pclf[i].size, tp.pclf[i].lastModified);
	}

	pdlg->ShowWindow(FALSE);
	::DestroyWindow(pdlg->m_hWnd);
	delete pdlg;

	cl_free_file_list(hcl, tp.pclf);

	prtiFolder->bCached = true;

	if (prtiFolder->nClass == TNS_VOLUME) {
		UINT nPathCount;
		PCLPATHINFO_STRUCT pclpi = cl_get_path_auth(hcl, m_tree.GetItemText(htiVolume), &nPathCount);
		if (!pclpi && cl_get_error_number(hcl) != CLERRNO_NOAVAILPATH_LIST) {
			AfxMessageBox(cl_get_error_message(hcl), MB_ICONERROR);
			m_tree.SelectItem(m_tree.GetRootItem());
			return false;
		}

		for (UINT i = 0; i < nPathCount; i++)
			SetAnonyFolder(htiVolume, pclpi[i].path, true);

		cl_free_path_auth(hcl, pclpi);
	}

	pmf->EndWaitMessage();

	return true;
}

LRESULT CRemoteView::OnShowObjectlist(WPARAM wParam, LPARAM lParam)
{
	if (m_bClosing)
		return S_OK;

	HTREEITEM         hti  = (HTREEITEM)wParam;
	PRTREEITEM_STRUCT prti = (PRTREEITEM_STRUCT)m_tree.GetItemData(hti);

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	pmf->BeginWaitMessage();

	m_list.DeleteAllItems();

	m_bUpdating = TRUE;
	m_list.SetRedraw(FALSE);

	m_nTotalCount = 0;
	m_nTotalBytes = 0;
	m_nTotalFiles = 0;

	CString sSize;

	m_cboAddr.Add(hti);
	switch (prti->nClass) {
	case TNS_ROOT:
		m_nTotalCount = (long)prti->paObject.GetCount();
		for (int i = 0; i < m_nTotalCount; i++) {
			PRLISTITEM_STRUCT prli = (PRLISTITEM_STRUCT)prti->paObject[i];

//			sSize.Format("%s 남음", BYTE2KMBYTE(prli->nSize - _atoi64(prli->saAttr[0]), 3, true));
			sSize.Format("전체 %s" , BYTE2KMBYTE(_atoi64(prli->saAttr[1]), 0, true));

			m_list.InsertItem(i, prli->sName, pmf->m_iDriveIcon);
			m_list.SetItemText(i, 1, sSize);
			m_list.SetItemText(i, 2, "서비스");
			m_list.SetItemText(i, 3, "");
			m_list.SetItemData(i, (DWORD_PTR)prli);
		}
		break;
	case TNS_VOLUME:
	case TNS_FOLDER:
		m_nTotalCount = (long)prti->paObject.GetCount();
		for (int i = 0; i < m_nTotalCount; i++) {
			PRLISTITEM_STRUCT prli = (PRLISTITEM_STRUCT)prti->paObject[i];

			if (prli->bFolder)
				sSize  = "";
			else {
				sSize  = BYTE2KMBYTE(prli->nSize, 1, false);

				m_nTotalBytes = prli->nSize;
				m_nTotalFiles++;
			}

			m_list.InsertItem(i, prli->sName, prli->iIcon);
			m_list.SetItemText(i, 1, sSize);
			m_list.SetItemText(i, 2, prli->saAttr[2]);
			m_list.SetItemText(i, 3, prli->saAttr[3]);
			m_list.SetItemData(i, (DWORD_PTR)prli);
/*
			MSG					msg;
			
			while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
*/
		}
		break;
	}

	m_list.Sort();
	if (m_list.GetItemCount() > 0)
		m_list.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);

	m_list.SetRedraw(TRUE);
	m_bUpdating = FALSE;

	ShowStatusSpace();
	ShowStatusObject(FALSE, FALSE);

	pmf->PostMessage(WMU_UPDATE_CONTROL_STATUS);
	pmf->EndWaitMessage();

	return S_OK;
}

void CRemoteView::RedrawFocus()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	if (!pmf->m_bShowRemoteTree)
		return;

	RECT rc;
	GetClientRect(&rc);

	CDC* pDC = GetDC();

	CBrush br;

	br.CreateSysColorBrush(COLOR_CAPTIONTEXT);
	rc.left   = m_cxSplitter;
	rc.right  = m_cxSplitter + SPLITTER_SIZE - 1;
	rc.top    = CAPTION_HEIGHT + 1;
	rc.bottom -= STATUS_HEIGHT;
	pDC->FillRect(&rc, &br);
	br.DeleteObject();

	br.CreateSysColorBrush(pmf->m_fl == FL_REMOTE ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
	rc.left  = m_cxSplitter + 1;
	rc.right = m_cxSplitter + SPLITTER_SIZE - 2;
	pDC->FillRect(&rc, &br);
	br.DeleteObject();

	ReleaseDC(pDC);
}

void CRemoteView::RedrawControl(int cx, int cy)
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	if (!pmf)
		return;

	int cxList;
	int cyStatusBar = pmf->m_bShowRemoteStatus ? STATUS_HEIGHT : 0;

	HDWP hdwp = BeginDeferWindowPos(13);
	if (hdwp) {
		if (pmf->m_bShowRemoteTree) {
			cxList = m_cxSplitter + SPLITTER_SIZE;
			DeferWindowPos(hdwp, m_capTitle.m_hWnd, HWND_TOP, 1, HIGHLIGHT_SIZE, m_cxSplitter + 1, CAPTION_HEIGHT, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_tree.m_hWnd, HWND_TOP, -1, HEADER_HEIGHT, m_cxSplitter + 1, cy - HEADER_HEIGHT - cyStatusBar, SWP_NOZORDER);
		}
		else {
			cxList = 0;
			DeferWindowPos(hdwp, m_capTitle.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_tree.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
		}
		DeferWindowPos(hdwp, m_capAddr.m_hWnd, HWND_TOP, cxList - 3, HIGHLIGHT_SIZE, ADDRESS_WIDTH + 3, CAPTION_HEIGHT, SWP_NOZORDER);
		DeferWindowPos(hdwp, m_cboAddr.m_hWnd, HWND_TOP, cxList + ADDRESS_WIDTH, HIGHLIGHT_SIZE, cx - (cxList + (ADDRESS_BTN_WIDTH << 1)) - ADDRESS_WIDTH - 1, 200, SWP_NOZORDER);
		DeferWindowPos(hdwp, m_btnUpAddr.m_hWnd, HWND_TOP, cx - (ADDRESS_BTN_WIDTH << 1) - 1, HIGHLIGHT_SIZE, ADDRESS_BTN_WIDTH, CAPTION_HEIGHT, SWP_NOZORDER);
		DeferWindowPos(hdwp, m_btnListStyle.m_hWnd, HWND_TOP, cx - ADDRESS_BTN_WIDTH - 1, HIGHLIGHT_SIZE, ADDRESS_BTN_WIDTH, CAPTION_HEIGHT, SWP_NOZORDER);
		DeferWindowPos(hdwp, m_list.m_hWnd, HWND_TOP, cxList - 1, HEADER_HEIGHT, cx - cxList + 1, cy - HEADER_HEIGHT - cyStatusBar, SWP_NOZORDER);
		DeferWindowPos(hdwp, m_capStatus.m_hWnd, HWND_TOP, 0, cy - cyStatusBar, cx, cyStatusBar, SWP_NOZORDER);
		if (pmf->m_bShowRemoteStatus) {
			int nTop = cy - cyStatusBar + 4;
			DeferWindowPos(hdwp, m_prgStatusSpace.m_hWnd, HWND_TOP, 1, nTop - 4, 77, cyStatusBar - 1, SWP_NOZORDER | SWP_FRAMECHANGED);
			DeferWindowPos(hdwp, m_stcStatusSpace.m_hWnd, HWND_TOP, 80, nTop, 170, STATUS_TEXT_HEIGHT, SWP_NOZORDER | SWP_FRAMECHANGED);
			DeferWindowPos(hdwp, m_stcStatusObject.m_hWnd, HWND_TOP, 255, nTop, 170, STATUS_TEXT_HEIGHT, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_stcStatusMsg.m_hWnd, HWND_TOP, 430, nTop, cx - 435, STATUS_TEXT_HEIGHT, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_stcSeparator1.m_hWnd, HWND_TOP, 253, nTop - 3, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
			DeferWindowPos(hdwp, m_stcSeparator2.m_hWnd, HWND_TOP, 428, nTop - 3, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
		}
		else {
			DeferWindowPos(hdwp, m_prgStatusSpace.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_stcStatusSpace.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_stcStatusObject.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_stcStatusMsg.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_stcSeparator1.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
			DeferWindowPos(hdwp, m_stcSeparator2.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
		}
		EndDeferWindowPos(hdwp);
	}

	RedrawFocus();
}

void CRemoteView::RedrawControl()
{
	RECT rc;
	GetClientRect(&rc);

	RedrawControl(rc.right, rc.bottom);
}

void CRemoteView::ApplyListStyle()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	ASSERT(pmf);

	m_list.SetListStyle(pmf->m_nRemoteListType);
}

void CRemoteView::MakeNewFolder()
{
	HTREEITEM htiSelected = m_tree.GetSelectedItem();
	if (!htiSelected)
		return;

	PRTREEITEM_STRUCT prti = (PRTREEITEM_STRUCT)m_tree.GetItemData(htiSelected);
	if (!prti || prti->nClass == TNS_ROOT)
		return;

	CString sFolderName = "NewFolder";
	int     iFolder     = 2;

	BOOL bFoundFolder = TRUE;
	while (bFoundFolder) {
		bFoundFolder = FALSE;

		HTREEITEM hti = m_tree.GetChildItem(htiSelected);
		while (hti) {
			if (sFolderName == m_tree.GetItemText(hti)) {
				bFoundFolder = TRUE;
				break;
			}

			hti = m_tree.GetNextSiblingItem(hti);
		}

		if (bFoundFolder)
			sFolderName.Format("NewFolder(%d)", iFolder++);
	}

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	CString sPath = m_tree.GetPath(htiSelected) + "/" + sFolderName;
	if (!pmf->MakeRemoteFolder(m_tree.GetVolumeItem(htiSelected), sPath))
		return;

	CTime time(CTime::GetCurrentTime());
	CString sTime = time.Format("%Y-%m-%d %p %I:%M:%S");
	sTime.Replace("AM", "오전");
	sTime.Replace("PM", "오후");

	AppendObject(htiSelected, true, sPath, 0, sTime);
	SendMessage(WMU_SHOW_OBJECTLIST, (WPARAM)htiSelected);

	for (int i = 0; i < m_list.GetItemCount(); i++) {
		if (m_list.GetItemText(i, 0) != sFolderName)
			continue;

		m_list.SetItemState(i, LVIS_FOCUSED, LVIF_TEXT);
		m_list.EditLabel(i);
	}
}

void CRemoteView::AppendObject(HTREEITEM htiParent, bool bFolder, LPCTSTR pszPath, __int64 nSize, LPCTSTR pszLastModified)
{
	CString sName = pszPath;
	sName = sName.Mid(sName.ReverseFind('/') + 1);

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

    SHFILEINFO shfi;
	DWORD      dwAttr;
	CString    sSize;

	if (bFolder) {
		HTREEITEM hti = m_tree.InsertItem(sName, pmf->m_iFolderIcon, pmf->m_iFolderIcon, htiParent);

		PRTREEITEM_STRUCT prti = new RTREEITEM_STRUCT;
		prti->bCached = false;
		prti->nClass  = TNS_FOLDER;
		prti->sName   = sName;
		prti->saAttr.Add(pszLastModified);
		prti->saAttr.Add("");
		m_tree.SetItemData(hti, (DWORD_PTR)prti);

		m_tree.InsertItem("", -1, -1, hti);

		dwAttr = FILE_ATTRIBUTE_DIRECTORY;
		sSize  = "";
	}
	else {
		dwAttr = FILE_ATTRIBUTE_NORMAL;
		sSize.Format("%15I64d", nSize);
	}

	if (!SHGetFileInfo(sName.Mid(sName.ReverseFind('.')), dwAttr, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME)) {
		shfi.iIcon         = -1;
		shfi.szTypeName[0] = NULL;
	}

	PRLISTITEM_STRUCT prli = new RLISTITEM_STRUCT;
	prli->iIcon   = shfi.iIcon;
	prli->bFolder = bFolder;
	prli->sName   = sName;
	prli->nSize   = nSize;
	prli->saAttr.Add(sName.MakeUpper());
	prli->saAttr.Add(sSize);
	prli->saAttr.Add(shfi.szTypeName);
	prli->saAttr.Add(pszLastModified);

	((PRTREEITEM_STRUCT)m_tree.GetItemData(htiParent))->paObject.Add(prli);
}

bool CRemoteView::IsExistsFileName(HTREEITEM htiParent, LPCTSTR pszOldFileName, LPCTSTR pszNewFileName)
{
	CString sOldFileName = pszOldFileName;
	CString sNewFileName = pszNewFileName;

//	sOldFileName.MakeLower();
//	sNewFileName.MakeLower();

	if (sOldFileName == sNewFileName)
		return false;

	PRTREEITEM_STRUCT prti = (PRTREEITEM_STRUCT)m_tree.GetItemData(htiParent);
	for (int i = 0; i < prti->paObject.GetCount(); i++) {
		PRLISTITEM_STRUCT prli = (PRLISTITEM_STRUCT)prti->paObject[i];
		CString sName = prli->sName;
//		sName.MakeLower();

		if (sName == sOldFileName)
			continue;

		if (sName == sNewFileName) {
			AfxMessageBox("이미 존재하는 파일 이름입니다. 다름 이름을 입력 하십시오.", MB_ICONEXCLAMATION);
			return true;
		}
	}

	return false;
}

void CRemoteView::DeleteTreeItem(HTREEITEM htiDelete)
{
	if (htiDelete == m_tree.GetRootItem() || ((PRTREEITEM_STRUCT)m_tree.GetItemData(htiDelete))->nClass != TNS_FOLDER)
		return;

	if (AfxMessageBox("선택된 폴더를 삭제하시겠습니까?", MB_YESNO) != IDYES)
		return;

	HTREEITEM htiVolume = m_tree.GetVolumeItem(htiDelete);
	CString sPath = m_tree.GetPath(htiDelete);
	CString sText = m_tree.GetItemText(htiDelete);

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	pmf->BeginWaitMessage();

	if (!pmf->Delete1RemoteObject(htiVolume, sPath)) {
		pmf->EndWaitMessage();
		return;
	}

	m_tree.DeleteChildItem(htiDelete);

	if (m_tree.GetSelectedItem() == m_tree.GetParentItem(htiDelete)) {
		for (int i = 0; i < m_list.GetItemCount(); i++) {
			if (m_list.GetItemText(i, 0) == sText) {
				m_list.DeleteItem(i);
				break;
			}
		}
	}

	m_tree.DeleteItem(htiDelete);

	m_tree.SetFocus();

	pmf->PostMessage(WMU_UPDATE_CONTROL_STATUS);
	pmf->EndWaitMessage();
}

void CRemoteView::DeleteListItem()
{
	POSITION pos = m_list.GetFirstSelectedItemPosition();
	if (!pos)
		return;

	if (AfxMessageBox("선택된 파일을 삭제하시겠습니까?", MB_YESNO) != IDYES)
		return;

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	pmf->BeginWaitMessage();

	m_bUpdating = TRUE;

	CDWordArray m_anSelectedItems;

	HTREEITEM htiSelected = m_tree.GetSelectedItem();
	CString   sPath       = m_tree.GetPath(htiSelected);

	CStringArray saFile;
	while (pos) {
		int iItem = m_list.GetNextSelectedItem(pos);

		saFile.Add(sPath + "/" + m_list.GetItemText(iItem, 0));
	}

	CStringArray saSucceed;
	pmf->DeleteRemoteObject(m_tree.GetVolumeItem(htiSelected), saFile, saSucceed);

	m_bUpdating = FALSE;

	pmf->EndWaitMessage();

	if (saSucceed.GetCount() == 0)
		return;

	RefreshItem();
}

void CRemoteView::RefreshItem()
{
	HTREEITEM htiSelected = m_tree.GetSelectedItem();
	if (!htiSelected)
		return;

	PRTREEITEM_STRUCT prti = (PRTREEITEM_STRUCT)m_tree.GetItemData(htiSelected);
	ASSERT(prti);

	PostMessage(prti->nClass == TNS_ROOT ? WMU_SHOW_VOLUMELIST : WMU_SHOW_FOLDERLIST,
		(WPARAM)htiSelected, (LPARAM)TRUE);
}

void CRemoteView::SetControlStatus(BOOL bConnected)
{
	m_cboAddr.EnableWindow(bConnected);
	m_btnUpAddr.EnableWindow(bConnected);
}

void CRemoteView::ShowStatusSpace()
{
	if (m_bUpdating)
		return;

	HTREEITEM hti = m_tree.GetSelectedItem();
	if (!hti)
		return;

	PRTREEITEM_STRUCT prti = (PRTREEITEM_STRUCT)m_tree.GetItemData(hti);
	if (prti->nClass == TNS_ROOT) {
		m_stcStatusSpace.SetWindowText("");
		m_prgStatusSpace.ShowWindow(SW_HIDE);
	}
	else {
		prti = (PRTREEITEM_STRUCT)m_tree.GetItemData(m_tree.GetVolumeItem(hti));

		__int64 nTotalBytes = _atoi64(prti->saAttr[2]);
		__int64 nUsedBytes  = _atoi64(prti->saAttr[3]);
		if (nTotalBytes > 0) {
			CString sText = " 서비스 여유 공간: ";
			sText += BYTE2KMBYTE(nTotalBytes - nUsedBytes, 0, TRUE);
			m_stcStatusSpace.SetWindowText(sText);

			double fPercent = 100.0 - ((nUsedBytes * 100.0) / nTotalBytes);
			sText.Format("%d.%02d%% 남음", (int)fPercent, (int)fPercent%100);
			m_prgStatusSpace.SetPos(100 - (int)fPercent, sText);
			m_prgStatusSpace.ShowWindow(SW_SHOW);
		}
		else {
			m_stcStatusSpace.SetWindowText("알수없음");
			m_prgStatusSpace.SetPos(0, "N/A");
			m_prgStatusSpace.ShowWindow(SW_SHOW);
		}
	}
}

void CRemoteView::ShowStatusObject(BOOL bSelected, BOOL bUpdate, BOOL bAllSelected)
{
	if (!bSelected) {
		m_nSelectedCount = 0;
		m_nSelectedBytes = 0;
		m_nSelectedFiles = 0;

		if (bUpdate) {
			m_nTotalCount = m_list.GetItemCount();
			m_nTotalBytes = 0;
			m_nTotalFiles = 0;

			for (int i = 0; i < m_nTotalCount; i++) {
				PRLISTITEM_STRUCT prli = (PRLISTITEM_STRUCT)m_list.GetItemData(i);
				if (!prli->bFolder) {
					m_nTotalBytes += prli->nSize;
					m_nTotalFiles++;
				}
			}
		}

SHOW_TOTALOBJECTSTATUS:
		if (m_nTotalFiles > 0)
			m_stcStatusObject.SetWindowText(NumericFormat(m_nTotalCount) + " 개체, " + BYTE2KMBYTE(m_nTotalBytes, 0, TRUE));
		else
			m_stcStatusObject.SetWindowText(NumericFormat(m_nTotalCount) + " 개체");
	}
	else {
		if (!bAllSelected && bUpdate) {
			m_nSelectedCount = 0;
			m_nSelectedBytes = 0;
			m_nSelectedFiles = 0;

			POSITION pos = m_list.GetFirstSelectedItemPosition();
			while (pos) {
				int iItem = m_list.GetNextSelectedItem(pos);

				m_nSelectedCount++;

				PRLISTITEM_STRUCT pobj = (PRLISTITEM_STRUCT)m_list.GetItemData(iItem);
				if (!pobj->bFolder) {
					m_nSelectedBytes += pobj->nSize;
					m_nSelectedFiles++;
				}
			}
		}

		if (bAllSelected) {
			m_nSelectedCount = m_nTotalCount;
			m_nSelectedBytes = m_nTotalBytes;
			m_nSelectedFiles = m_nTotalFiles;
		}

		if (m_nSelectedCount == 0)
			goto SHOW_TOTALOBJECTSTATUS;

		if (m_nSelectedFiles > 0)
			m_stcStatusObject.SetWindowText(NumericFormat(m_nSelectedCount) + " 개체가 선택됨, " + BYTE2KMBYTE(m_nSelectedBytes, 0, TRUE));
		else
			m_stcStatusObject.SetWindowText(NumericFormat(m_nSelectedCount) + " 개체가 선택됨");
	}

	AfxGetMainWnd()->PostMessage(WMU_UPDATE_CONTROL_STATUS);
}

BOOL CRemoteView::GetSelectedObject(CStringArray& saObject)
{
	CMainFrame *pmf = (CMainFrame *)AfxGetMainWnd();

	BOOL bFoundVolume = FALSE;

	if (pmf->m_pwndRemote == &m_list) {
		CString sPath = m_tree.GetPath();

		POSITION pos = m_list.GetFirstSelectedItemPosition();

		while (pos) {
			int iItem = m_list.GetNextSelectedItem(pos);

			CString sItem = sPath + "/" + m_list.GetItemText(iItem, 0);

			saObject.Add(sItem);
		}
	}
	else {
		if (m_tree.GetSelectedItem() == m_tree.GetRootItem())
			bFoundVolume = TRUE;
		else
			saObject.Add(m_tree.GetPath());
	}

	if (bFoundVolume)
		AfxMessageBox("서비스는 다운로드 할 수 없습니다.", MB_ICONEXCLAMATION);

	return saObject.GetCount() > 0 ? TRUE : FALSE;
}

void CRemoteView::SetAnonyFolder(HTREEITEM htiVolume, LPCTSTR pszFolder, bool bSet, bool bRefresh)
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	HTREEITEM hti = m_tree.GetChildItem(htiVolume);
	while (hti) {
		if (((PRTREEITEM_STRUCT)m_tree.GetItemData(hti))->sName == pszFolder) {
			if (bSet) {
				int iIcon = pmf->m_iAnonyAuthIcon;// + (m_tree.GetItemState(hti, TVIS_EXPANDED) ? 1 : 0);
				m_tree.SetItemImage(hti, iIcon, iIcon);
				((PRTREEITEM_STRUCT)m_tree.GetItemData(hti))->saAttr.SetAt(1, "1");
			}
			else {
				int iIcon = pmf->m_iFolderIcon;// + (m_tree.GetItemState(hti, TVIS_EXPANDED) ? 1 : 0);
				m_tree.SetItemImage(hti, iIcon, iIcon);
				((PRTREEITEM_STRUCT)m_tree.GetItemData(hti))->saAttr.SetAt(1, "");
			}
			break;
		}

		hti = m_tree.GetNextSiblingItem(hti);
	}

	PRTREEITEM_STRUCT prti = (PRTREEITEM_STRUCT)m_tree.GetItemData(htiVolume);
	for (int i = 0; i < prti->paObject.GetCount(); i++) {
		if (((PRLISTITEM_STRUCT)prti->paObject[i])->sName == pszFolder) {
			if (bSet) {
				((PRLISTITEM_STRUCT)prti->paObject[i])->iIcon = pmf->m_iAnonyAuthIcon;
			}
			else {
				((PRLISTITEM_STRUCT)prti->paObject[i])->iIcon = pmf->m_iFolderIcon;
			}
			break;
		}
	}
	
	if (bRefresh && m_tree.GetSelectedItem() == htiVolume)
		PostMessage(WMU_SHOW_OBJECTLIST, (WPARAM)htiVolume);
}

void CRemoteView::ClearAllData()
{
	m_bClosing = true;
	
	OutputDebugString(_T("Clear Addr Combo"));
	// dadamin add
	for(int i = m_cboAddr.GetCount() -1; i >= 0; --i)
	{
		m_cboAddr.DeleteItem(i);
	}
	// dadamin add
	m_cboAddr.Clear();
	
	OutputDebugString(_T("Clear Tree"));
	m_tree.DeleteAllItems();
	
	OutputDebugString(_T("Clear List"));
	m_list.DeleteAllItems();
	
	OutputDebugString(_T("Clear End"));
	SetControlStatus(FALSE);

	m_bClosing = false;
}

void CRemoteView::InvertTracker(int x)
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	CRect rc;
	GetWindowRect(&rc);
	pmf->ScreenToClient(&rc);

	rc.top    += (CAPTION_HEIGHT + 1);
	rc.bottom -= STATUS_HEIGHT;

	CDC* pDC = pmf->GetDC();

	CBrush* pBrush    = CBrush::FromHandle((HBRUSH)::GetStockObject(WHITE_BRUSH));
	HBRUSH  hOldBrush = NULL;

	if (pBrush != NULL)
		hOldBrush = (HBRUSH)SelectObject(pDC->m_hDC, pBrush->m_hObject);

	pDC->PatBlt(x, rc.top, SPLITTER_SIZE - 1, rc.Height(), PATINVERT);

	if (hOldBrush != NULL)
		SelectObject(pDC->m_hDC, hOldBrush);

	ReleaseDC(pDC);
}

void CRemoteView::InsertAnonyFolderIcon(bool bLarge, bool bOpen)
{
	SHFILEINFO shfi;
	SHGetFileInfo("", FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_ICON | (bLarge ? SHGFI_LARGEICON : SHGFI_SMALLICON) | (bOpen ? SHGFI_OPENICON : 0));
	HICON hicon = ::LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ANONY_FOLDER));

	HBRUSH hbBkgnd = ::CreateSolidBrush(RGB(255, 255, 255));

	RECT rc;
	rc.left   = rc.top = 0;
	rc.right  = bLarge ? 32 : 16;
	rc.bottom = bLarge ? 32 : 16;

	CImageList* pil = bLarge ? m_pilLarge : m_pilSmall;

	int iIcon = pil->GetImageCount();
	pil->SetImageCount(iIcon + 1);

	CClientDC cdc(this);
	HDC     hdc    = ::CreateCompatibleDC(cdc.m_hDC);
	HBITMAP hbm    = CreateCompatibleBitmap(cdc.m_hDC, rc.right, rc.bottom);
	HBITMAP hbmOld = (HBITMAP)SelectObject(hdc, hbm);

	::FillRect(hdc, &rc, hbBkgnd);

	DrawIconEx(hdc, 0, 0, shfi.hIcon, rc.right, rc.bottom, 0, NULL, DI_NORMAL | DI_COMPAT);
	DrawIconEx(hdc, 0, 0, hicon, rc.right, rc.bottom, 0, NULL, DI_NORMAL | DI_COMPAT);

	DestroyIcon(shfi.hIcon);

	SelectObject(hdc, hbmOld);

	// Attach to Bitmap and Replace image in CImageList
	CBitmap bm;
	bm.Attach(hbm);
	pil->Replace(iIcon, &bm, NULL);
	if (!bOpen)
		((CMainFrame*)AfxGetMainWnd())->m_iAnonyAuthIcon = iIcon;

	DeleteDC(hdc);
	DeleteObject(hbm);

	DeleteObject(hbBkgnd);
}

DWORD WINAPI GetFileListThread(LPVOID lpParam)
{
	LPTHREAD_PARAM ptp = (LPTHREAD_PARAM)lpParam;
	
	DWORD	dwRet;

	ptp->pclf = cl_get_file_list(ptp->hcl, ptp->sPath, 1, &ptp->nFileCount);


	if(ptp->pclf)
		dwRet = ERROR_SUCCESS;
	else
		dwRet = -1;

	return dwRet;
}
