/*
UserinfoEx plugin for Miranda IM

Copyright:
� 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol

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 "commonheaders.h"

typedef struct _ICODESC 
{
	LPSTR	pszName;
	LPSTR	pszDesc;
	LPSTR	pszSection;
	WORD	idResource;
	BYTE	size;
} ICODESC;

HICON ghDefIcon = NULL;

static ICODESC icoDesc[] = 
{
	// common
	{ ICO_COMMON_IM,		LPGEN("IM Naming"),					SECT_COMMON,	IDI_MIRANDA,			0	},
	{ ICO_COMMON_PASSWORD,	LPGEN("Password"),					SECT_COMMON,	IDI_PASSWORD,			0	},
	{ ICO_COMMON_FEMALE,	LPGEN("Female"),					SECT_COMMON,	IDI_FEMALE,				0	},
	{ ICO_COMMON_MALE,		LPGEN("Male"),						SECT_COMMON,	IDI_MALE,				0	},
	{ ICO_COMMON_BIRTHDAY,	LPGEN("Birthday"),					SECT_COMMON,	IDI_BIRTHDAY,			0	},
	{ ICO_COMMON_CLOCK,		LPGEN("Timezone"),					SECT_COMMON,	IDI_CLOCK,				1	},
	{ ICO_COMMON_MARITAL,	LPGEN("Marital status"),			SECT_COMMON,	IDI_MARITAL,			0	},
	{ ICO_COMMON_ADDRESS,	LPGEN("Address"),					SECT_COMMON,	IDI_TREE_ADDRESS,		0	},
	{ ICO_COMMON_ANNIVERSARY,LPGEN("Anniversary"),				SECT_COMMON,	IDI_ANNIVERSARY,		0	},

	//zodiac
	{ ICO_ZOD_AQUARIUS,		LPGEN("Aquarius"),					SECT_COMMON,	IDI_ZOD_AQUARIUS,		128	},
	{ ICO_ZOD_ARIES,		LPGEN("Aries"),						SECT_COMMON,	IDI_ZOD_ARIES,			128	},
	{ ICO_ZOD_CANCER,		LPGEN("Cancer"),					SECT_COMMON,	IDI_ZOD_CANCER,			128	},
	{ ICO_ZOD_CAPRICORN,	LPGEN("Capricorn"),					SECT_COMMON,	IDI_ZOD_CAPRICORN,		128	},
	{ ICO_ZOD_GEMINI,		LPGEN("Gemini"),					SECT_COMMON,	IDI_ZOD_GEMINI,			128	},
	{ ICO_ZOD_LEO,			LPGEN("Leo"),						SECT_COMMON,	IDI_ZOD_LEO,			128	},
	{ ICO_ZOD_LIBRA,		LPGEN("Libra"),						SECT_COMMON,	IDI_ZOD_LIBRA,			128	},
	{ ICO_ZOD_PISCES,		LPGEN("Pisces"),					SECT_COMMON,	IDI_ZOD_PISCES,			128	},
	{ ICO_ZOD_SAGITTARIUS,	LPGEN("Sagittarius"),				SECT_COMMON,	IDI_ZOD_SAGITTARIUS,	128	},
	{ ICO_ZOD_SCORPIO,		LPGEN("Scorpio"),					SECT_COMMON,	IDI_ZOD_SCORPIO,		128	},
	{ ICO_ZOD_TAURUS,		LPGEN("Taurus"),					SECT_COMMON,	IDI_ZOD_TAURUS,			128	},
	{ ICO_ZOD_VIRGO,		LPGEN("Virgo"),						SECT_COMMON,	IDI_ZOD_VIRGO,			128	},
	// later with new icon pack version
	//{ ICO_ZOD_UNKNOWN,		LPGEN("Unknown"),					SECT_COMMON,	IDI_ZOD_UNKNOWN,		128	},

	// lists
	{ ICO_LST_MODULES,		LPGEN("Export: Modules"),			SECT_COMMON,	IDI_LST_MODULES,		0	},
	{ ICO_LST_FOLDER,		LPGEN("Export: Folder"),			SECT_COMMON,	IDI_LST_FOLDER,			0	},
	{ ICO_TREE_DEFAULT,		LPGEN("Default"),					SECT_TREE,		IDI_LST_FOLDER,			0	},

	// dialogs
	{ ICO_DLG_DETAILS,		LPGEN("Details Infobar"),			SECT_DLG,		IDI_DLG_DETAILS,		48	},
	{ ICO_DLG_PHONE,		LPGEN("Phone Infobar"),				SECT_DLG,		IDI_DLG_PHONE,			1	},
	{ ICO_DLG_EMAIL,		LPGEN("E-Mail Infobar"),			SECT_DLG,		IDI_DLG_EMAIL,			1	},
	{ ICO_DLG_EXPORT,		LPGEN("Export VCard"),				SECT_DLG,		IDI_EXPORT,				1	},
	{ ICO_DLG_IMPORT,		LPGEN("Import VCard"),				SECT_DLG,		IDI_IMPORT,				1	},
	{ ICO_DLG_ANNIVERSARY,	LPGEN("Anniversary Infobar"),		SECT_DLG,		IDI_ANNIVERSARY,		1	},

	// button icons
	{ ICO_BTN_UPDATE,		LPGEN("Update"),					SECT_BUTTONS,	IDI_BTN_UPDATE,			0	},
	{ ICO_BTN_IMPORT,		LPGEN("Import"),					SECT_BUTTONS,	IDI_IMPORT,				0	},
	{ ICO_BTN_EXPORT,		LPGEN("Export"),					SECT_BUTTONS,	IDI_EXPORT,				0	},
	{ ICO_BTN_OK,			LPGEN("Ok"),						SECT_BUTTONS,	IDI_BTN_OK,				0	},
	{ ICO_BTN_CANCEL,		LPGEN("Cancel"),					SECT_BUTTONS,	IDI_BTN_CLOSE,			0	},
	{ ICO_BTN_APPLY,		LPGEN("Apply"),						SECT_BUTTONS,	IDI_BTN_APPLY,			0	},
	{ ICO_BTN_GOTO,			LPGEN("Goto"),						SECT_BUTTONS,	IDI_BTN_GOTO,			0	},
	{ ICO_BTN_PHONE,		LPGEN("Phone"),						SECT_BUTTONS,	IDI_BTN_PHONE,			0	},
	{ ICO_BTN_FAX,			LPGEN("Fax"),						SECT_BUTTONS,	IDI_BTN_FAX,			0	},
	{ ICO_BTN_CELLULAR,		LPGEN("Cellular"),					SECT_BUTTONS,	IDI_BTN_CELLULAR,		0	},
	{ ICO_BTN_CUSTOMPHONE,	LPGEN("Custom Phone"),				SECT_BUTTONS,	IDI_BTN_CUSTOMPHONE,	0	},
	{ ICO_BTN_EMAIL,		LPGEN("e-mail"),					SECT_BUTTONS,	IDI_BTN_EMAIL,			0	},
	{ ICO_BTN_DOWNARROW,	LPGEN("Down arrow"),				SECT_BUTTONS,	IDI_BTN_DOWNARROW,		0	},
	{ ICO_BTN_ADD,			LPGEN("Add"),						SECT_BUTTONS,	IDI_BTN_ADD,			0	},
	{ ICO_BTN_EDIT,			LPGEN("Edit"),						SECT_BUTTONS,	IDI_BTN_EDIT,			0	},
	{ ICO_BTN_DELETE,		LPGEN("Delete"),					SECT_BUTTONS,	IDI_BTN_DELETE,			0	},
	{ ICO_BTN_SEARCH,		LPGEN("Search"),					SECT_BUTTONS,	IDI_SEARCH,				0	},
	{ ICO_BTN_EXIMPORT,		LPGEN("Ex-/Import"),				SECT_BUTTONS,	IDI_BTN_EXIMPORT,		0	},
	{ ICO_BTN_BDAY_BACKUP,	LPGEN("Backup Birthday"),			SECT_BUTTONS,	IDI_BTN_BIRTHDAY_BACKUP,0	},
	//{ ICO_BTN_YES,		LPGEN("Yes"),						SECT_BUTTONS,	IDI_BTN_YES,			0	},
	//{ ICO_BTN_NO,			LPGEN("No"),						SECT_BUTTONS,	IDI_BTN_NO,				0	},
	//{ ICO_BTN_IGNORE,		LPGEN("Ignore"),					SECT_BUTTONS,	IDI_BTN_IGNORE,			0	},

	//birthday and anniversary
	{ ICO_RMD_DTB0,			LPGEN("Birthday today"),			SECT_REMIND,	IDI_RMD_DTB0,			0	},
	{ ICO_RMD_DTB1,			LPGEN("Birthday tomorrow"),			SECT_REMIND,	IDI_RMD_DTB1,			0	},
	{ ICO_RMD_DTB2,			LPGEN("Birthday in 2 days"),		SECT_REMIND,	IDI_RMD_DTB2,			0	},
	{ ICO_RMD_DTB3,			LPGEN("Birthday in 3 days"),		SECT_REMIND,	IDI_RMD_DTB3,			0	},
	{ ICO_RMD_DTB4,			LPGEN("Birthday in 4 days"),		SECT_REMIND,	IDI_RMD_DTB4,			0	},
	{ ICO_RMD_DTB5,			LPGEN("Birthday in 5 days"),		SECT_REMIND,	IDI_RMD_DTB5,			0	},
	{ ICO_RMD_DTB6,			LPGEN("Birthday in 6 days"),		SECT_REMIND,	IDI_RMD_DTB6,			0	},
	{ ICO_RMD_DTB7,			LPGEN("Birthday in 7 days"),		SECT_REMIND,	IDI_RMD_DTB7,			0	},
	{ ICO_RMD_DTB8,			LPGEN("Birthday in 8 days"),		SECT_REMIND,	IDI_RMD_DTB8,			0	},
	{ ICO_RMD_DTB9,			LPGEN("Birthday in 9 days"),		SECT_REMIND,	IDI_RMD_DTB9,			0	},
	{ ICO_RMD_DTBX,			LPGEN("Birthday later"),			SECT_REMIND,	IDI_RMD_DTBX,			0	},
		
	{ ICO_RMD_DTA0,			LPGEN("Anniversary today"),			SECT_REMIND,	IDI_RMD_DTA0,			0	},
	{ ICO_RMD_DTA1,			LPGEN("Anniversary tomorrow"),		SECT_REMIND,	IDI_RMD_DTA1,			0	},
	{ ICO_RMD_DTA2,			LPGEN("Anniversary in 2 days"),		SECT_REMIND,	IDI_RMD_DTA2,			0	},
	{ ICO_RMD_DTA3,			LPGEN("Anniversary in 3 days"),		SECT_REMIND,	IDI_RMD_DTA3,			0	},
	{ ICO_RMD_DTA4,			LPGEN("Anniversary in 4 days"),		SECT_REMIND,	IDI_RMD_DTA4,			0	},
	{ ICO_RMD_DTA5,			LPGEN("Anniversary in 5 days"),		SECT_REMIND,	IDI_RMD_DTA5,			0	},
	{ ICO_RMD_DTA6,			LPGEN("Anniversary in 6 days"),		SECT_REMIND,	IDI_RMD_DTA6,			0	},
	{ ICO_RMD_DTA7,			LPGEN("Anniversary in 7 days"),		SECT_REMIND,	IDI_RMD_DTA7,			0	},
	{ ICO_RMD_DTA8,			LPGEN("Anniversary in 8 days"),		SECT_REMIND,	IDI_RMD_DTA8,			0	},
	{ ICO_RMD_DTA9,			LPGEN("Anniversary in 9 days"),		SECT_REMIND,	IDI_RMD_DTA9,			0	},
	{ ICO_RMD_DTAX,			LPGEN("Anniversary later"),			SECT_REMIND,	IDI_RMD_DTAX,			0	},
};	

/**
 * This function finds the default iconpack file and return its path.
 *
 * @param		- none
 *
 * @return		This function returns the relative path to an existing icon pack.
 **/
