/*
 * YAMN plugin main file
 * Miranda homepage: http://miranda-icq.sourceforge.net/
 * YAMN homepage: http://www.majvan.host.sk/Projekty/YAMN
 *
 * initializes all variables for further work
 *
 * (c) majvan 2002-2004
 */


#include "main.h"
#include "yamn.h"
#include "resources/resource.h"
#include <io.h>
//- imported ---------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------

//CRITICAL_SECTION MWCS;
//CRITICAL_SECTION ASCS;
//CRITICAL_SECTION PRCS;

extern LPCRITICAL_SECTION PluginRegCS;
extern HANDLE ExitEV;
extern HANDLE WriteToFileEV;

extern int PosX,PosY,SizeX,SizeY;
extern int HeadPosX,HeadPosY,HeadSizeX,HeadSizeY,HeadSplitPos;

//From account.cpp
extern LPCRITICAL_SECTION AccountStatusCS;
extern LPCRITICAL_SECTION FileWritingCS;
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------

WCHAR	*ProfileName		= NULL;		//e.g. "majvan"
WCHAR	*UserDirectory		= NULL;		//e.g. "F:\WINNT\Profiles\UserXYZ"
char	*ProtoName			= YAMN_DBMODULE;
//char *AltProtoName;
char	*szMirandaDir		= NULL;
char	*szProfileDir		= NULL;

INT_PTR YAMN_STATUS;

BOOL UninstallPlugins;

HANDLE hAccountFolder;

HINSTANCE *hDllPlugins;
static int iDllPlugins=0;

PLUGINLINK *pluginLink;
YAMN_VARIABLES YAMNVar;

int hLangpack;
struct MM_INTERFACE mmi;

static const MUUID interfaces[] = {MUUID_YAMN_FORCECHECK, MIID_LAST};

PLUGININFOEX pluginInfo={
	sizeof(PLUGININFOEX),
	YAMN_SHORTNAME,
	YAMN_VERSION,
	"Mail notifier and browser for Miranda IM. Included POP3 protocol. Mod for Mataes Pack.",
	"y_b tweety (majvan)",
	"francois.mean@skynet.be",
	"� (2002-2004 majvan) 2005-2007 tweety y_b Miranda community",
	"http://www.miranda-im.org/download/details.php?action=viewfile&id=3411", //"http://www.majvan.host.sk/Projekty/YAMN?fm=soft",
	UNICODE_AWARE,
	0,		//doesn't replace anything built-in
	{ 0xb047a7e5, 0x27a, 0x4cfc, { 0x8b, 0x18, 0xed, 0xa8, 0x34, 0x5d, 0x27, 0x90 } } // {B047A7E5-027A-4cfc-8B18-EDA8345D2790}

};

SKINSOUNDDESC NewMailSound={
	sizeof(SKINSOUNDDESC),
	YAMN_NEWMAILSOUND,	//name to refer to sound when playing and in db
	YAMN_NEWMAILSNDDESC,	//description for options dialog
	"",	   		//default sound file to use, without path
};

SKINSOUNDDESC ConnectFailureSound={
	sizeof(SKINSOUNDDESC),
	YAMN_CONNECTFAILSOUND,	//name to refer to sound when playing and in db
	YAMN_CONNECTFAILSNDDESC,//description for options dialog
	"",	   		//default sound file to use, without path
};

HANDLE hNewMailHook;
//HANDLE hUninstallPluginsHook;

HANDLE NoWriterEV;

HANDLE hTTButton;		//TopToolBar button

DWORD HotKeyThreadID;

UINT SecTimer;

BOOL bIcolibEmbededInCore = FALSE;

HICON hYamnIcons[ICONSNUMBER];
char *iconDescs[ICONSNUMBER]={ICONSDESCS};
char *iconNames[ICONSNUMBER]={ICONSNAMES};
 int iconIndexes[ICONSNUMBER]={ICONSINDS};

HANDLE hMenuItemMain = 0;
HANDLE hMenuItemCont = 0;
HANDLE hMenuItemContApp = 0;

BOOL     (WINAPI *MyEnableThemeDialogTexture)(HANDLE, DWORD) = 0;
HMODULE hUxTheme = 0;

// function pointers, use typedefs for casting to shut up the compiler when using GetProcAddress()

