#include <windows.h>
#include <commctrl.h>
#include <TCHAR.H>
#include <SWI-Prolog.h>

#include "resource.h"
#include "defs.h"

extern HFONT HfBold;
extern HWND HWnd;
HWND HElv;
LPLVITEM LpLviElvSelection;
WNDPROC ElvPrevProc;

HWND
ElvCreate()
{
	LVCOLUMN lvc;

	LpLviElvSelection = malloc(sizeof(LVITEM));
	if (!LpLviElvSelection) return NULL;
	HElv = LvCreate((HMENU)IDC_EPISODELISTVIEW);

	lvc.mask = LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
	lvc.iSubItem = 0;
	lvc.pszText = TEXT("#");
	lvc.cx = 42;
	ListView_InsertColumn(HElv, 0, &lvc);

	lvc.iSubItem = 1;
	lvc.pszText = TEXT("Title");
	lvc.cx = 500;
	ListView_InsertColumn(HElv, 1, &lvc);

	ElvUpdate();
	ElvSelectRecent();
	return HElv;
}

LRESULT
ElvHandleNotify(LPARAM lParam)
{
	LPNMLISTVIEW lpNmLv;
	lpNmLv = (LPNMLISTVIEW)lParam;

	switch (lpNmLv->hdr.code) {
	case LVN_ITEMCHANGED:
		if ((lpNmLv->uChanged & LVIF_STATE)
			&& (lpNmLv->uNewState & LVIS_FOCUSED)) {
			LpLviElvSelection->iItem = lpNmLv->iItem;
			LpLviElvSelection->lParam = lpNmLv->lParam;
			ElvUpdateName(LpLviElvSelection);
			DlvShowEpisode(lpNmLv->lParam);
		}
		break;
	case NM_CUSTOMDRAW:
	{
		LPNMLVCUSTOMDRAW lpLvCd;
		lpLvCd = (LPNMLVCUSTOMDRAW)lParam;
		switch (lpLvCd->nmcd.dwDrawStage) {
		case CDDS_PREPAINT:
			return CDRF_NOTIFYITEMDRAW;
			break;
		case CDDS_ITEMPREPAINT:
			if (!Watched(lpLvCd->nmcd.lItemlParam)) {
				SelectObject(lpLvCd->nmcd.hdc,
					HfBold);
				return CDRF_NEWFONT;
			}
			break;
		}
		break;
	}
	case NM_DBLCLK:
	{
		fid_t f;
		term_t t;
		F(f);
		t = T(1);
		PI(t+0, LpLviElvSelection->lParam) goto b;
		P("local_episodes","open_episode",1,t);
b:		Fd(f);
		break;
	}
	case NM_RCLICK:
	{
		DWORD dwPos;
		extern HMENU HPopupMenu;
		dwPos = GetMessagePos();
		TrackPopupMenu(HPopupMenu, TPM_RIGHTBUTTON,
			LOWORD(dwPos), HIWORD(dwPos), 0,
			HWnd, NULL);
		break;
	}
	}

	return 0;
}
void
ElvRedraw()
{
	RedrawWindow(HElv, NULL, NULL,
		RDW_ERASE|RDW_FRAME|RDW_INVALIDATE|RDW_ALLCHILDREN);
}

void
ElvSetTop(int iItem)
{
	int iLast;
	iLast = ListView_GetItemCount(HElv)-1;
	ListView_EnsureVisible(HElv, iLast, TRUE);
	ListView_EnsureVisible(HElv, iItem, TRUE);
}

/* Select most recent episode. */
void
ElvSelectRecent()
{
	fid_t f;
	int iEpisode, iItem;
	LVFINDINFO lvfi;
	term_t t;

	F(f);
	t = T(1);
	P("track_episodes","most_recently_watched",1,t) goto e;
	GI(t,&iEpisode) goto e;

	lvfi.flags = LVFI_PARAM;
	lvfi.lParam = iEpisode;

	iItem = ListView_FindItem(HElv, -1, &lvfi);
	if (iItem == -1) goto e;

	if (iItem > 5)
		ElvSetTop(iItem-5);
	ListView_SetItemState(HElv, iItem, LVIS_SELECTED, LVIS_SELECTED);
	LpLviElvSelection->iItem = iItem;
	LpLviElvSelection->lParam = iEpisode;
	ElvUpdateName(LpLviElvSelection);
	DlvShowEpisode(iEpisode);

e:	Fd(f);
}

/* Update episode list. */
void
ElvUpdate()
{
	fid_t f;
	int iTop;
	LVITEM lviEpisode, lviName;
	qid_t q;
	term_t t;

	SendMessage(HElv, WM_SETREDRAW, FALSE, 0);
	iTop = ListView_GetTopIndex(HElv);
	ListView_DeleteAllItems(HElv);

	lviEpisode.mask = LVIF_TEXT|LVIF_PARAM;
	lviName.mask = LVIF_TEXT;

	F(f);
	t = T(2);
	q = Q("local_episodes","episode_file",2,t);

	for (int i = 0; Qn(q); i++) {
		char *szName;
		fid_t f2;
		int cb, iEpisode, iItem, r;
		TCHAR *tszEpisode, *tszName;
		term_t t2;

		/* Format name string. */

		GI(t,&iEpisode) goto e;
		F(f2);
		t2 = T(3);
		PI(t2,iEpisode) goto e;
		tszName = NULL;
		P("episode_data","lookup_episode_local",3,t2) goto skipname;
		GAC(t2+1,&szName) goto skipname;
		tszName = TszFromSz(szName, CP_UTF8);
		if (!tszName) goto e;

		/* Format episode string. */
skipname:
		cb = 100;
		tszEpisode = malloc(cb*sizeof(TCHAR));
		if (!tszEpisode) goto e1;
		_stprintf_s(tszEpisode, cb, TEXT("%d"), iEpisode);

		/* Insert item. */

		lviEpisode.iItem = i;
		lviEpisode.iSubItem = 0;
		lviEpisode.pszText = tszEpisode;
		lviEpisode.lParam = iEpisode;
		ListView_InsertItem(HElv, &lviEpisode);

		if (tszName) {
			lviName.iItem = i;
			lviName.iSubItem = 1;
			lviName.pszText = tszName;
			ListView_SetItem(HElv, &lviName);
		}

		free(tszEpisode);
e1:		if (tszName) free(tszName);
e:		Fd(f2);
	}

	/* Reset selection and scrolling position. */

	ElvSetTop(iTop);
	if (LpLviElvSelection) {
		ListView_SetItemState(HElv, LpLviElvSelection->iItem,
			LVIS_SELECTED, LVIS_SELECTED);
	}

	SendMessage(HElv, WM_SETREDRAW, TRUE, 0);
	ElvRedraw();
	Qc(q);
	Fd(f);
}

/* Update episode name. */
void
ElvUpdateName(LPLVITEM lpLvi)
{
	char *szName;
	fid_t f;
	TCHAR *tszName;
	term_t t;

	F(f);
	t = T(3);
	PI(t,lpLvi->lParam) goto e;
	P("episode_data","lookup_episode",3,t) goto e;
	GAC(t+1,&szName) goto e;

	tszName = TszFromSz(szName, CP_UTF8);
	if (!tszName) goto e;

	ListView_SetItemText(HElv, lpLvi->iItem, 1, tszName);

e:	Fd(f);
	return;
}