/*
WhenWasIt (birthday reminder) plugin for Miranda IM

Copyright � 2006-2011 Cristian Libotean

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"
#include "hooked_events.h"

#define DATE_CHANGE_CHECK_INTERVAL 20

#define EXCLUDE_HIDDEN  1
#define EXCLUDE_IGNORED 2

#define HOST "http://eblis.tla.ro/projects"


#define WHENWASIT_DATA "WhenWasIt%20unicode"


#if defined(WIN64) || defined(_WIN64)
#define WHENWASIT_VERSION_URL HOST "/miranda/WhenWasIt/updater/x64/WhenWasIt.html"
#define WHENWASIT_UPDATE_URL HOST "/miranda/WhenWasIt/updater/x64/" WHENWASIT_DATA ".zip"
#else
#define WHENWASIT_VERSION_URL HOST "/miranda/WhenWasIt/updater/WhenWasIt.html"
#define WHENWASIT_UPDATE_URL HOST "/miranda/WhenWasIt/updater/" WHENWASIT_DATA ".zip"
#endif
#define WHENWASIT_VERSION_PREFIX "WhenWasIt version "

HANDLE hModulesLoaded;
HANDLE hOptionsInitialize;
HANDLE hIconsChanged;
HANDLE hExtraIconListRebuild;
HANDLE hExtraImageApply;
HANDLE hContactSettingChanged;
HANDLE hTopToolBarModuleLoaded;
//HANDLE hContactSendMessage;

HANDLE hmCheckBirthdays = NULL;
HANDLE hmBirthdayList = NULL;
HANDLE hmRefreshDetails = NULL;
HANDLE hmAddChangeBirthday = NULL;
HANDLE hmImportBirthdays = NULL;
HANDLE hmExportBirthdays = NULL;

UINT_PTR hCheckTimer = NULL;
UINT_PTR hDateChangeTimer = NULL;

int currentDay;

int HookEvents()
{
	Log("%s", "Entering function " __FUNCTION__);
	hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
	hOptionsInitialize = HookEvent(ME_OPT_INITIALISE, OnOptionsInitialise);
	Log("%s", "Leaving function " __FUNCTION__);
	
	return 0;
}

int UnhookEvents()
{
	Log("%s", "Entering function " __FUNCTION__);
	UnhookEvent(hModulesLoaded);
	UnhookEvent(hOptionsInitialize);
	UnhookEvent(hIconsChanged);
	UnhookEvent(hExtraIconListRebuild);
	UnhookEvent(hExtraImageApply);
	UnhookEvent(hContactSettingChanged);
	UnhookEvent(hTopToolBarModuleLoaded);
	
	KillTimers();
	
	Log("%s", "Leaving function " __FUNCTION__);
	
	return 0;
}

int OnModulesLoaded(WPARAM wParam, LPARAM lParam)
{
	hIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, OnIconsChanged);
	hExtraIconListRebuild = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, OnExtraIconListRebuild);
	hExtraImageApply = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, OnExtraImageApply);
	hContactSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, OnContactSettingChanged);
	hTopToolBarModuleLoaded = HookEvent(ME_TTB_MODULELOADED, OnTopToolBarModuleLoaded);
	
	SkinAddNewSoundEx(BIRTHDAY_NEAR_SOUND, LPGEN("WhenWasIt"), LPGEN("Birthday near"));
	SkinAddNewSoundEx(BIRTHDAY_TODAY_SOUND, LPGEN("WhenWasIt"), LPGEN("Birthday today"));
	
	RebuildAdvIconList();
	
	UpdateTimers();
	CLISTMENUITEM cl = {0};
	cl.cbSize = sizeof(CLISTMENUITEM);
	cl.hIcon = hiCheckMenu;
	cl.position = 10000000;
	cl.pszService = MS_WWI_CHECK_BIRTHDAYS;
	cl.pszName = "Check for birthdays";
	cl.pszPopupName = "Birthdays (When Was It)";
	hmCheckBirthdays = Menu_AddMainMenuItem(&cl);
	
	cl.pszService = MS_WWI_LIST_SHOW;
	cl.pszName = "Birthday list";
	cl.hIcon = hiListMenu;
	hmBirthdayList = Menu_AddMainMenuItem(&cl);
	
	cl.pszService = MS_WWI_REFRESH_USERDETAILS;
	cl.position = 10100000;
	cl.pszName = "Refresh user details";
	cl.hIcon = hiRefreshUserDetails;
	hmRefreshDetails = Menu_AddMainMenuItem(&cl);
	
	cl.pszService = MS_WWI_IMPORT_BIRTHDAYS;
	cl.position = 10200000;
	cl.pszName = "Import birthdays";
	cl.hIcon = hiImportBirthdays;
	hmImportBirthdays = Menu_AddMainMenuItem(&cl);
	
	cl.pszService = MS_WWI_EXPORT_BIRTHDAYS;
	cl.pszName = "Export birthdays";
	cl.hIcon = hiExportBirthdays;
	hmExportBirthdays = Menu_AddMainMenuItem(&cl);
	
	cl.pszService = MS_WWI_ADD_BIRTHDAY;
	cl.position = 10000000;
	cl.hIcon = hiAddBirthdayContact;
	cl.pszName = "Add/change user &birthday";
	hmAddChangeBirthday = Menu_AddContactMenuItem(&cl);

	// Register hotkeys
	HOTKEYDESC hotkey = {0};
	hotkey.cbSize = sizeof(hotkey);
	hotkey.pszSection = LPGEN("Birthdays");

	hotkey.pszName = "wwi_birthday_list";
	hotkey.pszDescription = LPGEN("Birthday list");
	hotkey.pszService = MS_WWI_LIST_SHOW;
	Hotkey_Register(&hotkey);
		
	hotkey.pszName = "wwi_check_birthdays";
	hotkey.pszDescription = LPGEN("Check for birthdays");
	hotkey.pszService = MS_WWI_CHECK_BIRTHDAYS;
	Hotkey_Register(&hotkey);
	
	return 0;
}

int OnTopToolBarModuleLoaded(WPARAM wParam, LPARAM lParam)
{
	TTBButton ttb = {0};
	ttb.cbSize = sizeof(ttb);
	ttb.dwFlags = TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP;
	ttb.pszService = MS_WWI_CHECK_BIRTHDAYS;
	ttb.hIconUp = hiCheckMenu;
	ttb.name = ttb.pszTooltipUp = LPGEN("Check for birthdays");
	TopToolbar_AddButton(&ttb);
	return 0;
}

int OnOptionsInitialise(WPARAM wParam, LPARAM lParam)
{
	OPTIONSDIALOGPAGE odp = {0};
	
	odp.cbSize = sizeof(odp);
	odp.position = 100000000;
	odp.hInstance = hInstance;
	odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_WWI);
	odp.pszTitle = LPGEN("When Was It");
	odp.pszGroup = LPGEN("Contact List");
	odp.groupPosition = 910000000;
	odp.flags = ODPF_BOLDGROUPS;
	odp.pfnDlgProc = DlgProcOptions;
	Options_AddPage(wParam, &odp);
	
	return 0;
}

void UpdateMenuItems()
{
	CLISTMENUITEM cl = {0};
	cl.cbSize = sizeof(CLISTMENUITEM);
	cl.flags = CMIM_ICON;
	cl.hIcon = hiCheckMenu;
	int res = CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hmCheckBirthdays, (LPARAM) &cl);
	
	cl.hIcon = hiListMenu;
	res = CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hmBirthdayList, (LPARAM) &cl);
	
	cl.hIcon = hiRefreshUserDetails;
	res = CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hmRefreshDetails, (LPARAM) &cl);
	
	cl.hIcon = hiAddBirthdayContact;
	res = CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hmAddChangeBirthday, (LPARAM) &cl);
	
	cl.hIcon = hiImportBirthdays;
	res = CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hmImportBirthdays, (LPARAM) &cl);
	
	cl.hIcon = hiExportBirthdays;
	res = CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hmExportBirthdays, (LPARAM) &cl);
}

int OnIconsChanged(WPARAM wParam, LPARAM lParam)
{
	GetIcons();
	UpdateMenuItems();
	
	return 0;
}

int OnContactSettingChanged(WPARAM wParam, LPARAM lParam)
{
	DBCONTACTWRITESETTING *dw = (DBCONTACTWRITESETTING *) lParam;
	//static HANDLE oldContact = NULL;
	DBVARIANT dv = dw->value;
	if ((strcmp(dw->szModule, DUMMY_MODULE) == 0) && (strcmp(dw->szSetting, DUMMY_SETTING) == 0))
		{
			OnExtraImageApply(wParam, 0);
		}
	//oldContact = (HANDLE) wParam;
	
	return 0;
}

int OnExtraIconListRebuild(WPARAM wParam, LPARAM lParam)
{
	RebuildAdvIconList();
	
	return 0;
}

int OnExtraImageApply(WPARAM wParam, LPARAM lParam)
{
	HANDLE hContact = (HANDLE) wParam;
	if ((hContact))
		{
			int count = CallService(MS_DB_CONTACT_GETCOUNT, 0, 0);
			//int daysInAdvance = DBGetContactSettingWord(NULL, ModuleName, "DaysInAdvance", DAYS_TO_NOTIFY);
			//int popupTimeout = DBGetContactSettingWord(NULL, ModuleName, "PopupTimeout", POPUP_TIMEOUT);
			//DWORD foreground = DBGetContactSettingDword(NULL, ModuleName, "Foreground", FOREGROUND_COLOR);
			//DWORD background = DBGetContactSettingDword(NULL, ModuleName, "Background", BACKGROUND_COLOR);
			//int bUsePopups = DBGetContactSettingByte(NULL, ModuleName, "UsePopups", TRUE);
			//int bUseClistIcon = DBGetContactSettingByte(NULL, ModuleName, "UseClistIcon", TRUE);
			//int bUseDialog = DBGetContactSettingByte(NULL, ModuleName, "UseDialog", TRUE);
			//int clistIcon = DBGetContactSettingByte(NULL, ModuleName, "AdvancedIcon", CLIST_ICON);
			//int notifyFor = DBGetContactSettingByte(NULL, ModuleName, "NotifyFor", 0);
			int hidden = DBGetContactSettingByte(hContact, "CList", "Hidden", 0);
			int ignored = DBGetContactSettingDword(hContact, "Ignore", "Mask1", 0);
			ignored = ((ignored & 0x3f) != 0) ? 1 : 0;
			int ok = 1;
			if (commonData.notifyFor & EXCLUDE_HIDDEN)
			{
				ok &= (hidden == 0);
			}
			if (commonData.notifyFor & EXCLUDE_IGNORED)
			{
				ok &= (ignored == 0);
			}
		
			int dtb;
			int dab;
			int caps = ServiceExists(MS_CLIST_EXTRA_ADD_ICON); // CallService(MS_CLUI_GETCAPS, 0, 0);
			
			time_t today = Today();
			
			if ((ok) && (((dtb = NotifyContactBirthday(hContact, today, commonData.daysInAdvance)) >= 0) || ((dab = NotifyMissedContactBirthday(hContact, today, commonData.daysAfter)) > 0)))
			{
				int age = GetContactAge(hContact);
				DBWriteContactSettingByte(hContact, "UserInfo", "Age", age);
				
				if ((bShouldCheckBirthdays) && (commonData.bUsePopups))
				{
					if (dtb >= 0)
					{
						bBirthdayFound = 1; //only set it if we're called from our CheckBirthdays service
						PopupNotifyBirthday(hContact, dtb, age);
					}
					else if (dab > 0)
					{
						PopupNotifyMissedBirthday(hContact, dab, age);
					}
				}
					
				if (bShouldCheckBirthdays)
				{
					if (dtb >= 0)
					{
						SoundNotifyBirthday(dtb);
					}
				}
					
				if ((bShouldCheckBirthdays) && (commonData.bUseDialog))
				{
					if (dtb >= 0)
					{
						DialogNotifyBirthday(hContact, dtb, age);
					}
					else if (dab > 0)
					{
						DialogNotifyMissedBirthday(hContact, dab, age);
					}
				}
				
				if ((caps > 0) && (commonData.bUseClistIcon)) //TODO
				{
					if (dtb >= 0)
					{
						ClistIconNotifyBirthday(hContact, dtb, commonData.clistIcon);
					}
				}
			}
			else{
				if (caps > 0) //TODO
				{ //clear the icon
					ClearClistIcon(hContact, commonData.clistIcon);
				}
			}
		}
		
	return 0;
}

int UpdateTimers()
{
	if (hCheckTimer)
		{
			KillTimer(NULL, hCheckTimer);
			hCheckTimer = NULL;
		}
	long interval;
	interval = DBGetContactSettingDword(NULL, ModuleName, "Interval", CHECK_INTERVAL);
	interval *= 1000 * 60 * 60; //go from miliseconds to hours
	hCheckTimer = SetTimer(NULL, 0, interval, (TIMERPROC) OnCheckTimer);
	if (!hDateChangeTimer)
		{
			hDateChangeTimer = SetTimer(NULL, 0, 1000 * DATE_CHANGE_CHECK_INTERVAL, (TIMERPROC) OnDateChangeTimer);
		}
		
	return 0;
}

int KillTimers()
{
	Log("%s", "Entering function " __FUNCTION__);
	if (hCheckTimer)
		{
			KillTimer(NULL, hCheckTimer);
			hCheckTimer = NULL;
		}
	if (hDateChangeTimer)
		{
			KillTimer(NULL, hDateChangeTimer);
			hDateChangeTimer = NULL;
		}
	Log("%s", "Leaving function " __FUNCTION__);
			
	return 0;
}

VOID CALLBACK OnCheckTimer(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime)
{
	Log("%s", "Entering function " __FUNCTION__);
	CheckBirthdaysService(0, 1);
	Log("%s", "Leaving function " __FUNCTION__);
}

VOID CALLBACK OnDateChangeTimer(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime)
{
	SYSTEMTIME now;
	//Log("%s", "Entering function " __FUNCTION__);
	GetLocalTime(&now);
	if (currentDay != now.wDay)
		{
			CheckBirthdaysService(0, 1);
		}
		//else{
		//	RefreshAllContactListIcons();
		//}
	currentDay = now.wDay;
		
	//Log("%s", "Leaving function " __FUNCTION__);
}