typedef BOOL (WINAPI *PITA)();
typedef HANDLE (WINAPI *POTD)(HWND, LPCWSTR);
typedef UINT (WINAPI *PDTB)(HANDLE, HDC, int, int, RECT *, RECT *);
typedef UINT (WINAPI *PCTD)(HANDLE);
typedef UINT (WINAPI *PDTT)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, DWORD, RECT *);

PITA pfnIsThemeActive = 0;
POTD pfnOpenThemeData = 0;
PDTB pfnDrawThemeBackground = 0;
PCTD pfnCloseThemeData = 0;
PDTT pfnDrawThemeText = 0;

#define FIXED_TAB_SIZE 100                  // default value for fixed width tabs

/*
 * visual styles support (XP+)
 * returns 0 on failure
 */

int InitVSApi()
{
    if((hUxTheme = LoadLibraryA("uxtheme.dll")) == 0)
        return 0;

    pfnIsThemeActive = (PITA)GetProcAddress(hUxTheme, "IsThemeActive");
    pfnOpenThemeData = (POTD)GetProcAddress(hUxTheme, "OpenThemeData");
    pfnDrawThemeBackground = (PDTB)GetProcAddress(hUxTheme, "DrawThemeBackground");
    pfnCloseThemeData = (PCTD)GetProcAddress(hUxTheme, "CloseThemeData");
    pfnDrawThemeText = (PDTT)GetProcAddress(hUxTheme, "DrawThemeText");
    
    MyEnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD))GetProcAddress(hUxTheme, "EnableThemeDialogTexture");
    if(pfnIsThemeActive != 0 && pfnOpenThemeData != 0 && pfnDrawThemeBackground != 0 && pfnCloseThemeData != 0 && pfnDrawThemeText != 0) {
        return 1;
    }
    return 0;
}

/*
 * unload uxtheme.dll
 */

int FreeVSApi()
{
    if(hUxTheme != 0)
        FreeLibrary(hUxTheme);
    return 0;
}


//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------

static void GetProfileDirectory(char *szPath,int cbPath)
//This is copied from Miranda's sources. In 0.2.1.0 it is needed, in newer vesions of Miranda use MS_DB_GETPROFILEPATH service
{
	szProfileDir=new char[MAX_PATH];
	if (ServiceExists(MS_DB_GETPROFILEPATH)){
		if (!CallService(MS_DB_GETPROFILEPATH,(WPARAM)cbPath,(LPARAM)szPath)) {
			lstrcpy(szProfileDir,szPath);
			return; //success
		}
	}
	char szMirandaIni[MAX_PATH],szExpandedProfileDir[MAX_PATH];
	DWORD dwAttributes;

	lstrcpy(szMirandaIni,szMirandaDir);
	lstrcat(szMirandaIni,"\\mirandaboot.ini");
	GetPrivateProfileString("Database","ProfileDir",".",szProfileDir,sizeof(szProfileDir),szMirandaIni);
	ExpandEnvironmentStrings(szProfileDir,szExpandedProfileDir,sizeof(szExpandedProfileDir));
	_chdir(szMirandaDir);
	if(!_fullpath(szPath,szExpandedProfileDir,cbPath))
		lstrcpyn(szPath,szMirandaDir,cbPath);
	if(szPath[lstrlen(szPath)-1]=='\\') szPath[lstrlen(szPath)-1]='\0';
	if((dwAttributes=GetFileAttributes(szPath))!=0xffffffff&&dwAttributes&FILE_ATTRIBUTE_DIRECTORY) return;
	CreateDirectory(szPath,NULL);
}

void SetDefaultProtocolIcons()
{
	char szFileName[MAX_PATH+1];
	char oldname[] = YAMN_DBMODULE"4007_"; // the deprecated one
	char dllname[] = "plugins\\"YAMN_DBMODULE".dll,-xxxxx";

	// determine whether external icon file exists
	lstrcpy(szFileName, szMirandaDir);
	lstrcat(szFileName, "\\icons\\proto_"YAMN_DBMODULE".dll");
	BOOL isDllPresent = (_access(szFileName, 0) == 0);

	WORD statuses[4] = {ID_STATUS_OFFLINE,ID_STATUS_ONLINE,ID_STATUS_NA,ID_STATUS_OCCUPIED};
	BYTE  indices[4] = {7,                0,               3,           4};
	//From skinicons.c skinIconStatusToIdStatus[] 
	BYTE protoStatusInd[4] = {0,1,4,5};

	for (int i=0;i<4;i++){
		oldname[sizeof(oldname)-2]=protoStatusInd[i]+'1'; // "Out for lunch will not work here"
		if (isDllPresent){ // use the icons in proto_YAMN.dll and delete any user settings
			DBDeleteContactSetting(NULL, "Icons", oldname);
		} else {
			DBVARIANT dbv;
			if(!DBGetContactSetting(NULL,"SkinIcons",iconNames[indices[i]],&dbv)) 
			{// user won't be able to set status icons different from those in YAMN section
				DBWriteContactSettingString(NULL, "Icons", oldname, (char *)dbv.pszVal);			
				DBFreeVariant(&dbv);
			} else {
				_snprintf(&dllname[sizeof(dllname)-6],5,"%d",iconIndexes[indices[i]]);
				DBWriteContactSettingString(NULL, "Icons", oldname, dllname);			
			}
		}
	}
}

extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
	YAMNVar.hInst=hinstDLL;
	if(fdwReason==DLL_PROCESS_ATTACH)
	{
		if(NULL==(UserDirectory=new WCHAR[MAX_PATH]))
			return FALSE;
	}
	return TRUE;
}

extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
{
	if (mirandaVersion >= PLUGIN_MAKE_VERSION(0, 7, 0, 3))
		bIcolibEmbededInCore = TRUE;
	pluginInfo.cbSize = sizeof(PLUGININFO);//Miranda pre-0.7.0.17 does not load the plugin if cbSize does not match.
	return (PLUGININFO *) &pluginInfo;
}

extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
{
	if (mirandaVersion >= PLUGIN_MAKE_VERSION(0, 7, 0, 3))
		bIcolibEmbededInCore = TRUE;
	pluginInfo.cbSize = sizeof(PLUGININFOEX);//Make sure cbSize is correct;
	return &pluginInfo;
}

extern "C" __declspec(dllexport) const MUUID * MirandaPluginInterfaces(void)
{
	return interfaces;
}

#ifdef YAMN_DEBUG
static char unknownCP[1500]={0};
#endif
// The callback function
BOOL CALLBACK EnumSystemCodePagesProc(LPTSTR cpStr)
{
    //Convert code page string to number
    UINT cp = _ttoi(cpStr);
    if (!IsValidCodePage(cp))
        return TRUE;

    //Get Code Page name
    CPINFOEX info;
    if(GetCPInfoEx(cp,0,&info)){
		#ifdef YAMN_DEBUG
		BOOLEAN found = FALSE;
		#endif
		for (int i=1;i<CPLENALL;i++) if (CodePageNamesAll[i].CP==cp) {
			CodePageNamesAll[i].isValid = TRUE;
			CPLENSUPP++;
			#ifdef YAMN_DEBUG
			found = TRUE;
			#endif
			break;
		}
		#ifdef YAMN_DEBUG
		if (!found) {
			strcat(unknownCP,info.CodePageName);
			strcat(unknownCP,"\n");
		}
		#endif
	}
    return TRUE;
}

