/*

Jabber Protocol Plugin for Miranda NG

Copyright (c) 2002-04 Santithorn Bunchua
Copyright (c) 2005-12 George Hazan
Copyright (c) 2007    Maxim Mluhov
Copyright (C) 2012-24 Miranda NG team

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 "stdafx.h"
#include "jabber_iq.h"
#include "jabber_caps.h"

void CJabberProto::OnIqResultMamInfo(const TiXmlElement *iqNode, CJabberIqInfo *pInfo)
{
	if (pInfo->GetIqType() == JABBER_IQ_TYPE_RESULT) {
		if (auto *n = XmlFirstChild(iqNode, "prefs")) {
			m_bMamPrefsAvailable = true;

			if (auto *type = n->Attribute("default")) {
				if (!strcmp(type, "never"))
					m_iMamMode = 0;
				else if (!strcmp(type, "roster"))
					m_iMamMode = 1;
				else
					m_iMamMode = 2;
			}
		}
	}

	// shall we retrieve missing messages?
	if (pInfo->GetUserData())
		MamRetrieveMissingMessages();
}

void CJabberProto::MamSetMode(int iNewMode)
{
	if (!m_bEnableMam)
		return;

	const char *szMode;
	switch (iNewMode) {
	case 0:  szMode = "never"; break;
	case 1:  szMode = "roster"; break;
	default: szMode = "always"; break;
	}

	XmlNodeIq iq(AddIQ(&CJabberProto::OnIqResultMamInfo, JABBER_IQ_TYPE_SET));
	auto *node = iq << XCHILDNS("prefs", JABBER_FEAT_MAM) << XATTR("default", szMode);
	node << XCHILD("always"); node << XCHILD("never");
	m_ThreadInfo->send(iq);
}

/////////////////////////////////////////////////////////////////////////////////////////

void CJabberProto::MamRetrieveMissingMessages()
{
	CMStringA szLastId = getMStringA("LastMamId");

	XmlNodeIq iq("set", SerialNext());
	auto *query = iq << XCHILDNS("query", JABBER_FEAT_MAM);

	if (szLastId.IsEmpty()) {
		m_bMamDisableMessages = true; // our goal is to save message id, not to store messages
		m_bMamCreateRead = false;

		char buf[100];
		time2str(time(0), buf, _countof(buf));

		auto *form = query << XCHILDNS("x", JABBER_FEAT_DATA_FORMS) << XATTR("type", "submit");
		form << XCHILD("field") << XATTR("var", "FORM_TYPE") << XATTR("type", "hidden") << XCHILD("value", JABBER_FEAT_MAM);
		form << XCHILD("field") << XATTR("var", "end") << XCHILD("value", buf);
	}
	else {
		auto *set = query << XCHILDNS("set", "http://jabber.org/protocol/rsm");
		set << XCHILD("max", "1000");
		set << XCHILD("after", szLastId);
	}
	
	m_ThreadInfo->send(iq);
}

/////////////////////////////////////////////////////////////////////////////////////////
// Contact's history loader

void CJabberProto::MamSendForm(const char *pszWith, const char *pszAfter)
{
	auto *pReq = AddIQ(&CJabberProto::OnIqResultRsm, JABBER_IQ_TYPE_SET);
	pReq->SetParamsToParse(JABBER_IQ_PARSE_FROM);

	XmlNodeIq iq(pReq);
	auto *query = iq << XCHILDNS("query", JABBER_FEAT_MAM);

	auto *form = query << XCHILDNS("x", JABBER_FEAT_DATA_FORMS) << XATTR("type", "submit");
	form << XCHILD("field") << XATTR("var", "FORM_TYPE") << XATTR("type", "hidden") << XCHILD("value", JABBER_FEAT_MAM);
	if (pszWith != nullptr)
		form << XCHILD("field") << XATTR("var", "with") << XCHILD("value", pszWith);

	auto *rsm = query << XCHILDNS("set", "http://jabber.org/protocol/rsm");
	rsm << XCHILD("max", "1000");
	if (pszAfter != nullptr)
		rsm << XCHILD("after", pszAfter);
	m_ThreadInfo->send(iq);
}


void CJabberProto::OnIqResultRsm(const TiXmlElement *iqNode, CJabberIqInfo *pInfo)
{
	// even if that flag was enabled, unset it
	m_bMamDisableMessages = false;

	if (auto *fin = XmlGetChildByTag(iqNode, "fin", "xmlns", JABBER_FEAT_MAM)) {
		// if dataset is complete, there's nothing more to do
		if (!mir_strcmp(XmlGetAttr(fin, "complete"), "true"))
			return;

		if (auto *set = XmlGetChildByTag(fin, "set", "xmlns", "http://jabber.org/protocol/rsm"))
			if (auto *lastId = XmlGetChildText(set, "last"))
				MamSendForm(ptrA(getUStringA(pInfo->GetHContact(), "jid")), lastId);
	}
}

INT_PTR __cdecl CJabberProto::OnMenuLoadHistory(WPARAM hContact, LPARAM)
{
	if (hContact == 0 || !m_bEnableMam)
		return 0;

	// wipe out old history first
	if (IDYES == MessageBoxW(NULL, TranslateT("Do you want to erase local history before loading it from server?"), m_tszUserName, MB_YESNOCANCEL | MB_ICONQUESTION)) {
		DB::ECPTR pCursor(DB::Events(hContact));
		while (pCursor.FetchNext())
			pCursor.DeleteEvent();
	}

	// load remaining items from server
	if (m_bJabberOnline) {
		ptrA jid(getUStringA(hContact, "jid"));
		if (jid != nullptr) {
			m_bMamCreateRead = true;
			MamSendForm(jid);
		}
	}
	return 0;
}