/*
Copyright © 2009 Jim Porter
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,  see .
*/
#include "common.h"
#include "proto.h"
#include 
#include 
void TwitterProto::UpdateChat(const twitter_user &update)
{
	GCDEST gcd = { m_szModuleName };
	gcd.ptszID = const_cast(m_tszUserName);
	gcd.iType  = GC_EVENT_MESSAGE;
	GCEVENT gce  = {sizeof(gce)};
	gce.pDest    = &gcd;
	gce.dwFlags  = GC_TCHAR|GCEF_ADDTOLOG;
	gce.pDest    = &gcd;
	gce.ptszUID  = mir_a2t( update.username.c_str());
	gce.bIsMe    = (update.username == twit_.get_username());
	gce.ptszText = ( TCHAR* )update.status.text.c_str();
	gce.time     = static_cast(update.status.time);
	DBVARIANT nick;
	HANDLE hContact = UsernameToHContact( _A2T(update.username.c_str()));
	if (hContact && !DBGetContactSettingTString(hContact, "CList", "MyHandle", &nick)) {
		gce.ptszNick = mir_tstrdup( nick.ptszVal );
		DBFreeVariant(&nick);
	}
	else gce.ptszNick = mir_a2t( update.username.c_str());
	CallServiceSync(MS_GC_EVENT, 0, reinterpret_cast(&gce));
	mir_free(const_cast(gce.ptszNick));
	mir_free(const_cast(gce.ptszUID));
	mir_free(const_cast(gce.ptszText));
}
int TwitterProto::OnChatOutgoing(WPARAM wParam, LPARAM lParam)
{
	GCHOOK *hook = reinterpret_cast(lParam);
	if (strcmp(hook->pDest->pszModule, m_szModuleName))
		return 0;
	TCHAR *text;
	switch(hook->pDest->iType) {
	case GC_USER_MESSAGE:
		text = mir_tstrdup(hook->ptszText);
		ForkThread(&TwitterProto::SendTweetWorker, this, text);
		break;
	
	case GC_USER_PRIVMESS:
		text = mir_tstrdup(hook->ptszUID);
		CallService(MS_MSG_SENDMESSAGE, reinterpret_cast( UsernameToHContact(text)), 0);
		mir_free(text);
		break;
	}
	return 0;
}
// TODO: remove nick?
void TwitterProto::AddChatContact(const TCHAR *name, const TCHAR *nick)
{
	GCDEST gcd = { m_szModuleName };
	gcd.ptszID = const_cast(m_tszUserName);
	gcd.iType  = GC_EVENT_JOIN;
	GCEVENT gce    = {sizeof(gce)};
	gce.pDest      = &gcd;
	gce.dwFlags    = GC_TCHAR;
	gce.ptszNick   = nick ? nick:name;
	gce.ptszUID    = name;
	gce.bIsMe      = false;
	gce.ptszStatus = _T("Normal");
	gce.time       = static_cast(time(0));
	CallServiceSync(MS_GC_EVENT, 0, reinterpret_cast(&gce));
}
void TwitterProto::DeleteChatContact(const TCHAR *name)
{
	GCDEST gcd = { m_szModuleName };
	gcd.ptszID = const_cast(m_tszUserName);
	gcd.iType  = GC_EVENT_PART;
	GCEVENT gce    = {sizeof(gce)};
	gce.pDest      = &gcd;
	gce.dwFlags    = GC_TCHAR;
	gce.ptszNick   = name;
	gce.ptszUID    = gce.ptszNick;
	gce.time       = static_cast(time(0));
	CallServiceSync(MS_GC_EVENT, 0, reinterpret_cast(&gce));
	mir_free(const_cast(gce.ptszNick));
}
int TwitterProto::OnJoinChat(WPARAM, LPARAM suppress)
{
	GCSESSION gcw = {sizeof(gcw)};
	// ***** Create the group chat session
	gcw.dwFlags   = GC_TCHAR;
	gcw.iType     = GCW_CHATROOM;
	gcw.pszModule = m_szModuleName;
	gcw.ptszName  = m_tszUserName;
	gcw.ptszID    = m_tszUserName;
	CallServiceSync(MS_GC_NEWSESSION,  0,  (LPARAM)&gcw);
	if (m_iStatus != ID_STATUS_ONLINE)
		return 0;
	// ***** Create a group
	GCDEST gcd = { m_szModuleName };
	gcd.ptszID = const_cast(m_tszUserName);
	GCEVENT gce = {sizeof(gce)};
	gce.pDest = &gcd;
	gce.dwFlags = GC_TCHAR;
	gcd.iType = GC_EVENT_ADDGROUP;
	gce.ptszStatus = _T("Normal");
	CallServiceSync(MS_GC_EVENT, 0, reinterpret_cast(&gce));
	// ***** Hook events
	HookProtoEvent(ME_GC_EVENT, &TwitterProto::OnChatOutgoing, this);
	// Note: Initialization will finish up in SetChatStatus,  called separately
	if (!suppress)
		SetChatStatus(m_iStatus);
	in_chat_ = true;
	return 0;
}
int TwitterProto::OnLeaveChat(WPARAM, LPARAM)
{
	in_chat_ = false;
	GCDEST gcd = { m_szModuleName };
	gcd.ptszID = const_cast(m_tszUserName);
	gcd.iType = GC_EVENT_CONTROL;
	GCEVENT gce = {sizeof(gce)};
	gce.dwFlags = GC_TCHAR;
	gce.pDest = &gcd;
	CallServiceSync(MS_GC_EVENT, SESSION_OFFLINE,   reinterpret_cast(&gce));
	CallServiceSync(MS_GC_EVENT, SESSION_TERMINATE, reinterpret_cast(&gce));
	return 0;
}
void TwitterProto::SetChatStatus(int status)
{
	GCDEST gcd = { m_szModuleName };
	gcd.ptszID = const_cast(m_tszUserName);
	gcd.iType = GC_EVENT_CONTROL;
	GCEVENT gce = {sizeof(gce)};
	gce.dwFlags = GC_TCHAR;
	gce.pDest = &gcd;
	if (status == ID_STATUS_ONLINE) {
		// Add all friends to contact list
		for(HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
			hContact;
			hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
		{
			if (!IsMyContact(hContact))
				continue;
			DBVARIANT uid, nick;
			if ( DBGetContactSettingTString(hContact, m_szModuleName, TWITTER_KEY_UN, &uid))
				continue;
			if ( !DBGetContactSettingTString(hContact, "CList", "MyHandle", &nick))
				AddChatContact(uid.ptszVal, nick.ptszVal);
			else
				AddChatContact(uid.ptszVal);
			DBFreeVariant(&nick);
			DBFreeVariant(&uid);
		}
		// For some reason,  I have to send an INITDONE message,  even if I'm not actually
		// initializing the room...
		CallServiceSync(MS_GC_EVENT, SESSION_INITDONE, reinterpret_cast(&gce));
		CallServiceSync(MS_GC_EVENT, SESSION_ONLINE,   reinterpret_cast(&gce));
	}
	else CallServiceSync(MS_GC_EVENT, SESSION_OFFLINE, reinterpret_cast(&gce));
}