int SystemModulesLoaded(WPARAM,LPARAM){
	if(ServiceExists(MS_SKIN2_ADDICON))
	{
		//MessageBox(NULL,"Icolib present","test",0);
		SKINICONDESC sid = {0};
		HICON temp;
		sid.cbSize = SKINICONDESC_SIZE; 
		sid.pszSection = "YAMN";
		sid.pszDefaultFile = NULL;
		for (int i=0; i<ICONSNUMBER; i++){
			sid.iDefaultIndex = -iconIndexes[i];
			sid.pszName = iconNames[i];
			sid.pszDescription = iconDescs[i];
			sid.hDefaultIcon = hYamnIcons[i];
			CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
			if (temp = (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) iconNames[i]))hYamnIcons[i]=temp; 
		}
	}

	CLISTMENUITEM mi;

	//Insert "Check mail (YAMN)" item to Miranda's menu
	ZeroMemory(&mi,sizeof(mi));
	mi.cbSize = sizeof(mi);
	mi.position = 0xb0000000;
	mi.flags = 0;
	mi.hIcon = hYamnIcons[5];
	mi.pszName = "Check &mail (All Account)";
	mi.pszPopupName = NULL;//ProtoName;
	mi.pszService = MS_YAMN_FORCECHECK;
	if(DBGetContactSettingByte(NULL, YAMN_DBMODULE, YAMN_SHOWMAINMENU, 1))
		hMenuItemMain = (HANDLE) CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);

	mi.pszName = "Check &mail (This Account)";
	mi.pszContactOwner = ProtoName;
	mi.pszService = MS_YAMN_CLISTCONTEXT;
	hMenuItemCont = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);

	mi.hIcon = hYamnIcons[4];
	mi.pszName = "Launch application";
	mi.pszContactOwner = ProtoName;
	mi.pszService = MS_YAMN_CLISTCONTEXTAPP;
	hMenuItemContApp = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);

	//Use for the Updater plugin
	if(ServiceExists(MS_UPDATE_REGISTER)) 
	{
		Update update = {0};
		char szVersion[16];
		char szUrl[250];

		update.szComponentName = pluginInfo.shortName;
		update.pbVersion = (BYTE *)CreateVersionStringPlugin((PLUGININFO *)&pluginInfo, szVersion);
		update.cpbVersion = (int)strlen((char *)update.pbVersion);
		/*#ifdef YAMN_9x
		update.szUpdateURL = "http://addons.miranda-im.org/feed.php?dlfile=2166";
		update.szVersionURL = "http://addons.miranda-im.org/details.php?action=viewfile&id=2166";
		update.pbVersionPrefix = (BYTE *)"<span class=\"fileNameHeader\">YAMN tweety win9x ";
		#else
		update.szUpdateURL = "http://addons.miranda-im.org/feed.php?dlfile=2165";
		update.szVersionURL = "http://addons.miranda-im.org/details.php?action=viewfile&id=2165";
		update.pbVersionPrefix = (BYTE *)"<span class=\"fileNameHeader\">YAMN tweety ";
		#endif*/
		update.szUpdateURL = "http://addons.miranda-im.org/feed.php?dlfile=3411";
		update.szVersionURL = "http://addons.miranda-im.org/details.php?action=viewfile&id=3411";
		update.pbVersionPrefix = (BYTE *)"<span class=\"fileNameHeader\">YAMN 2in1 ";
		wsprintf(szUrl,"http://www.miranda-fr.net/tweety/yamn/%s.zip",YAMN_FILENAME);
	    update.szBetaUpdateURL = szUrl;
		update.szBetaVersionURL = "http://www.miranda-fr.net/tweety/yamn/yamn_beta.html";
		update.pbBetaVersionPrefix = (BYTE *)"YAMN version ";
		update.cpbVersionPrefix = (int)strlen((char *)update.pbVersionPrefix);
		update.cpbBetaVersionPrefix = (int)strlen((char *)update.pbBetaVersionPrefix);

		CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);

	}
	if (ServiceExists(MS_FOLDERS_GET_PATH)){
		//char AccountFolder[MAX_PATH];
		//CallService(MS_DB_GETPROFILEPATH, (WPARAM) MAX_PATH, (LPARAM)AccountFolder);
		//sprintf(AccountFolder,"%s\\%s",AccountFolder,ProtoName);
		hAccountFolder = FoldersRegisterCustomPathW(ProtoName,YAMN_DBMODULE" Account Folder", UserDirectory);
		
		FoldersGetCustomPathW(hAccountFolder,  UserDirectory, MAX_PATH, UserDirectory);
		//MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,AccountFolder,-1,UserDirectory,strlen(AccountFolder)+1);
	}

	RegisterPOP3Plugin(0,0);

	return 0;
}

//int IcoLibIconsChanged(WPARAM wParam, LPARAM lParam); // implemented in services.cpp
extern HCURSOR hCurSplitNS, hCurSplitWE;
extern "C" int __declspec(dllexport) Load(PLUGINLINK *link)
{
	UINT mod,vk;
	char pn[MAX_PATH+1];
	char *fc;
	int i,k;

	pluginLink=link;
	mir_getLP(&pluginInfo);
	mir_getMMI(&mmi);

	YAMN_STATUS = ID_STATUS_OFFLINE;

	//	we get the Miranda Root Path
	szMirandaDir=new char[MAX_PATH];
	if (ServiceExists(MS_UTILS_PATHTOABSOLUTE)){
		CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)".",(LPARAM)szMirandaDir);
	}
	else {
		char *str2;
		GetModuleFileName(GetModuleHandle(NULL),szMirandaDir,MAX_PATH);
		str2=strrchr(szMirandaDir,'\\');
		if(str2!=NULL) *str2=0;
	}

	//	we get the user path where our yamn-account.book.ini is stored from mirandaboot.ini file
	char szProfileDir[MAX_PATH+1];
	GetProfileDirectory(szProfileDir,sizeof(szProfileDir));
	MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,szProfileDir,-1,UserDirectory,(int)strlen(szProfileDir)+1);

	
	// Enumerate all the code pages available for the System Locale
	EnumSystemCodePages(EnumSystemCodePagesProc, CP_INSTALLED);
	CodePageNamesSupp = new _tcptable[CPLENSUPP];
	for (i=0,k=0;i<CPLENALL;i++) {
		if (CodePageNamesAll[i].isValid){
			CodePageNamesSupp[k]=CodePageNamesAll[i];
			k++;
		}
	}
	#ifdef YAMN_DEBUG
