/**********************************************************************
 * 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 "psiplusimportpage.h"
#include <QDir>
#include <QStandardItemModel>
#include <QDomElement>
#include <QDateTime>
#include <QtDebug>
#include <util/xpc/util.h>
#include "importwizard.h"
#include "imhistimporterbase.h"

namespace LeechCraft
{
namespace NewLife
{
namespace Importers
{
	PsiPlusImportPage::PsiPlusImportPage (QWidget *parent)
	: Common::IMImportPage (parent)
	{
		auto tfd = [] (const QDomElement& account, const QString& field)
			{ return account.firstChildElement (field).text (); };

		auto adapter = Common::XMLIMAccount::ConfigAdapter
		{
			AccountsModel_,
			QStringList (".config") << "Psi+" << "profiles",
			"accounts.xml",
			[] (const QDomElement&) { return "xmpp"; },
			[=] (const QDomElement& acc) { return tfd (acc, "name"); },
			[=] (const QDomElement& acc) { return tfd (acc, "enabled") == "true"; },
			[=] (const QDomElement& acc) { return tfd (acc, "jid"); },
			[=] (const QDomElement& acc, QVariantMap& accountData)
			{
				accountData ["Port"] = tfd (acc, "port").toInt ();
				accountData ["Host"] = tfd (acc, "use-host") == "true" ?
						tfd (acc, "host") :
						QString ();

				QStringList jids;

				auto rosterItem = acc.firstChildElement ("roster-cache").firstChildElement ();
				while (!rosterItem.isNull ())
				{
					const QString& jid = rosterItem.firstChildElement ("jid").text ();
					if (!jid.isEmpty ())
						jids << jid;
					rosterItem = rosterItem.nextSiblingElement ();
				}
				accountData ["Contacts"] = jids;
			}
		};
		XIA_.reset (new Common::XMLIMAccount (adapter));
	}

	void PsiPlusImportPage::FindAccounts ()
	{
		XIA_->FindAccounts ();
		Ui_.AccountsTree_->expandAll ();
	}

	void PsiPlusImportPage::SendImportAcc (QStandardItem *accItem)
	{
		Entity e = Util::MakeEntity (QVariant (),
				QString (),
				FromUserInitiated | OnlyHandle,
				"x-leechcraft/im-account-import");

		QVariantMap data = accItem->data (Roles::AccountData).toMap ();
		data.remove ("Contacts");
		e.Additional_ ["AccountData"] = data;

		emit gotEntity (e);
	}

	namespace
	{
		class HistImporter : public IMHistImporterBase
		{
			QString Profile_;
			QString AccName_;
			QString AccID_;
			QStringList JIDs_;
			QString CurrentJID_;

			QFile CurrentFile_;
		public:
			HistImporter (const QString& profile,
					const QString& accName, const QString& accId,
					const QStringList& jids, QObject *parent = 0)
			: IMHistImporterBase (parent)
			, Profile_ (profile)
			, AccName_ (accName)
			, AccID_ (accId)
			, JIDs_ (jids)
			{
			}
		protected:
			Entity GetEntityChunk ()
			{
				Entity e;
				if (JIDs_.isEmpty ())
					return e;

				const int lim = 1000;

				int counter = 0;
				QVariantList list;

				if (!OpenNextFile ())
					return e;

				while (CurrentFile_.isOpen ())
				{
					while (true)
					{
						if (CurrentFile_.atEnd ())
						{
							CurrentFile_.close ();
							break;
						}

						try
						{
							const auto& var = ParseLine (QString::fromUtf8 (CurrentFile_.readLine ()));
							if (!var.isNull ())
							{
								list << var;
								if (++counter > lim)
									break;
							}
						}
						catch (const std::exception& e)
						{
							qWarning () << Q_FUNC_INFO
									<< "error parsing line"
									<< e.what ();
						}
					}

					if (counter > lim)
						break;

					if (!CurrentFile_.isOpen () || CurrentFile_.atEnd ())
					{
						CurrentFile_.close ();

						if (!OpenNextFile ())
							break;
					}
				}

				if (counter)
				{
					e.Additional_ ["History"] = list;
					e.Mime_ = "x-leechcraft/im-history-import";
					e.Additional_ ["AccountName"] = AccName_;
					e.Additional_ ["AccountID"] = AccID_;
					e.Parameters_ = OnlyHandle | FromUserInitiated;
				}

				return e;
			}
		private:
			bool OpenNextFile ()
			{
				while (!CurrentFile_.isOpen ())
				{
					if (JIDs_.isEmpty ())
						return false;

					CurrentJID_ = JIDs_.takeFirst ();
					CurrentFile_.setFileName (GetFileName (CurrentJID_));
					if (!CurrentFile_.exists ())
						continue;

					if (!CurrentFile_.open (QIODevice::ReadOnly))
					{
						qWarning () << Q_FUNC_INFO
								<< "cannot open"
								<< CurrentFile_.fileName ()
								<< CurrentFile_.errorString ();
						continue;
					}

					if (JIDs_.isEmpty ())
						return false;
				}

				return true;
			}

			QString GetFileName (QString jid)
			{
				return QString ("%1/.local/share/Psi+/profiles/%2/history/%3.history")
						.arg (QDir::homePath ())
						.arg (Profile_)
						.arg (jid.replace ('@', "_at_"));
			}

			QVariant ParseLine (const QString& line)
			{
				QStringList list = line.split ('|', QString::SkipEmptyParts);
				if (list.size () < 5 || list [1] != "1")
					return QVariant ();

				QVariantMap result;
				result ["EntryID"] = CurrentJID_;
				result ["DateTime"] = QDateTime::fromString (list.at (0), Qt::ISODate);
				result ["Direction"] = list.at (2) == "to" ? "out" : "in";

				list.erase (list.begin (), list.begin () + 4);
				result ["Body"] = list.join ("|").trimmed ();
				result ["MessageType"] = "chat";
				return result;
			}
		};
	}

	void PsiPlusImportPage::SendImportHist (QStandardItem *accItem)
	{
		QVariantMap data = accItem->data (Roles::AccountData).toMap ();

		HistImporter *hi = new HistImporter (data ["ParentProfile"].toString (),
				data ["Name"].toString (),
				data ["Jid"].toString (),
				data ["Contacts"].toStringList ());
		connect (hi,
				SIGNAL (gotEntity (LeechCraft::Entity)),
				qobject_cast<ImportWizard*> (wizard ())->GetPlugin (),
				SIGNAL (gotEntity (LeechCraft::Entity)));
	}
}
}
}
