// LocalListCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "ConsoleApp.h"
#include "LocalListCtrl.h"

#include "MainFrm.h"
#include "LocalView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

BOOL DeleteDirectory(CString sDirectory);

/////////////////////////////////////////////////////////////////////////////
// CLocalListCtrl

CLocalListCtrl::CLocalListCtrl()
{
}

CLocalListCtrl::~CLocalListCtrl()
{
}

#ifdef _USE_XTREME_TOOLKITPRO
BEGIN_MESSAGE_MAP(CLocalListCtrl, CXTShellListCtrl)
#else // _USE_XTREME_TOOLKITPRO
BEGIN_MESSAGE_MAP(CLocalListCtrl, CListCtrl)
#endif // _USE_XTREME_TOOLKITPRO
	//{{AFX_MSG_MAP(CLocalListCtrl)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CLocalListCtrl message handlers

BOOL CLocalListCtrl::PreTranslateMessage(MSG* pMsg)
{
	CMainFrame *pmf = (CMainFrame *)AfxGetMainWnd();

	switch (pMsg->message)
	{
	case WM_SETFOCUS:
	case WM_LBUTTONDOWN:
	case WM_RBUTTONDOWN:
		pmf->SetFocus(this);
		break;
	case WM_KEYDOWN:
		if (GetKeyState(VK_CONTROL) & 128) {
			if (pMsg->wParam == VK_D) {
				DeleteSelectedItem();
				return TRUE;
			}
			else if (pMsg->wParam == VK_V) {
				if (PasteClipboard())
					return TRUE;
			}
		}
		break;
	}

	return CListCtrl::PreTranslateMessage(pMsg);
}

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

#ifndef _USE_XTREME_TOOLKITPRO
	IPTxShListItems *pitems = (IPTxShListItems *)get_Items();

	long nTotalCount;

	pitems->get_Count(&nTotalCount);

	VARIANT_BOOL bFileSystem;

	IPTxShTreeNode *pnode = (IPTxShTreeNode*)((CLocalView*)GetParent())->m_tree.get_SelectedNode();
	pnode->get_IsFileSystem(&bFileSystem);
	if (bFileSystem) {
		IPTxShListItem *pitem;
		for (int i = 0; i < nTotalCount; i++) {
			pitems->get_Item(i, &pitem);

			VARIANT_BOOL bSelected;
			pitem->get_Selected(&bSelected);
			if (!bSelected)
				continue;

			BSTR bstr;
			pitem->get_PathName(&bstr);
			CString sPath(bstr);
			::SysFreeString(bstr);

			if (sPath == "")
				continue;

			DWORD dwAttr = GetFileAttributes(sPath);
			if (dwAttr == INVALID_FILE_ATTRIBUTES)
				continue;

			if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
				DeleteDirectory(sPath);
			else
				DeleteFile(sPath);
		}

		Refresh();
	}
#endif // !_USE_XTREME_TOOLKITPRO
}

BOOL CLocalListCtrl::PasteClipboard(CString sFolder)
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	CLocalTreeCtrl* ptree = &((CLocalView*)GetParent())->m_tree;

#ifndef _USE_XTREME_TOOLKITPRO
	VARIANT_BOOL bFileSystem;

	IPTxShTreeNode *pnode = (IPTxShTreeNode*)ptree->get_SelectedNode();
	pnode->get_IsFileSystem(&bFileSystem);
	if (!bFileSystem)
		return FALSE;

	BSTR bstr;
	pnode->get_PathName(&bstr);
	CString sPath(bstr);
	::SysFreeString(bstr);

	COleDataObject odo;

	if (odo.AttachClipboard() && odo.IsDataAvailable(CF_HDROP))
		return ((CLocalView*)GetParent())->CopyClipboard(odo, sPath);

	if (pmf->m_cbs == CBS_NONE)
		return FALSE;

	if (pmf->m_saDragSource.GetCount() == 0)
		return FALSE;

	pmf->m_sDragTarget = sFolder == "" ? sPath : sFolder;
#endif // _USE_XTREME_TOOLKITPRO
	return pmf->Download(false);
}

#ifdef _USE_XTREME_TOOLKITPRO
#define ISZIPFILE(dw) (BOOL)(dw & SFGAO_FOLDER) && (dw & SFGAO_STREAM)

