/*

Jabber Protocol Plugin for Miranda IM
Copyright ( C ) 2002-04  Santithorn Bunchua
Copyright ( C ) 2005-07  George Hazan
Copyright ( C ) 2007     Maxim Mluhov
Copyright ( C ) 2007     Victor Pavlychko

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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include "stdafx.h"

HTREEITEM OptTree_FindNamedTreeItemAt(HWND hwndTree, HTREEITEM hItem, const wchar_t *name);
HTREEITEM OptTree_AddItem(HWND hwndTree, wchar_t *name, LPARAM lParam, int iconIndex);

static void OptTree_TranslateItem(HWND hwndTree, HTREEITEM hItem)
{
	wchar_t buf[128];

	TVITEM tvi = {0};
	tvi.mask = TVIF_HANDLE|TVIF_TEXT;
	tvi.hItem = hItem;
	tvi.pszText = buf;
	tvi.cchTextMax = _countof(buf);
	SendMessage(hwndTree, TVM_GETITEM, 0, (LPARAM)&tvi);
	// ��������, ���� �� ����������.
	if ((tvi.lParam != -1) && (pOptions[tvi.lParam].dwFlag & OPTTREE_NOTRANSLATE)) return;
	tvi.pszText = TranslateW(tvi.pszText);
	SendMessage(hwndTree, TVM_SETITEM, 0, (LPARAM)&tvi);
}

void OptTree_Translate(HWND hwndTree)
{
	HTREEITEM hItem = TreeView_GetRoot(hwndTree);
	while (hItem)
	{
		HTREEITEM hItemTmp = 0;

		OptTree_TranslateItem(hwndTree, hItem);
		if (hItemTmp = TreeView_GetChild(hwndTree, hItem))
		{
			hItem = hItemTmp;
		} else
		if (hItemTmp = TreeView_GetNextSibling(hwndTree, hItem))
		{
			hItem = hItemTmp;
		} else
		{
			while (1)
			{
				if (!(hItem = TreeView_GetParent(hwndTree, hItem))) break;
				if (hItemTmp = TreeView_GetNextSibling(hwndTree, hItem))
				{
					hItem = hItemTmp;
					break;
				}
			}
		}
	}
}

HTREEITEM OptTree_FindNamedTreeItemAt(HWND hwndTree, HTREEITEM hItem, const wchar_t *name)
{
	TVITEM tvi = {0};
	wchar_t str[MAX_PATH];

	if (hItem)
		tvi.hItem = TreeView_GetChild(hwndTree, hItem);
	else
		tvi.hItem = TreeView_GetRoot(hwndTree);

	if (!name)
		return tvi.hItem;

	tvi.mask = TVIF_TEXT;
	tvi.pszText = str;
	tvi.cchTextMax = _countof(str);

	while (tvi.hItem)
	{
		TreeView_GetItem(hwndTree, &tvi);

		if (!mir_wstrcmp(tvi.pszText, name))
			return tvi.hItem;

		tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem);
	}
	return NULL;
}

HTREEITEM OptTree_AddItem(HWND hwndTree, wchar_t *name, LPARAM lParam, int iconIndex)
{
	wchar_t itemName[1024];

	wchar_t* sectionName;
	int sectionLevel = 0;

	HTREEITEM hSection = NULL, result = NULL;
	mir_wstrcpy(itemName, name);
	sectionName = itemName;

	while (sectionName)
	{
		// allow multi-level tree
		wchar_t* pItemName = sectionName;
		HTREEITEM hItem;

		if (sectionName = wcschr(sectionName, '/'))
		{
			// one level deeper
			*sectionName = 0;
			sectionName++;
		}

		hItem = OptTree_FindNamedTreeItemAt(hwndTree, hSection, pItemName);
		if (!sectionName || !hItem)
		{
			if (!hItem)
			{
				TVINSERTSTRUCT tvis = {0};

				tvis.hParent = hSection;
				tvis.hInsertAfter = TVI_LAST;//TVI_SORT;
				tvis.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_STATE;
				tvis.item.pszText = pItemName;
				tvis.item.state = tvis.item.stateMask = TVIS_EXPANDED;
				if (sectionName)
				{
					tvis.item.lParam = 0;
					tvis.item.iImage = tvis.item.iSelectedImage = -1;
				} else
				{
					tvis.item.lParam = lParam;
					tvis.item.iImage = tvis.item.iSelectedImage = iconIndex;
					tvis.item.mask |= TVIF_IMAGE|TVIF_SELECTEDIMAGE;
				}
				hItem = TreeView_InsertItem(hwndTree, &tvis);
				if (!sectionName)
					result = hItem;
			}
		}
		sectionLevel++;
		hSection = hItem;
	}

	return result;
}

BOOL  OptTree_ProcessMessage(HWND hwnd, UINT msg, WPARAM, LPARAM lparam, BOOL*, int idcTree, OPTTREE_OPTION *options, int optionCount)
{
	enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_RCHECK, IMG_NORCHECK, IMG_GRPOPEN, IMG_GRPCLOSED };

	HWND hwndTree = GetDlgItem(hwnd, idcTree);
	switch (msg)
	{
		case WM_INITDIALOG:
		{
			int indx;
			wchar_t itemName[1024];
			HIMAGELIST hImgLst;

			TreeView_SelectItem(hwndTree, NULL);
			TreeView_DeleteAllItems(hwndTree);

			hImgLst = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR|ILC_COLOR32|ILC_MASK, 5, 1);
			ImageList_ReplaceIcon(hImgLst, -1, (HICON)Skin_LoadIcon(SKINICON_OTHER_MIRANDA));
			ImageList_ReplaceIcon(hImgLst, -1, (HICON)Skin_LoadIcon(SKINICON_OTHER_TICK));	// check on
			ImageList_ReplaceIcon(hImgLst, -1, (HICON)Skin_LoadIcon(SKINICON_OTHER_NOTICK));	// check off
			ImageList_ReplaceIcon(hImgLst, -1, (HICON)Skin_LoadIcon(SKINICON_OTHER_TICK));	// radio on
			ImageList_ReplaceIcon(hImgLst, -1, (HICON)Skin_LoadIcon(SKINICON_OTHER_NOTICK));	// radio on
			ImageList_ReplaceIcon(hImgLst, -1, (HICON)Skin_LoadIcon(SKINICON_OTHER_GROUPOPEN));
			ImageList_ReplaceIcon(hImgLst, -1, (HICON)Skin_LoadIcon(SKINICON_OTHER_GROUPSHUT));
			TreeView_SetImageList(hwndTree, hImgLst, TVSIL_NORMAL);

			/* build options tree. based on code from IcoLib */
			for (indx = 0; indx < optionCount; indx++)
			{
				wchar_t* sectionName;
				int sectionLevel = 0;

				HTREEITEM hSection = NULL;
				if (options[indx].szOptionName)
					mir_wstrcpy(itemName, options[indx].szOptionName);
				else
					itemName[0] = 0;

				sectionName = itemName;

				while (sectionName)
				{
					// allow multi-level tree
					wchar_t* pItemName = sectionName;
					HTREEITEM hItem;

					if (sectionName = wcschr(sectionName, '/'))
					{
						// one level deeper
						*sectionName = 0;
						sectionName++;
					}

					hItem = OptTree_FindNamedTreeItemAt(hwndTree, hSection, pItemName);
					//if (!sectionName || !hItem)
					if ((!sectionName || !hItem) && !(options[indx].dwFlag & OPTTREE_INVISIBLE))
					{
						if (!hItem)
						{
							TVINSERTSTRUCT tvis = {0};

							tvis.hParent = hSection;
							tvis.hInsertAfter = TVI_LAST;//TVI_SORT;
							tvis.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_STATE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
							tvis.item.pszText = pItemName;
							tvis.item.state = tvis.item.stateMask = TVIS_EXPANDED;
							if (sectionName)
							{
								tvis.item.lParam = -1;
								tvis.item.state |= TVIS_BOLD;
								tvis.item.stateMask |= TVIS_BOLD;
								tvis.item.iImage = tvis.item.iSelectedImage = IMG_GRPOPEN;
							} else
							{
								tvis.item.lParam = indx;
								if (options[indx].groupId == OPTTREE_CHECK)
								{
									tvis.item.iImage = tvis.item.iSelectedImage = IMG_NOCHECK;
								} else
								{
									tvis.item.iImage = tvis.item.iSelectedImage = IMG_NORCHECK;
								}
							}
							hItem = TreeView_InsertItem(hwndTree, &tvis);
							if (!sectionName)
								options[indx].hItem = hItem;
						}
					}
					sectionLevel++;
					hSection = hItem;
				}
			}

			OptTree_Translate(hwndTree);
			ShowWindow(hwndTree, SW_SHOW);
			TreeView_SelectItem(hwndTree, OptTree_FindNamedTreeItemAt(hwndTree, 0, NULL));
			break;
		}

		case WM_DESTROY:
		{
			ImageList_Destroy(TreeView_GetImageList(hwndTree, TVSIL_NORMAL));
			break;
		}

		case WM_NOTIFY:
		{
			LPNMHDR lpnmhdr = (LPNMHDR)lparam;
			if (lpnmhdr->idFrom != idcTree) break;
			switch (lpnmhdr->code)
			{
				case NM_CLICK:
				{
					TVHITTESTINFO hti;
					hti.pt.x=(short)LOWORD(GetMessagePos());
					hti.pt.y=(short)HIWORD(GetMessagePos());
					ScreenToClient(lpnmhdr->hwndFrom,&hti.pt);
					if(TreeView_HitTest(lpnmhdr->hwndFrom,&hti))
					{
						if(hti.flags&TVHT_ONITEMICON)
						{
							TVITEM tvi;
							tvi.mask=TVIF_HANDLE|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
							tvi.hItem=hti.hItem;
							TreeView_GetItem(lpnmhdr->hwndFrom,&tvi);
							switch (tvi.iImage)
							{
								case IMG_GRPOPEN:
									tvi.iImage = tvi.iSelectedImage = IMG_GRPCLOSED;
									TreeView_Expand(lpnmhdr->hwndFrom, tvi.hItem, TVE_COLLAPSE);
									break;
								case IMG_GRPCLOSED:
									tvi.iImage = tvi.iSelectedImage = IMG_GRPOPEN;
									TreeView_Expand(lpnmhdr->hwndFrom, tvi.hItem, TVE_EXPAND);
									break;

								case IMG_CHECK:
									tvi.iImage = tvi.iSelectedImage = IMG_NOCHECK;
									SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
									break;
								case IMG_NOCHECK:
									tvi.iImage = tvi.iSelectedImage = IMG_CHECK;
									SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
									break;
								case IMG_NORCHECK:
								{
									int i;
									for (i = 0; i < optionCount; ++i)
									{
										if (options[i].groupId == options[tvi.lParam].groupId)
										{
											TVITEM tvi_tmp;
											tvi_tmp.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
											tvi_tmp.hItem = options[i].hItem;
											tvi_tmp.iImage = tvi_tmp.iSelectedImage = IMG_NORCHECK;
											TreeView_SetItem(lpnmhdr->hwndFrom, &tvi_tmp);
										}
									}
									tvi.iImage = tvi.iSelectedImage = IMG_RCHECK;
									SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
									break;
								}
							}
							TreeView_SetItem(lpnmhdr->hwndFrom,&tvi);
						}
					}
					break;
				}
				
				case TVN_ITEMEXPANDED:
					LPNMTREEVIEW lpnmtv = (LPNMTREEVIEW)lparam;
					TVITEM tvi;
					tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
					tvi.hItem = lpnmtv->itemNew.hItem;
					tvi.iImage = tvi.iSelectedImage =
						(lpnmtv->itemNew.state & TVIS_EXPANDED) ? IMG_GRPOPEN : IMG_GRPCLOSED;
					SendMessage(lpnmhdr->hwndFrom, TVM_SETITEM, 0, (LPARAM)&tvi);
					break;
			}
			break;
		}
	}
	return FALSE;
}

