/*
Copyright (C) 2012-23 Miranda NG team (https://miranda-ng.org)
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 version 2
of the License.
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 "stdafx.h"
void CTelegramProto::InitGroupChat(TG_USER *pUser, const TD::chat *pChat)
{
	if (pUser->m_si)
		return;
		
	wchar_t wszId[100];
	_i64tow(pUser->id, wszId, 10);
	SESSION_INFO *si;
	Utf2T wszNick(pChat->title_.c_str());
	if (pUser->bLoadMembers) {
		si = Chat_NewSession(GCW_CHATROOM, m_szModuleName, wszId, wszNick, pUser);
		if (!si->pStatuses) {
			Chat_AddGroup(si, TranslateT("Creator"));
			Chat_AddGroup(si, TranslateT("Admin"));
			Chat_AddGroup(si, TranslateT("Participant"));
			// push async query to fetch users
			if (m_arBasicGroups.find((TG_BASIC_GROUP*)&pUser->id))
				SendQuery(new TD::getBasicGroupFullInfo(pUser->id), &CTelegramProto::StartGroupChat, pUser);
			else
				SendQuery(new TD::getSupergroupMembers(pUser->id, 0, 0, 100), &CTelegramProto::StartGroupChat, pUser);
		}
		else {
			Chat_Control(si, m_bHideGroupchats ? WINDOW_HIDDEN : SESSION_INITDONE);
			Chat_Control(si, SESSION_ONLINE);
		}
	}
	else {
		if (si = Chat_NewSession(GCW_CHANNEL, m_szModuleName, wszId, wszNick, pUser)) {
			if (!si->pStatuses) {
				Chat_AddGroup(si, TranslateT("SuperAdmin"));
				Chat_AddGroup(si, TranslateT("Visitor"));
				ptrW wszMyId(getWStringA(DBKEY_ID)), wszMyNick(Contact::GetInfo(CNF_DISPLAY, 0, m_szModuleName));
				GCEVENT gce = { si, GC_EVENT_JOIN };
				gce.pszUID.w = wszMyId;
				gce.pszNick.w = wszMyNick;
				gce.bIsMe = true;
				gce.pszStatus.w = TranslateT("Visitor");
				Chat_Event(&gce);
				gce.bIsMe = false;
				gce.pszUID.w = wszId;
				gce.pszNick.w = wszNick;
				gce.pszStatus.w = TranslateT("SuperAdmin");
				Chat_Event(&gce);
			}
			Chat_Control(si, m_bHideGroupchats ? WINDOW_HIDDEN : SESSION_INITDONE);
			Chat_Control(si, SESSION_ONLINE);
		}
	}
	
	pUser->m_si = si;
}
void CTelegramProto::StartGroupChat(td::ClientManager::Response &response, void *pUserData)
{
	if (!response.object)
		return;
	TD::array> *pMembers;
	switch (response.object->get_id()) {
	case TD::basicGroupFullInfo::ID:
		pMembers = &((TD::basicGroupFullInfo *)response.object.get())->members_;
		break;
	case TD::chatMembers::ID:
		pMembers = &((TD::chatMembers *)response.object.get())->members_;
		break;
	default:
		debugLogA("Gotten class ID %d instead of %d, exiting", response.object->get_id(), TD::basicGroupFullInfo::ID);
		return;
	}
	auto *pUser = (TG_USER *)pUserData;
	for (auto &it : *pMembers) {
		auto *pMember = it.get();
		const wchar_t *pwszRole;
		switch (pMember->status_->get_id()) {
		case TD::chatMemberStatusCreator::ID:
			pwszRole = TranslateT("Creator");
			break;
		case TD::chatMemberStatusAdministrator::ID:
			pwszRole = TranslateT("Admin");
			break;
		case TD::chatMemberStatusMember::ID:
		default:
			pwszRole = TranslateT("Participant");
			break;
		}
		if (pMember->member_id_->get_id() != TD::messageSenderUser::ID)
			continue;
		int64_t memberId = ((TD::messageSenderUser *)pMember->member_id_.get())->user_id_;
		auto *pChatUser = FindUser(memberId);
		if (pChatUser == nullptr)
			continue;
		wchar_t wszUserId[100];
		_i64tow(memberId, wszUserId, 10);
		GCEVENT gce = { pUser->m_si, GC_EVENT_JOIN };
		gce.pszUID.w = wszUserId;
		gce.pszStatus.w = pwszRole;
		switch (pChatUser->hContact) {
		case 0:
			gce.bIsMe = true;
			__fallthrough;
		case INVALID_CONTACT_ID:
			gce.pszNick.w = pChatUser->wszNick.c_str();
			break;
		default:
			gce.pszNick.w = Clist_GetContactDisplayName(pChatUser->hContact);
			break;
		}
		Chat_Event(&gce);
	}
	Chat_Control(pUser->m_si, m_bHideGroupchats ? WINDOW_HIDDEN : SESSION_INITDONE);
	Chat_Control(pUser->m_si, SESSION_ONLINE);
}
/////////////////////////////////////////////////////////////////////////////////////////
int CTelegramProto::GcMuteHook(WPARAM hContact, LPARAM mode)
{
	if (Proto_IsProtoOnContact(hContact, m_szModuleName)) {
		if (auto *pUser = FindUser(GetId(hContact))) {
			auto settings = TD::make_object();
			memcpy(settings.get(), &pUser->notificationSettings, sizeof(pUser->notificationSettings));
			switch (mode) {
			case CHATMODE_MUTE:
				settings->use_default_mute_for_ = false;
				settings->mute_for_ = 45000000;
				break;
			default:
				settings->use_default_mute_for_ = true;
				settings->mute_for_ = 0;
				break;
			}
			SendQuery(new TD::setChatNotificationSettings(pUser->chatId, std::move(settings)));
		}
	}
	return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////
enum
{
	IDM_LEAVE = 1,
};
int CTelegramProto::GcEventHook(WPARAM, LPARAM lParam)
{
	GCHOOK *gch = (GCHOOK *)lParam;
	if (gch == nullptr)
		return 0;
	if (mir_strcmpi(gch->si->pszModule, m_szModuleName))
		return 0;
	auto userId = _wtoi64(gch->si->ptszID);
	switch (gch->iType) {
	case GC_USER_MESSAGE:
		if (gch->ptszText && mir_wstrlen(gch->ptszText) > 0) {
			rtrimw(gch->ptszText);
			Chat_UnescapeTags(gch->ptszText);
			SendTextMessage(-userId, T2Utf(gch->ptszText));
		}
		break;
	case GC_USER_PRIVMESS:
		Chat_SendPrivateMessage(gch);
		break;
	case GC_USER_LOGMENU:
		Chat_LogMenu(gch);
		break;
	case GC_USER_NICKLISTMENU:
		break;
	}
	return 1;
}
void CTelegramProto::Chat_LogMenu(GCHOOK *gch)
{
	switch (gch->dwData) {
	case IDM_LEAVE:
		int64_t id = GetId(gch->si->hContact);
		if (auto *pUser = FindUser(id)) {
			pUser->m_si = nullptr;
			SendQuery(new TD::leaveChat(pUser->chatId));
		}
		Chat_Terminate(gch->si);
		Contact::Hide(gch->si->hContact);
		Contact::RemoveFromList(gch->si->hContact);
		break;
	}
}
void CTelegramProto::Chat_SendPrivateMessage(GCHOOK *gch)
{
	MCONTACT hContact;
	TD::int53 userId = _wtoi64(gch->ptszUID);
	auto *pUser = FindUser(userId);
	if (pUser == nullptr || pUser->hContact == INVALID_CONTACT_ID) {
		PROTOSEARCHRESULT psr = { sizeof(psr) };
		psr.id.w = (wchar_t *)gch->ptszUID;
		psr.firstName.w = (wchar_t *)gch->ptszNick;
		hContact = AddToList(PALF_TEMPORARY, &psr);
		if (hContact == 0)
			return;
		setWString(hContact, "Nick", gch->ptszNick);
		Contact::Hide(hContact);
		db_set_dw(hContact, "Ignore", "Mask1", 0);
	}
	else hContact = pUser->hContact;
	CallService(MS_MSG_SENDMESSAGE, hContact, 0);
}
/////////////////////////////////////////////////////////////////////////////////////////
static gc_item sttLogListItems[] =
{
	{ LPGENW("&Leave chat session"), IDM_LEAVE, MENU_ITEM }
};
int CTelegramProto::GcMenuHook(WPARAM, LPARAM lParam)
{
	GCMENUITEMS *gcmi = (GCMENUITEMS *)lParam;
	if (gcmi == nullptr)
		return 0;
	if (mir_strcmpi(gcmi->pszModule, m_szModuleName))
		return 0;
	auto *pUser = FindUser(_wtoi64(gcmi->pszID));
	if (pUser == nullptr)
		return 0;
	if (gcmi->Type == MENU_ON_LOG) {
		Chat_AddMenuItems(gcmi->hMenu, _countof(sttLogListItems), sttLogListItems, &g_plugin);
	}
	else if (gcmi->Type == MENU_ON_NICKLIST) {
	}
	return 0;
}