BOOL CLocalListCtrl::InitListViewItems(XT_TVITEMDATA* lptvid, LPSHELLFOLDER lpsf)
{
	CShellMalloc lpMalloc;

	if (!lpMalloc)
		return FALSE;

	LPENUMIDLIST lpe = NULL;

	if (FAILED(lpsf->EnumObjects(::GetParent(m_pListCtrl->m_hWnd), m_uFlags, &lpe)))
		return FALSE;

	if (lpe == NULL)
		return FALSE;

	int          iCtr = 0;
	ULONG        ulFetched = 0;
	LPITEMIDLIST lpi = NULL;

	while (lpe->Next(1, &lpi, &ulFetched) == S_OK)
	{
		// Now get the friendly name that we'll put in the treeview...
		CString szFileName, szFullFilePath;
		GetName(lpsf, lpi, SHGDN_NORMAL, szFileName);
		GetName(lpsf, lpi, SHGDN_FORPARSING, szFullFilePath);

		// Note that since we are interested in the display attributes as well as
		// the other attributes, we need to set ulAttrs to SFGAO_DISPLAYATTRMASK
		// before calling GetAttributesOf();
		ULONG ulAttrs = SFGAO_FOLDER | SFGAO_STREAM | SFGAO_FILESYSANCESTOR | SFGAO_DISPLAYATTRMASK | SFGAO_REMOVABLE | SFGAO_COMPRESSED | SFGAO_ENCRYPTED;
		UINT  uFlags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON;
		lpsf->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lpi, &ulAttrs);

		BOOL bIncludeFile = !IsItemFiltered(szFullFilePath, ulAttrs);

		if (bIncludeFile)
		{
			// allocate memory for ITEMDATA struct
			XT_LVITEMDATA* lplvid = (XT_LVITEMDATA*)lpMalloc.Alloc(sizeof(XT_LVITEMDATA));
			if (lplvid == NULL)
			{
				if (lpe)
				{
					lpe->Release();
				}

				return FALSE;
			}

			lplvid->ulAttribs = ulAttrs;
			LPITEMIDLIST lpifqThisItem = ConcatPidls(lpMalloc, lptvid->lpifq, lpi);

			LV_ITEM lvi;
			lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
			lvi.iItem = iCtr++;
			lvi.iSubItem = 0;
			lvi.pszText = (LPTSTR)(LPCTSTR)szFileName;
			lvi.cchTextMax = 0;
			lvi.iImage = GetItemIcon(lpifqThisItem, uFlags);

			lplvid->lpsfParent = lpsf;
			lpsf->AddRef();

			// Make a copy of the ITEMIDLIST
			lplvid->lpi = DuplicateItem(lpMalloc, lpi);
			lvi.lParam = (LPARAM)lplvid;

			// Add the item to the listview
			int iIndex = m_pListCtrl->InsertItem(&lvi);
			SetAttributes(iIndex, ulAttrs);
			if (iIndex >= 0)
			{
				TCHAR szItemPath[_MAX_PATH];
				::SHGetPathFromIDList(lpifqThisItem, szItemPath);

				//if (((ulAttrs & SFGAO_FILESYSTEM) == SFGAO_FILESYSTEM) &&
				//	((ulAttrs & SFGAO_FOLDER) == 0))
				if (!(ulAttrs & SFGAO_FOLDER) || // folder
					((ulAttrs & SFGAO_FOLDER) && (ulAttrs & SFGAO_STREAM))) // zip file
				{
					WIN32_FIND_DATA fdata;
					HANDLE handle = ::FindFirstFile(szItemPath, &fdata);

					if (handle != INVALID_HANDLE_VALUE)
					{
						{
							LONGLONG fsize = fdata.nFileSizeHigh*((LONGLONG)ULONG_MAX + 1) + fdata.nFileSizeLow;

							TCHAR szBuffer[16];
							CString strSize;
							strSize.Format(_T("%s KB"), InsertCommas((fsize + 1024)/1024, szBuffer, 15));

							m_pListCtrl->SetItemText(iIndex, 1, strSize);
						}

						FILETIME ltime;
						::FileTimeToLocalFileTime(&fdata.ftLastWriteTime, &ltime);

						SYSTEMTIME time;
						::FileTimeToSystemTime(&ltime, &time);

						if ((time.wYear >= 1970 && time.wYear <= 2038) &&
							(time.wMonth >= 1 && time.wMonth <= 12))
						{
							CTime cTime;
							cTime = CTime(
								time.wYear,
								time.wMonth,
								time.wDay,
								time.wHour,
								time.wMinute,
								time.wSecond);

							m_pListCtrl->SetItemText(iIndex, 3, cTime.Format(_T("%m/%d/%y %I:%M %p")));
						}
						else
						{
							m_pListCtrl->SetItemText(iIndex, 3, _T("")); // Invalid date
						}

						::FindClose(handle);
					}

				}
				else
				{
					m_pListCtrl->SetItemText(iIndex, 2, _T("0 bytes"));
				}

				SHFILEINFO sfi;
				::SHGetFileInfo((TCHAR*)lpifqThisItem, 0, &sfi,
					sizeof(SHFILEINFO), SHGFI_PIDL | SHGFI_TYPENAME);

				m_pListCtrl->SetItemText(iIndex, 2, sfi.szTypeName);
			}
			else
			{
				if (lpifqThisItem)
				{
					lpMalloc.Free(lpifqThisItem);
				}

				return FALSE;
			}


			if (lpifqThisItem)
			{
				lpMalloc.Free(lpifqThisItem);
			}
		}

		// Free the pidl that the shell gave us.
		if (lpi)
		{
			lpMalloc.Free(lpi);
			lpi = NULL;
		}
	}

	if (lpe)
	{
		lpe->Release();
	}
	return TRUE;
}
#endif // _USE_XTREME_TOOLKITPRO