DWORD OptTree_GetOptions(HWND hwnd, int idcTree, OPTTREE_OPTION *options, int optionCount, char *szSettingName)
{
	enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_RCHECK, IMG_NORCHECK, IMG_GRPOPEN, IMG_GRPCLOSED };

	HWND hwndTree = GetDlgItem(hwnd, idcTree);
	DWORD result = 0;
	int i;
	for (i = 0; i < optionCount; ++i)
	{
		if ((!options[i].szSettingName && !szSettingName) ||
			(options[i].szSettingName && szSettingName && !mir_strcmp(options[i].szSettingName, szSettingName)))
		{
			TVITEM tvi;
			tvi.mask = TVIF_HANDLE|TVIF_IMAGE;
			tvi.hItem = options[i].hItem;
			TreeView_GetItem(hwndTree, &tvi);
			if ((tvi.iImage == IMG_CHECK) || (tvi.iImage == IMG_RCHECK))
				result |= options[i].dwFlag;
		}
	}
	return result;
}

void OptTree_SetOptions(HWND hwnd, int idcTree, OPTTREE_OPTION *options, int optionCount, DWORD dwOptions, char *szSettingName)
{
	enum { IMG_GROUP, IMG_CHECK, IMG_NOCHECK, IMG_RCHECK, IMG_NORCHECK, IMG_GRPOPEN, IMG_GRPCLOSED };

	HWND hwndTree = GetDlgItem(hwnd, idcTree);
	int i;
	for (i = 0; i < optionCount; ++i)
	{
		if ((!options[i].szSettingName && !szSettingName) ||
			(options[i].szSettingName && szSettingName && !mir_strcmp(options[i].szSettingName, szSettingName)))
		{
			TVITEM tvi;
			tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
			tvi.hItem = options[i].hItem;
			if (options[i].groupId == OPTTREE_CHECK)
			{
				tvi.iImage = tvi.iSelectedImage = (dwOptions & options[i].dwFlag) ? IMG_CHECK : IMG_NOCHECK;
			} else
			{
				tvi.iImage = tvi.iSelectedImage = (dwOptions & options[i].dwFlag) ? IMG_RCHECK : IMG_NORCHECK;
			}
			TreeView_SetItem(hwndTree, &tvi);
		}
	}
}