/*
astyle --force-indent=tab=4 --brackets=linux --indent-switches
		--pad=oper --one-line=keep-blocks  --unpad=paren

Chat module plugin for Miranda NG

Copyright (C) 2003 J�rgen Persson

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.

Group chat module: contact list support functions. Add chat rooms as
contacts and handle default action for such contacts.

This code was taken in almost unmodified from from the chat.dll
plugin, originally written by J�rgen Persson

*/

/*
 * handles interaction of the group chat implementation with the contact list plugin
 */

#include "..\commonheaders.h"

char *szChatIconString = "chaticon";

static HANDLE Clist_GroupExists(TCHAR *tszGroup)
{
	unsigned int i = 0;
	TCHAR*		 _t = 0;
	char		 str[10];
	INT_PTR		 result = 0;
	DBVARIANT	 dbv = {0};
	int			 match;

	do {
		_itoa(i, str, 10);
		result = M->GetTString(0, "CListGroups", str, &dbv);
		if (!result) {
			match = (!_tcscmp(tszGroup, &dbv.ptszVal[1]) && (lstrlen(tszGroup) == lstrlen(&dbv.ptszVal[1])));
			db_free(&dbv);
			if (match)
				return((HANDLE)(i + 1));
		}
		i++;
	}
	while(result == 0);
	return 0;
}

HANDLE CList_AddRoom(const char* pszModule, const TCHAR* pszRoom, const TCHAR* pszDisplayName, int iType)
{
	HANDLE hContact = CList_FindRoom(pszModule, pszRoom);
	DBVARIANT dbv;
	TCHAR pszGroup[50];

	*pszGroup = '\0';
	if (!M->GetTString(NULL, "Chat", "AddToGroup", &dbv)) {
		if (lstrlen(dbv.ptszVal) > 0)
			lstrcpyn(pszGroup, dbv.ptszVal, 50);
		db_free(&dbv);
	} else
		lstrcpyn(pszGroup, _T("Chat rooms"), 50);

	if (pszGroup[0])
		CList_CreateGroup(pszGroup);

	if (hContact)
		return hContact;

	// here we create a new one since no one is to be found

	if ((hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0)) == NULL)
		return NULL;

	CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)pszModule);
	if (pszGroup && lstrlen(pszGroup) > 0)
		CallService(MS_CLIST_CONTACTCHANGEGROUP, (WPARAM)hContact, (LPARAM)g_Settings.hGroup);
	else
		db_unset(hContact, "CList", "Group");

	M->WriteTString(hContact, pszModule, "Nick", pszDisplayName);
	M->WriteTString(hContact, pszModule, "ChatRoomID", pszRoom);
	M->WriteByte(hContact, pszModule, "ChatRoom", (BYTE)iType);
	db_set_w(hContact, pszModule, "Status", ID_STATUS_OFFLINE);
	return hContact;
}

BOOL CList_SetOffline(HANDLE hContact, BOOL bHide)
{
	if (hContact) {
		char* szProto = GetContactProto(hContact);
		if (szProto == NULL)
			return FALSE;

		int i = M->GetByte(hContact, szProto, "ChatRoom", 0);
		db_set_w(hContact, szProto, "ApparentMode", (LPARAM)0);
		db_set_w(hContact, szProto, "Status", ID_STATUS_OFFLINE);
		return TRUE;
	}
	return FALSE;
}

BOOL CList_SetAllOffline(BOOL bHide, const char *pszModule)
{
	for (HANDLE hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) {
		char *szProto = GetContactProto(hContact);
		if (MM_FindModule(szProto)) {
			if (!pszModule || (pszModule && !strcmp(pszModule, szProto))) {
				int i = M->GetByte(hContact, szProto, "ChatRoom", 0);
				if (i != 0) {
					db_set_w(hContact, szProto, "ApparentMode", (LPARAM)(WORD) 0);
					db_set_w(hContact, szProto, "Status", ID_STATUS_OFFLINE);
				}
			}
		}
	}
	return TRUE;
}

int CList_RoomDoubleclicked(WPARAM wParam, LPARAM lParam)
{
	DBVARIANT dbv;
	char *szProto;
	BOOL bRedrawFlag = FALSE;
	bool fCreate = false;

	HANDLE hContact = (HANDLE)wParam;
	if (!hContact)
		return 0;

	szProto = GetContactProto(hContact);
	if (MM_FindModule(szProto)) {
		if (M->GetByte(hContact, szProto, "ChatRoom", 0) == 0)
			return 0;

		if (!M->GetTString(hContact, szProto, "ChatRoomID", &dbv)) {
			SESSION_INFO* si = SM_FindSession(dbv.ptszVal, szProto);
			if (si) {
				// is the "toggle visibility option set, so we need to close the window?
				if (si->hWnd != NULL
						&& M->GetByte("Chat", "ToggleVisibility", 0) == 1
						&& !CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, 0)
						&& IsWindowVisible(si->hWnd)
						&& !IsIconic(si->pContainer->hwnd)) {
					PostMessage(si->hWnd, GC_CLOSEWINDOW, 0, 0);
					db_free(&dbv);
					return 1;
				}
				else
					fCreate = true;

				ShowRoom(si, WINDOW_VISIBLE, TRUE);
				if (lParam && fCreate) {
					SendMessage(si->hWnd, DM_ACTIVATEME, 0, 0);
					if (si->dat)
						SetForegroundWindow(si->dat->pContainer->hwnd);
				}
			}
			db_free(&dbv);
			return 1;
		}
	}

	return 0;
}