LPTSTR IcoLib_GetDefaultIconFileName()
{
	static LPTSTR	path[] = {
		_T("Icons\\uinfoex_icons.dll"),
		_T("Plugins\\uinfoex_icons.dll"),
		_T("Customize\\Icons\\uinfoex_icons.dll")
	};
	TCHAR absolute[MAX_PATH];

	for (int i = 0; i < SIZEOF(path); i++) {
		PathToAbsoluteT(path[i], absolute);
		if ( PathFileExists(absolute))
			return path[i];
	}
	return NULL;
}

/**
 * This function checks the version of an iconpack.
 * If the icon pack's version differs from the desired one, 
 * dialog with a warning is displayed.
 *
 * @param		szIconPack	- This is the path to the icon pack. 
 *							  It can be absolute or relative.
 *
 * @return	nothing
 **/
static void IcoLib_CheckIconPackVersion(LPTSTR szIconPack)
{
	if (db_get_b(NULL, MODNAME, SET_ICONS_CHECKFILEVERSION, TRUE))
	{
		if (szIconPack)
		{
			TCHAR szAbsolutePath[MAX_PATH];
			PathToAbsoluteT(szIconPack, szAbsolutePath);

			HMODULE hIconDll = LoadLibrary(szAbsolutePath);
			if (hIconDll) 
			{
				CHAR szFileVersion[64];

				if (!LoadStringA(hIconDll, IDS_ICOPACKVERSION, szFileVersion, sizeof(szFileVersion)) ||
						mir_strcmp(szFileVersion, "__UserInfoEx_IconPack_1.2__"))
				{
					MsgErr(NULL, LPGENT("Warning: Your current IconPack's version differs from the one UserInfoEx is designed for.\nSome icons may not be displayed correctly"));
				}
				FreeLibrary(hIconDll);
			}
		}
		else
		{
			MsgErr(NULL, LPGENT("Warning: No IconPack found in one of the following directories: 'customize\\icons', 'icons' or 'plugins'!"));
		}
	}
}