//unknownCP	0x6005a734
//20127 (US-ASCII)
//20261 (T.61)
//28605 (ISO 8859-15 Latin 9)
//737   (OEM - Greek 437G)
//874   (ANSI/OEM - Thai)
//932   (ANSI/OEM - Japanese Shift-JIS)
//936   (ANSI/OEM - Simplified Chinese GBK)
//949   (ANSI/OEM - Korean)
    MessageBox( NULL,unknownCP, TEXT("Unkown Code Page"), MB_OK);
	#endif

	HIMAGELIST CSImages = ImageList_Create(16, 16, ILC_COLOR8|ILC_MASK, 0, 3);
	{// workarround of 4bit forced images
		HBITMAP hScrBM = (HBITMAP)LoadImage(YAMNVar.hInst,MAKEINTRESOURCE(IDB_ICONS), IMAGE_BITMAP, 0, 0,LR_SHARED);
		ImageList_AddMasked(CSImages, hScrBM, RGB( 255, 0, 255 ));
		DeleteObject(hScrBM);
	}
	for (i=0,k=0; i<ICONSNUMBER; i++){
		switch (i){
			case 0: case 3: case 4: case 7: hYamnIcons[i] = LoadIcon(YAMNVar.hInst,MAKEINTRESOURCE(iconIndexes[i])); break;
			case 6: hYamnIcons[i] = hYamnIcons[4]; break;
			default: hYamnIcons[i] = ImageList_ExtractIcon(NULL, CSImages, k); k++;
		}
	}

	//Registering YAMN as protocol
	PROTOCOLDESCRIPTOR pd = {0};
	pd.cbSize=PROTOCOLDESCRIPTOR_V3_SIZE;
	pd.szName=ProtoName;
	pd.type=PROTOTYPE_PROTOCOL;
	
	CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd);

	if(NULL==(ProfileName=new WCHAR[MAX_PATH]))
		return 1;

	CallService(MS_DB_GETPROFILENAME,(WPARAM)sizeof(pn),(LPARAM)&(*pn));	//not to pass entire array to fcn
	if(NULL!=(fc=strrchr(pn,(int)'.')))
		*fc=0;
	MultiByteToWideChar(CP_ACP,MB_USEGLYPHCHARS,pn,-1,ProfileName,(int)strlen(pn)+1);

	if(NULL==(AccountStatusCS=new CRITICAL_SECTION))
		return 1;
	if(NULL==(FileWritingCS=new CRITICAL_SECTION))
		return 1;
	if(NULL==(PluginRegCS=new CRITICAL_SECTION))
		return 1;

	InitializeCriticalSection(AccountStatusCS);
	InitializeCriticalSection(FileWritingCS);
	InitializeCriticalSection(PluginRegCS);

	if(NULL==(NoWriterEV=CreateEvent(NULL,TRUE,TRUE,NULL)))
		return 1;
	if(NULL==(WriteToFileEV=CreateEvent(NULL,FALSE,FALSE,NULL)))
		return 1;
	if(NULL==(ExitEV=CreateEvent(NULL,TRUE,FALSE,NULL)))
		return 1;
//	AccountWriterSO=new SCOUNTER(NoWriterEV);

	NewMailSound.pszDescription=Translate(YAMN_NEWMAILSNDDESC);
	ConnectFailureSound.pszDescription=Translate(YAMN_CONNECTFAILSNDDESC);

	PosX=DBGetContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBPOSX,0);
	PosY=DBGetContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBPOSY,0);
	SizeX=DBGetContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBSIZEX,800);
	SizeY=DBGetContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBSIZEY,200);

	HeadPosX=DBGetContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBMSGPOSX,0);
	HeadPosY=DBGetContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBMSGPOSY,0);
	HeadSizeX=DBGetContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBMSGSIZEX,690);
	HeadSizeY=DBGetContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBMSGSIZEY,300);
	HeadSplitPos=DBGetContactSettingWord(NULL,YAMN_DBMODULE,YAMN_DBMSGPOSSPLIT,250);

	optDateTime=DBGetContactSettingByte(NULL,YAMN_DBMODULE,YAMN_DBTIMEOPTIONS,optDateTime);

