/**********************************************************************
 * LeechCraft - modular cross-platform feature rich internet client.
 * Copyright (C) 2006-2014  Georg Rudoy
 *
 * Boost Software License - Version 1.0 - August 17th, 2003
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **********************************************************************/

#include "xep0232handler.h"
#include <algorithm>
#include <QtDebug>
#include <QXmppDataForm.h>

namespace LeechCraft
{
namespace Azoth
{
namespace Xoox
{
namespace XEP0232Handler
{
	const QString SWInfoFormType = "urn:xmpp:dataforms:softwareinfo";

	bool SoftwareInformation::IsNull () const
	{
		return OS_.isEmpty () && OSVer_.isEmpty () &&
				Software_.isEmpty () && SoftwareVer_.isEmpty ();
	}

	SoftwareInformation FromDataForm (const QXmppDataForm& form)
	{
		if (form.isNull ())
			return SoftwareInformation ();

		const auto& fields = form.fields ();
		auto pos = std::find_if (fields.begin (), fields.end (),
				[] (decltype (fields.front ()) field) { return field.key () == "FORM_TYPE"; });
		if (pos == fields.end ())
		{
			qWarning () << Q_FUNC_INFO
					<< "no FORM_TYPE"
					<< form.title ();
			return SoftwareInformation ();
		}

		if (pos->value () != SWInfoFormType)
			return SoftwareInformation ();

		SoftwareInformation si;
		Q_FOREACH (const QXmppDataForm::Field& f, fields)
		{
			const auto& var = f.key ();
			if (var == "icon")
			{
				const auto& media = f.media ();
				si.IconWidth_ = media.width ();
				si.IconHeight_ = media.height ();
				Q_FOREACH (const auto& pair, media.uris ())
					if (pair.second.startsWith ("http"))
					{
						si.IconURL_ = QUrl::fromEncoded (pair.second.toLatin1 ());
						si.IconType_ = pair.first;
					}
					else if (pair.second.startsWith ("cid"))
						si.IconCID_ = pair.second;
			}
			else if (var == "os")
				si.OS_ = f.value ().toString ();
			else if (var == "os_version")
				si.OSVer_ = f.value ().toString ();
			else if (var == "software")
				si.Software_ = f.value ().toString ();
			else if (var == "software_version")
				si.SoftwareVer_ = f.value ().toString ();
			else if (var != "FORM_TYPE")
				qWarning () << Q_FUNC_INFO
						<< "unknown field"
						<< var
						<< f.value ();
		}
		return si;
	}

	QXmppDataForm ToDataForm (const SoftwareInformation& si)
	{
		QList<QXmppDataForm::Field> fields;

		QXmppDataForm::Field typeField (QXmppDataForm::Field::HiddenField);
		typeField.setKey ("FORM_TYPE");
		typeField.setValue (SWInfoFormType);
		fields << typeField;

		if (si.IconURL_.isValid ())
		{
			QXmppDataForm::Field iconField;
			iconField.setKey ("icon");
			QXmppDataForm::Media media;
			media.setWidth (si.IconHeight_);
			media.setHeight (si.IconWidth_);
			QList<QPair<QString, QString>> uris;
			if (!si.IconCID_.isEmpty ())
				uris << qMakePair (si.IconType_, si.IconCID_);
			uris << qMakePair (si.IconType_, QString (si.IconURL_.toEncoded ()));
			media.setUris (uris);
			iconField.setMedia (media);
			iconField.setValue (si.IconURL_.toEncoded ());

			fields << iconField;
		}

		auto setStr = [&fields] (const QString& key, const QString& val)
		{
			if (!val.isEmpty ())
			{
				QXmppDataForm::Field field;
				field.setKey (key);
				field.setValue (val);
				fields << field;
			}
		};
		setStr ("os", si.OS_);
		setStr ("os_version", si.OSVer_);
		setStr ("software", si.Software_);
		setStr ("software_version", si.SoftwareVer_);

		QXmppDataForm form (QXmppDataForm::Result);
		form.setFields (fields);
		return form;
	}
}
}
}
}