/**
 * Returns a icon, identified by a name
 *
 * @param	pszIcon	- name of the icon
 *
 * @return:	HICON if the icon is loaded, NULL otherwise
 **/
HICON IcoLib_GetIcon(LPCSTR pszIcon)
{
	return (pszIcon) ? Skin_GetIcon(pszIcon) : NULL;
}

/**
 * Returns a icon, identified by a name
 *
 * @param	hIconItem	- this is the pointer to an IconItem structure in icolib.
 *
 * @return:	HICON if the icon is loaded, NULL otherwise
 **/
HICON IcoLib_GetIconByHandle(HANDLE hIconItem)
{
	return Skin_GetIconByHandle(hIconItem);
}

/**
 * Set the icon of each control in the list
 *
 * @param	hDlg		- handle to the dialog control, that owns the controls
 * @param	pCtrl		- list to all controls and its icon names
 * @param	numCtrls	- number of elements in the pCtrl list
 *
 * @return	nothing
 **/
void IcoLib_SetCtrlIcons(HWND hDlg, const ICONCTRL* pCtrl, BYTE numCtrls)
{
	HICON	hIcon;
	BYTE	i;
	HWND	hCtrl;

	for (i = 0; i < numCtrls; i++) 
	{
		hIcon = IcoLib_GetIcon(pCtrl[i].pszIcon);
		if (pCtrl[i].idCtrl)	
		{
			hCtrl = GetDlgItem(hDlg, pCtrl[i].idCtrl);
			switch (pCtrl[i].Message) 
			{
				case STM_SETICON:
				case STM_SETIMAGE:
						{
						ShowWindow(hCtrl, hIcon ? SW_SHOW : SW_HIDE);
					}
				case BM_SETIMAGE:
					{
						SendMessage(hCtrl, pCtrl[i].Message, IMAGE_ICON, (LPARAM) hIcon);
					}
			}
		}
		else
		{
			SendMessage(hDlg, pCtrl[i].Message, ICON_BIG, (LPARAM) hIcon);
		}
	}
}

