//	Album List for Winamp
//	Copyright (C) 1999-2001 Safai Ma
//
//	This program is free software; you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation; either version 2 of the License, or
//	(at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program; if not, write to the Free Software
//	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include <commctrl.h>
#include "resource.h"
#include "frontend.h"
#include "wa_ipc.h"
#include "gen.h"
#include "property.h"
#include "config.h"

extern winampGeneralPurposePlugin plugin;

/////////////////////////////////////////////////////////////////////////
// CTreePropertyPage
//

CTreePropertyPage *CTreePropertyPage::m_pPage = NULL;

CTreePropertyPage::CTreePropertyPage(UINT nIDTemplate, LPCTSTR szName /*=NULL*/, int nTree /*=0*/)
{
	m_lpszTemplateName = MAKEINTRESOURCE(nIDTemplate);
	m_hWnd = NULL;
	m_nTree = nTree;
	if (szName) lstrcpy(m_szName, szName);
}

CTreePropertyPage::~CTreePropertyPage()
{
}

void CTreePropertyPage::SetParams(LPCTSTR szName, int nTree /*=0*/)
{
	m_nTree = nTree;
	lstrcpy(m_szName, szName);
}

BOOL CTreePropertyPage::Create(HWND hParent)
{
	m_pPage = this;
	m_hWnd = CreateDialog(plugin.hDllInstance, m_lpszTemplateName, hParent, TPPWindowProc);
	m_pPage = NULL;
	if (m_hWnd == NULL) return FALSE;

	SetProp(m_hWnd, "CTreePropertyPage", (HANDLE)this);

	ShowWindow(m_hWnd, SW_SHOW);

	return TRUE;
}

BOOL CTreePropertyPage::SubclassDlgItem(UINT nID, WNDPROC wndProc, LPCTSTR str /*=NULL*/, DWORD dwData /*=0*/)
{
	HWND hWnd = GetDlgItem(m_hWnd, nID);
	if (hWnd == NULL) return FALSE;

	SetProp(hWnd, "OldWndProc", (HANDLE)GetWindowLong(hWnd, GWL_WNDPROC));
	SetWindowLong(hWnd, GWL_WNDPROC, (LONG)wndProc);

	if (str) SetProp(hWnd, str, (HANDLE)dwData);

	return TRUE;
}

BOOL CALLBACK CTreePropertyPage::TPPWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	CTreePropertyPage *pWnd = (CTreePropertyPage*)GetProp(hwnd, "CTreePropertyPage");

	if (pWnd == NULL)
	{
		pWnd = m_pPage;
		if (pWnd == NULL) return FALSE;
	}

	if (pWnd->DefWindowProc(hwnd, uMsg, wParam, lParam)) return TRUE;

	BOOL bRet = FALSE;
	switch(uMsg)
	{
	case WM_INITDIALOG:
		pWnd->m_hWnd = hwnd;
		bRet = pWnd->OnInitDialog();
		UpdateDialogStrings(hwnd);
		return bRet;

	case WM_DESTROY:
		pWnd->OnDestroy();
		break;
	}
	return FALSE;
}

BOOL CALLBACK CTreePropertyPage::DefWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return FALSE;
}

BOOL CTreePropertyPage::OnInitDialog()
{
	return FALSE;
}

void CTreePropertyPage::OnDestroy()
{
	RemoveProp(m_hWnd, "CTreePropertyPage");
	m_hWnd = NULL;
}

void CTreePropertyPage::OnOK()
{
}

void CTreePropertyPage::OnCancel()
{
}

LPTSTR CTreePropertyPage::GetName()
{
	return (LPTSTR)ALSTRING(m_szName);
}

/////////////////////////////////////////////////////////////////////////
// CTreePropertySheet
//

CTreePropertySheet *CTreePropertySheet::m_pSheet = NULL;

CTreePropertySheet::CTreePropertySheet()
{
	m_hWnd = NULL;
	m_nPageCount = 0;
}

CTreePropertySheet::~CTreePropertySheet()
{
}

BOOL CTreePropertySheet::Create(UINT nIDTemplate, HWND pParentWnd /*=NULL*/)
{
	m_pSheet = this;
	m_hWnd = CreateDialog(plugin.hDllInstance, MAKEINTRESOURCE(nIDTemplate), pParentWnd, TPSWindowProc);
	m_pSheet = NULL;
	if (m_hWnd == NULL) return FALSE;

	SetProp(m_hWnd, "CTreePropertySheet", (HANDLE)this);

	SelectPage(0);

	ShowWindow(m_hWnd, SW_SHOW);

	return TRUE;
}

void CTreePropertySheet::AddPage(CTreePropertyPage *pPage)
{
	if (m_nPageCount >= MAX_PAGE_COUNT) return;

	m_PageArray[m_nPageCount] = pPage;
	m_nPageCount++;
}

void CTreePropertySheet::AddPage(CTreePropertyPage *pPage, LPCTSTR szName, int nTree)
{
	if (m_nPageCount >= MAX_PAGE_COUNT) return;

	m_PageArray[m_nPageCount] = pPage;
	m_nPageCount++;

	pPage->SetParams(szName, nTree);
}