//Create new window queues for broadcast messages
	YAMNVar.MessageWnds=(HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0);
	YAMNVar.NewMailAccountWnd=(HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST,0,0);
	YAMNVar.Shutdown=FALSE;

	hCurSplitNS = LoadCursor(NULL, IDC_SIZENS);
	hCurSplitWE = LoadCursor(NULL, IDC_SIZEWE);

#ifdef YAMN_DEBUG
	InitDebug();
#endif


	CreateServiceFunctions();

	CallService(MS_SKIN_ADDNEWSOUND,0,(LPARAM)&NewMailSound);
	CallService(MS_SKIN_ADDNEWSOUND,0,(LPARAM)&ConnectFailureSound);

	/*
	// this does nothing - these event are never fired
	hNewMailHook=CreateHookableEvent(ME_YAMN_NEWMAIL);
	hUninstallPluginsHook=CreateHookableEvent(ME_YAMN_UNINSTALLPLUGINS);
	*/	

	HookEvents();

	if (!bIcolibEmbededInCore)
		SetDefaultProtocolIcons();

	LoadPlugins();

	InitVSApi();

	WordToModAndVk(DBGetContactSettingWord(NULL,YAMN_DBMODULE,YAMN_HKCHECKMAIL,YAMN_DEFAULTHK),&mod,&vk);
		
//Create thread for hotkey
	WORD HotKey = MAKEWORD((BYTE)vk,(BYTE)mod);
	CloseHandle(CreateThread(NULL,0,YAMNHotKeyThread,(LPVOID)HotKey,0,&HotKeyThreadID));
//Create thread that will be executed every second
	if(!(SecTimer=SetTimer(NULL,0,1000,(TIMERPROC)TimerProc)))
		return 1;


#ifdef YAMN_VER_BETA
	#ifdef YAMN_VER_BETA_CRASHONLY
	MessageBox(NULL,"This YAMN beta version is intended for testing. After crash, you should send report to author. Please read included readme when available. Thank you.","YAMN beta",MB_OK);
	#else
	MessageBox(NULL,"This YAMN beta version is intended for testing. You should inform author if it works or when it does not work. Please read included readme when available. Thank you.","YAMN beta",MB_OK);
	#endif
#endif
#ifdef YAMN_DEBUG
	MessageBox(NULL,"This YAMN creates extended debug logfiles. It is not intended for general use.","YAMN beta",MB_OK);
#endif

	return 0;
}

extern "C" int __declspec(dllexport) UninstallEx(PLUGINUNINSTALLPARAMS* ppup)
{
	const char* DocFiles[]={"YAMN-License.txt","YAMN-Readme.txt","YAMN-Readme.developers.txt",NULL};

	typedef int (* UNINSTALLFILTERFCN)();
	UNINSTALLFILTERFCN UninstallFilter;

	PUIRemoveSkinSound(YAMN_NEWMAILSOUND);
	PUIRemoveSkinSound(YAMN_CONNECTFAILSOUND);

	if(UninstallPlugins)
	{
		for(int i=0;i<iDllPlugins;i++)
		{
			if(NULL!=(UninstallFilter=(UNINSTALLFILTERFCN)GetProcAddress(hDllPlugins[i],"UninstallFilter")))
				UninstallFilter();

			FreeLibrary(hDllPlugins[i]);
			hDllPlugins[i]=NULL;				//for safety
		}
		iDllPlugins = 0;
		if(hDllPlugins){
			free((void *)hDllPlugins);
			hDllPlugins = NULL;
		}

//		NotifyEventHooks(ME_YAMN_UNINSTALLPLUGINS,0,0);
	}
	UninstallPOP3(ppup);

	MessageBoxA(NULL,"You have to delete manually YAMN plugins located in \"Plugins/YAMN\" folder.","YAMN uninstalling",MB_OK|MB_ICONINFORMATION);
	PUIRemoveFilesInDirectory(ppup->pszDocsPath,DocFiles);
	if(ppup->bDoDeleteSettings)
		PUIRemoveDbModule("YAMN");
	return 0;
}