/**
 * This function manually registers a single icon from the default icon library.
 *
 * @param		szIconID		- This is the uniquely identifying string for an icon. 
 *								  This string is the setting name in the database and should 
 *								  only use ASCII characters.
 * @param		szDescription	- This is the description displayed in the options dialog.
 * @param		szSection		- This is the subsection, where the icon is organized in the options dialog.
 * @param		szDefaultFile	- This is the validated path to the default icon file.
 * @param		idIcon			- This is the ResourceID of the icon in the default file.
 * @param		Size			- This is the desired size of the icon to load.
 *								  0:	default size for small icons (16x16)
 *								  1:	default size for normal icons (32x32)
 * @param		hDefIcon		- This is the default icon to use if the default icon
 *								  file does not exist and no custom icon is set up in the config.
 *
 * @return	This function returns the HANDLE of the icon item.
 **/
static HANDLE IcoLib_RegisterIconHandleEx(LPSTR szIconID, LPSTR szDescription, LPSTR szSection, LPTSTR szDefaultFile, int idIcon, int Size, HICON hDefIcon)
{
	HANDLE hIconHandle = NULL;

	if (szIconID && szDescription && szSection) {
		SKINICONDESC sid = { sizeof(sid) };
		sid.flags = SIDF_ALL_TCHAR;
		sid.pszName = szIconID;
		sid.ptszDescription = mir_a2t(szDescription);
		sid.ptszSection = mir_a2t(szSection);

		if (sid.ptszDescription && sid.ptszSection) {
			switch (Size) {
			// small icons (16x16)
			case 0:
				sid.cx = GetSystemMetrics(SM_CXSMICON);
				sid.cy = GetSystemMetrics(SM_CYSMICON);
				break;

			// normal icons (32x32)
			case 1:
				sid.cx = GetSystemMetrics(SM_CXICON);
				sid.cy = GetSystemMetrics(SM_CYICON);
				break;

			// custom icon size
			default:
				sid.cx = sid.cy = Size;
				break;
			}

			sid.ptszDefaultFile = szDefaultFile;
			if (sid.ptszDefaultFile && sid.ptszDefaultFile[0])
				sid.iDefaultIndex = -idIcon;
			else {
				sid.hDefaultIcon = hDefIcon;
				sid.iDefaultIndex = -1;
			}
			hIconHandle = Skin_AddIcon(&sid);
		}
		MIR_FREE(sid.ptszDescription);
		MIR_FREE(sid.ptszSection);
	}
	return hIconHandle;
}