INT_PTR CList_EventDoubleclicked(WPARAM wParam, LPARAM lParam)
{
	return CList_RoomDoubleclicked((WPARAM)((CLISTEVENT*)lParam)->hContact, (LPARAM)0);
}

INT_PTR CList_JoinChat(WPARAM wParam, LPARAM lParam)
{
	HANDLE hContact = (HANDLE)wParam;
	if ( hContact ) {
		char* szProto = GetContactProto(hContact);
		if ( szProto ) {
			if ( db_get_w( hContact, szProto, "Status", 0 ) == ID_STATUS_OFFLINE )
				CallProtoService( szProto, PS_JOINCHAT, wParam, lParam );
			else
				CList_RoomDoubleclicked( wParam, 0 );
	}	}

	return 0;
}

INT_PTR CList_LeaveChat(WPARAM wParam, LPARAM lParam)
{
	HANDLE hContact = (HANDLE)wParam;
	if ( hContact ) {
		char* szProto = GetContactProto(hContact);
		if ( szProto )
			CallProtoService( szProto, PS_LEAVECHAT, wParam, lParam );
	}
	return 0;
}

int CList_PrebuildContactMenu(WPARAM wParam, LPARAM lParam)
{
	HANDLE hContact = (HANDLE)wParam;
	if (hContact == NULL)
		return 0;

	bool bEnabled = false;
	char *szProto = GetContactProto(hContact);
	if ( szProto ) {
		// display this menu item only for chats
		if ( M->GetByte(hContact, szProto, "ChatRoom", 0 )) {
			// still hide it for offline protos
			if (CallProtoService( szProto, PS_GETSTATUS, 0, 0 ) != ID_STATUS_OFFLINE) {
				CLISTMENUITEM clmi = { sizeof(clmi) };
				clmi.flags = CMIM_NAME;
				if (db_get_w( hContact, szProto, "Status", 0 ) == ID_STATUS_OFFLINE)
					clmi.pszName = (char*)LPGEN("Join chat");
				else
					clmi.pszName = (char*)LPGEN("Open chat window");
				Menu_ModifyItem(hJoinMenuItem, &clmi);
				bEnabled = true;
	}	}	}

	Menu_ShowItem(hJoinMenuItem, bEnabled);
	Menu_ShowItem(hLeaveMenuItem, bEnabled);
	return 0;
}

INT_PTR CList_PrebuildContactMenuSvc(WPARAM wParam, LPARAM lParam)
{
	return CList_PrebuildContactMenu(wParam, lParam);
}

void CList_CreateGroup(TCHAR* group)
{
	if (!group)
		return;

	g_Settings.hGroup = Clist_GroupExists(group);

	if (g_Settings.hGroup == 0) {
		g_Settings.hGroup = (HANDLE)CallService(MS_CLIST_GROUPCREATE, 0, (LPARAM)group);

		if (g_Settings.hGroup) {
			CallService(MS_CLUI_GROUPADDED, (WPARAM)g_Settings.hGroup, 0);
			CallService(MS_CLIST_GROUPSETEXPANDED, (WPARAM)g_Settings.hGroup, 1);
		}
	}
}

BOOL CList_AddEvent(HANDLE hContact, HICON Icon, HANDLE event, int type, const TCHAR* fmt, ...)
{
	CLISTEVENT cle;
	va_list marker;
	TCHAR* szBuf = (TCHAR*)alloca(4096 * sizeof(TCHAR));

	if (!fmt || lstrlen(fmt) < 1 || lstrlen(fmt) > 2000)
		return FALSE;

	va_start(marker, fmt);
	_vstprintf(szBuf, fmt, marker);
	va_end(marker);

	cle.cbSize = sizeof(cle);
	cle.hContact = (HANDLE)hContact;
	cle.hDbEvent = (HANDLE)event;
	cle.flags = type + CLEF_TCHAR;
	cle.hIcon = Icon;
	cle.pszService = "GChat/DblClickEvent" ;
	cle.ptszTooltip = TranslateTS(szBuf);
	if (type) {
		if (!CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, 0))
			CallService(MS_CLIST_ADDEVENT, (WPARAM)hContact, (LPARAM)&cle);
	} else {
		if (CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, 0))
			CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)"chaticon");
		CallService(MS_CLIST_ADDEVENT, (WPARAM)hContact, (LPARAM)&cle);
	}
	return TRUE;
}

HANDLE CList_FindRoom(const char* pszModule, const TCHAR* pszRoom)
{
	for (HANDLE hContact = db_find_first(pszModule); hContact; hContact = db_find_next(hContact, pszModule)) {
		if ( !M->GetByte(hContact, pszModule, "ChatRoom", 0))
			continue;

		DBVARIANT dbv;
		if (!M->GetTString(hContact, pszModule, "ChatRoomID", &dbv)) {
			if (!lstrcmpi(dbv.ptszVal, pszRoom)) {
				db_free(&dbv);
				return hContact;
			}
			db_free(&dbv);
		}
	}
	return 0;
}