int Shutdown(WPARAM,LPARAM)
{
	DBWriteContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBMSGPOSX,HeadPosX);
	DBWriteContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBMSGPOSY,HeadPosY);
	DBWriteContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBMSGSIZEX,HeadSizeX);
	DBWriteContactSettingDword(NULL,YAMN_DBMODULE,YAMN_DBMSGSIZEY,HeadSizeY);
	DBWriteContactSettingWord(NULL,YAMN_DBMODULE,YAMN_DBMSGPOSSPLIT,HeadSplitPos);
	YAMNVar.Shutdown=TRUE;
//	CallService(MS_TTB_REMOVEBUTTON,(WPARAM)hTTButton,0);		//this often leads to deadlock in Miranda (bug in Miranda)
	KillTimer(NULL,SecTimer);

	UnregisterProtoPlugins();
	UnregisterFilterPlugins();
	return 0;
}

//We undo all things from Load()
extern "C" int __declspec(dllexport) Unload(void)
{
#ifdef YAMN_DEBUG
	UnInitDebug();
#endif
	DestroyCursor(hCurSplitNS);
	DestroyCursor(hCurSplitWE);

	CloseHandle(NoWriterEV);
	CloseHandle(WriteToFileEV);
	CloseHandle(ExitEV);

	FreeVSApi();

	DeleteCriticalSection(AccountStatusCS);
	delete AccountStatusCS;
	DeleteCriticalSection(FileWritingCS);
	delete FileWritingCS;
	DeleteCriticalSection(PluginRegCS);

	delete PluginRegCS;
	UnhookEvents();
	DestroyServiceFunctions();

	UnloadPlugins();

	delete [] CodePageNamesSupp;
	delete [] szMirandaDir;
	delete [] UserDirectory;
	delete [] szProfileDir;
	delete [] ProfileName;
	return 0;
}

void LoadPlugins()
{
	HANDLE hFind;
	WIN32_FIND_DATA fd;
	char szSearchPath[MAX_PATH];
	char szPluginPath[MAX_PATH];
	lstrcpy(szSearchPath,szMirandaDir);
	lstrcat(szSearchPath,"\\Plugins\\YAMN\\*.dll");
	typedef INT_PTR (*LOADFILTERFCN)(MIRANDASERVICE GetYAMNFcn);

	hDllPlugins=NULL;

	if(INVALID_HANDLE_VALUE!=(hFind=FindFirstFile(szSearchPath,&fd)))
	{
		do
		{	//rewritten from Miranda sources... Needed because Win32 API has a bug in FindFirstFile, search is done for *.dlllllll... too
			char *dot=strrchr(fd.cFileName,'.');
			if(dot)
			{ // we have a dot
				int len=(int)strlen(fd.cFileName); // find the length of the string
				char* end=fd.cFileName+len; // get a pointer to the NULL
				int safe=(end-dot)-1;	// figure out how many chars after the dot are "safe", not including NULL
		
				if((safe!=3) || (lstrcmpi(dot+1,"dll")!=0)) //not bound, however the "dll" string should mean only 3 chars are compared
					continue;
			}
			else
				continue;
			
			HINSTANCE hDll;
			LOADFILTERFCN LoadFilter;

			lstrcpy(szPluginPath,szMirandaDir);
			lstrcat(szPluginPath,"\\Plugins\\YAMN\\");
			lstrcat(szPluginPath,fd.cFileName);
			if((hDll=LoadLibrary(szPluginPath))==NULL) continue;
			LoadFilter=(LOADFILTERFCN)GetProcAddress(hDll,"LoadFilter");
			if(NULL==LoadFilter)
			{
				FreeLibrary(hDll);
				hDll=NULL;
				continue;
			}
			if(!(*LoadFilter)(GetFcnPtrSvc))
			{
				FreeLibrary(hDll);
				hDll=NULL;
			}

			if(hDll!=NULL)
			{
				hDllPlugins=(HINSTANCE *)realloc((void *)hDllPlugins,(iDllPlugins+1)*sizeof(HINSTANCE));
				hDllPlugins[iDllPlugins++]=hDll;
			}
		} while(FindNextFile(hFind,&fd));
	FindClose(hFind);
	}
}