/**
 * This function manually registers a single icon from the default icon library.
 *
 * @param		szIconID		- This is the uniquely identifying string for an icon. 
 *								  This string is the setting name in the database and should 
 *								  only use ASCII characters.
 * @param		szDescription	- This is the description displayed in the options dialog.
 * @param		szSection		- This is the subsection, where the icon is organized in the options dialog.
 * @param		idIcon			- This is the ResourceID of the icon in the default file
 * @param		Size			- This is the desired size of the icon to load.
 *								  0:	default size for small icons (16x16)
 *								  1:	default size for normal icons (32x32)
 *
 * @return	This function returns the HANDLE of the icon item.
 **/
HANDLE IcoLib_RegisterIconHandle(LPSTR szIconID, LPSTR szDescription, LPSTR szSection, int idIcon, int Size)
{
	return IcoLib_RegisterIconHandleEx(szIconID, szDescription, szSection, IcoLib_GetDefaultIconFileName(), idIcon, Size, ghDefIcon);
}

/**
 * This function manually registers a single icon from the default icon library.
 *
 * @param		szIconID		- This is the uniquely identifying string for an icon. 
 *								  This string is the setting name in the database and should 
 *								  only use ASCII characters.
 * @param		szDescription	- This is the description displayed in the options dialog.
 * @param		szSection		- This is the subsection, where the icon is organized in the options dialog.
 * @param		idIcon			- This is the ResourceID of the icon in the default file
 * @param		Size			- This is the desired size of the icon to load.
 *								  0:	default size for small icons (16x16)
 *								  1:	default size for normal icons (32x32)
 *
 * @return	 This function returns the HICON of the icon itself.
 **/
HICON IcoLib_RegisterIcon(LPSTR szIconID, LPSTR szDescription, LPSTR szSection, int idIcon, int Size)
{
	return IcoLib_GetIconByHandle(IcoLib_RegisterIconHandle(szIconID, szDescription, szSection, idIcon, Size));
}

/**
 * Add default icons to the skin library or load customized icons
 *
 * @param		none
 *
 * @return		nothing
 **/
void IcoLib_LoadModule()
{
	LPTSTR szDefaultFile = IcoLib_GetDefaultIconFileName();
	IcoLib_CheckIconPackVersion(szDefaultFile);

	// load default icon if required
	ghDefIcon = (HICON)LoadImage(ghInst, MAKEINTRESOURCE(IDI_DEFAULT), IMAGE_ICON, 
							 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);

	for (int i = 0; i < SIZEOF(icoDesc); i++) {	
		IcoLib_RegisterIconHandleEx(
			icoDesc[i].pszName, icoDesc[i].pszDesc, icoDesc[i].pszSection, 
			szDefaultFile, icoDesc[i].idResource, icoDesc[i].size, ghDefIcon);
	}
}