BOOL CALLBACK CTreePropertySheet::TPSWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	CTreePropertySheet *pWnd = (CTreePropertySheet*)GetProp(hwnd, "CTreePropertySheet");

	if (pWnd == NULL)
	{
		pWnd = m_pSheet;
		if (pWnd == NULL) return FALSE;
	}

	if (pWnd->DefWindowProc(hwnd, uMsg, wParam, lParam)) return TRUE;

	LPNMHDR pnmh;
	BOOL bRet = FALSE;
	switch(uMsg)
	{
	case WM_INITDIALOG:
		pWnd->m_hWnd = hwnd;
		bRet= pWnd->OnInitDialog();
		UpdateDialogStrings(hwnd);
		return bRet;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDOK:
			pWnd->OnOK();
			return TRUE;

		case IDCANCEL:
			pWnd->OnCancel();
			return TRUE;
		}

	case WM_NOTIFY:
		pnmh = (LPNMHDR)lParam;
		switch(pnmh->code)
		{
		case TVN_SELCHANGED:
			switch (pnmh->idFrom)
			{
			case IDC_OPTIONTREE:
				pWnd->OnNotifyTVNSelChanged((LPNMTREEVIEW)lParam);
				break;
			}
			break;
		}
		break;

	case WM_DESTROY:
		pWnd->OnDestroy();
		break;
	}
	return FALSE;
}

BOOL CALLBACK CTreePropertySheet::DefWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return FALSE;
}

BOOL CTreePropertySheet::OnInitDialog()
{
	HTREEITEM hTreeItem = TVI_ROOT;
	TVINSERTSTRUCT is;
	HWND hTree = GetDlgItem(m_hWnd, IDC_OPTIONTREE);

	for (int i=0; i<m_nPageCount; i++)
	{
		CTreePropertyPage *pPage = m_PageArray[i];
		is.hParent = pPage->IsTreeChild() ? hTreeItem : TVI_ROOT;
		is.hInsertAfter = TVI_LAST;
		is.item.mask = TVIF_TEXT|TVIF_PARAM;
		is.item.pszText = pPage->GetName();
		is.item.cchTextMax = lstrlen(is.item.pszText);
		is.item.lParam = (LPARAM)pPage;

		HTREEITEM hItem = TreeView_InsertItem(hTree, &is);

		if (is.hParent == TVI_ROOT)
		{
			TreeView_Expand(hTree, hTreeItem, TVE_EXPAND);
			hTreeItem = hItem;
		}

		TreeView_Expand(hTree, hTreeItem, TVE_EXPAND);
		pPage->SetTreeItem(hItem);
	}

	return TRUE;
}

void CTreePropertySheet::OnDestroy()
{
	RemoveProp(m_hWnd, "CTreePropertySheet");
	m_hWnd = NULL;
}

void CTreePropertySheet::OnOK()
{
	// call OnOK on all the pages
	for (int i=0; i<m_nPageCount; i++)
	{
		CTreePropertyPage *pPage = m_PageArray[i];
		if (pPage->m_hWnd)
		{
			pPage->OnOK();
		}
	}

	DestroyWindow(m_hWnd);
}

void CTreePropertySheet::OnCancel()
{
	// call OnOK on all the pages
	for (int i=0; i<m_nPageCount; i++)
	{
		CTreePropertyPage *pPage = m_PageArray[i];
		if (pPage->m_hWnd)
		{
			pPage->OnCancel();
		}
	}

	DestroyWindow(m_hWnd);
}

void CTreePropertySheet::OnNotifyTVNSelChanged(LPNMTREEVIEW pnmtv)
{
	// hide the old page (if necessary)
	if (pnmtv->itemOld.mask & TVIF_PARAM)
	{
		CTreePropertyPage *pOldPage = (CTreePropertyPage *)pnmtv->itemOld.lParam;
		if (pOldPage)
		{
			if (pOldPage->m_hWnd)
			{
				ShowWindow(pOldPage->m_hWnd, SW_HIDE);
			}
		}
	}

	// show the new page (create if necessary)
	if (pnmtv->itemNew.mask & TVIF_PARAM)
	{
		CTreePropertyPage *pNewPage = (CTreePropertyPage *)pnmtv->itemNew.lParam;
		if (pNewPage->m_hWnd == NULL)
		{
			pNewPage->Create(m_hWnd);

			// position the page in the right place
			HWND hHolder = GetDlgItem(m_hWnd, IDC_PPAGE_HOLDER);
			if (hHolder)
			{
				RECT rc;
				GetWindowRect(hHolder, &rc);
				POINT pt = { rc.left, rc.top };
				ScreenToClient(m_hWnd, &pt);
				SetWindowPos(pNewPage->m_hWnd, NULL, pt.x, pt.y, rc.right-rc.left, rc.bottom-rc.top, SWP_NOZORDER|SWP_NOACTIVATE);
			}
		}
		ShowWindow(pNewPage->m_hWnd, SW_SHOW);
	}
}

void CTreePropertySheet::SelectPage(int nPage)
{
	HWND hTree = GetDlgItem(m_hWnd, IDC_OPTIONTREE);

	CTreePropertyPage *pPage = m_PageArray[nPage];

	TreeView_SelectItem(hTree, pPage->GetTreeItem());
}