void UnloadPlugins()
{
	for(int i=iDllPlugins-1;i>=0;i--) {
		if(FreeLibrary(hDllPlugins[i])){
			hDllPlugins[i]=NULL;				//for safety
			iDllPlugins --;
		}
	}
	if(hDllPlugins){
		free((void *)hDllPlugins);
		hDllPlugins = NULL;
	}
}

void GetIconSize(HICON hIcon, int* sizeX, int* sizeY)
{
    ICONINFO ii;
    BITMAP bm;
    GetIconInfo(hIcon, &ii);
    GetObject(ii.hbmColor, sizeof(bm), &bm);
    if (sizeX != NULL) *sizeX = bm.bmWidth;
    if (sizeY != NULL) *sizeY = bm.bmHeight;
    DeleteObject(ii.hbmMask);
    DeleteObject(ii.hbmColor);
}

HBITMAP LoadBmpFromIcon(HICON hIcon)
{
	HBITMAP hBmp, hoBmp;
    HDC hdc, hdcMem;
    HBRUSH hBkgBrush;

	int IconSizeX = 16;
    int IconSizeY = 16;

	//GetIconSize(hIcon, &IconSizeX, &IconSizeY);

	//DebugLog(SynchroFile,"Icon size %i %i\n",IconSizeX,IconSizeY);

    if ((IconSizeX == 0) || (IconSizeY == 0)) 
	{    
        IconSizeX = 16;
        IconSizeY = 16;
    }

    RECT rc;
    BITMAPINFOHEADER bih = {0};
    int widthBytes;

    hBkgBrush = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
    bih.biSize = sizeof(bih);
    bih.biBitCount = 24;
    bih.biPlanes = 1;
    bih.biCompression = BI_RGB;
    bih.biHeight = IconSizeY;
    bih.biWidth = IconSizeX; 
    widthBytes = ((bih.biWidth*bih.biBitCount + 31) >> 5) * 4;
    rc.top = rc.left = 0;
    rc.right = bih.biWidth;
    rc.bottom = bih.biHeight;
    hdc = GetDC(NULL);
    hBmp = CreateCompatibleBitmap(hdc, bih.biWidth, bih.biHeight);
    hdcMem = CreateCompatibleDC(hdc);
    hoBmp = (HBITMAP)SelectObject(hdcMem, hBmp);
    FillRect(hdcMem, &rc, hBkgBrush);
    DrawIconEx(hdcMem, 0, 0, hIcon, bih.biWidth, bih.biHeight, 0, NULL, DI_NORMAL);
    SelectObject(hdcMem, hoBmp);

	return hBmp;
}

int AddTopToolbarIcon(WPARAM,LPARAM)
{
	TTBButton Button=
	{
		sizeof(TTBButton),
		NULL,
		NULL,
		NULL,
		MS_YAMN_FORCECHECK,
		TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP, // | TTBBF_DRAWBORDER,
		0,0,0,0,
		NULL
	};

	if(!DBGetContactSettingByte(NULL,YAMN_DBMODULE,YAMN_TTBFCHECK,1))
		return 1;
	
	Button.name=Translate("Check mail");
	
	Button.hbBitmapUp = LoadBmpFromIcon(hYamnIcons[5]);
	Button.hbBitmapDown = LoadBmpFromIcon(hYamnIcons[6]); //LoadBitmap(YAMNVar.hInst,MAKEINTRESOURCE(IDB_BMTTB));
	
	if((HANDLE)-1==(hTTButton=(HANDLE)CallService(MS_TTB_ADDBUTTON,(WPARAM)&Button,(LPARAM)0)))
		return 1;
	CallService(MS_TTB_SETBUTTONOPTIONS,MAKEWPARAM((WORD)TTBO_TIPNAME,(WORD)hTTButton),(LPARAM)Translate("Check mail"));
	return 0;
}

int UninstallQuestionSvc(WPARAM wParam,LPARAM)
{
//	if(strcmp((char *)wParam,Translate("Yet Another Mail Notifier")))
//		return 0;
	switch(MessageBoxA(NULL,Translate("Do you also want to remove native YAMN plugins settings?"),Translate("YAMN uninstalling"),MB_YESNOCANCEL|MB_ICONQUESTION))
	{
		case IDYES:
			UninstallPlugins=TRUE;
			break;
		case IDNO:
			UninstallPlugins=FALSE;
			break;
		case IDCANCEL:
			return 1;
	}
	return 0;
}