/**********************************************************************
 * 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.
 **********************************************************************/

#ifndef PLUGINS_LACKMAN_REPOINFO_H
#define PLUGINS_LACKMAN_REPOINFO_H
#include <functional>
#include <QMetaType>
#include <QStringList>
#include <QUrl>
#include <QMap>

namespace LeechCraft
{
namespace LackMan
{
	struct MaintainerInfo
	{
		QString Name_;
		QString Email_;
	};

	using MaintainerInfoList = QList<MaintainerInfo>;

	class RepoInfo
	{
		QUrl URL_;
		QString Name_;
		QString ShortDescr_;
		QString LongDescr_;

		MaintainerInfo Maintainer_;
		QStringList Components_;
	public:
		explicit RepoInfo ();
		explicit RepoInfo (const QUrl&);
		RepoInfo (const QUrl& url, const QString& name,
				const QString& shortDescr, const QStringList& components);

		const QUrl& GetUrl () const;
		void SetUrl (const QUrl&);
		const QString& GetName () const;
		void SetName (const QString&);
		const QString& GetShortDescr () const;
		void SetShortDescr (const QString&);
		const QString& GetLongDescr () const;
		void SetLongDescr (const QString&);
		const MaintainerInfo& GetMaintainer () const;
		void SetMaintainer (const MaintainerInfo&);
		const QStringList& GetComponents () const;
		void SetComponents (const QStringList&);
	};

	struct PackageShortInfo
	{
		QString Name_;
		QStringList Versions_;
		QMap<QString, QString> VersionArchivers_;
	};

	using PackageShortInfoList = QList<PackageShortInfo>;

	struct Dependency
	{
		enum Type
		{
			TRequires,
			TProvides,
			TMAX
		} Type_;

		/** Dependency version `relation` candidate version.
			*/
		enum Relation
		{
			G, //!< G Dependency version should be greater than candidate's.
			E, //!< E Dependency version should be equal to candidate's.
			L, //!< L Dependency version should be less than candidate's.
			GE,//!< GE Dependency version should be greater or equal to candidate's.
			LE //!< LE Dependency version should be less or equal to candidate's.
		};

		QString Name_;
		QString Version_;
	};

	using DependencyList = QList<Dependency>;

	bool operator== (const Dependency&, const Dependency&);

	struct Image
	{
		enum Type
		{
			TScreenshot,
			TThumbnail
		} Type_;
		QString URL_;
	};

	struct PackageInfo : PackageShortInfo
	{
		enum Type
		{
			/** @brief Package with a plugin for LeechCraft.
				*
				* Contents of packages of this type would be
				* installed into ~/.leechcraft/plugins/scriptable/$language
				*/
			TPlugin,

			/** @brief Translation (or a set of translations).
				*
				* Contents of packages of this type would be
				* installed into ~/.leechcraft/translations
				*/
			TTranslation,

			/** @brief Iconset package.
				*
				* Contents of packages of this type would be
				* installed into ~/.leechcraft/icons
				*/
			TIconset,

			/** @brief Plain data package.
				*
				* Use this if nothing else is appropriate.
				*
				* Contents of packages of this type would be
				* installed into ~/.leechcraft/data
				*/
			TData,

			/** @brief Theme package.
				*
				* Contents of packages of this type would be
				* installed into ~/.leechcraft/data
				*/
			TTheme,

			/** @brief Quark package.
			 */
			TQuark
		} Type_;
		QString Language_;
		QString Description_;
		QString LongDescription_;
		QStringList Tags_;
		QMap<QString, DependencyList> Deps_;
		QString MaintName_;
		QString MaintEmail_;
		QUrl IconURL_;
		QList<Image> Images_;
		QMap<QString, qint64> PackageSizes_;

		void Dump () const;
	};

	/** This contains those and only those fields which are
		* displayed in the Packages list.
		*/
	struct ListPackageInfo
	{
		int PackageID_;
		QString Name_;
		QString Version_;
		QString ShortDescription_;
		QString LongDescription_;
		PackageInfo::Type Type_;
		QString Language_;
		QUrl IconURL_;
		QStringList Tags_;
		bool HasNewVersion_;
		bool IsInstalled_;
	};

	bool operator== (const ListPackageInfo&, const ListPackageInfo&);

	using Comparator_t = std::function<bool (const QString&, const QString&)>;

	extern QMap<Dependency::Relation, Comparator_t> Relation2comparator;

	/** Describes an installed dependency. Installed dependency may
		* come either from system package manager of be installed
		* by LackMan. Source enum is used to distinguish between
		* these two cases.
		*/
	struct InstalledDependencyInfo
	{
		Dependency Dep_;

		/** Whether package was installed via standard system
			* means like system package manager or via LackMan.
			*/
		enum Source
		{
			SSystem,//!< SSystem Package came from system.
			SLackMan//!< SLackMan Package came via LackMan.
		} Source_;
	};

	using InstalledDependencyInfoList = QList<InstalledDependencyInfo>;

	uint qHash (const Dependency&);
}
}

Q_DECLARE_METATYPE (LeechCraft::LackMan::RepoInfo)
Q_DECLARE_METATYPE (LeechCraft::LackMan::PackageShortInfo)
Q_DECLARE_METATYPE (LeechCraft::LackMan::PackageShortInfoList)
Q_DECLARE_METATYPE (LeechCraft::LackMan::PackageInfo)

#endif
