/*******************************************************************************************************
 nomacs is a fast and small image viewer with the capability of synchronizing multiple instances
 
 Copyright (C) 2011-2016 Markus Diem <markus@nomacs.org>
 Copyright (C) 2011-2016 Stefan Fiel <stefan@nomacs.org>
 Copyright (C) 2011-2016 Florian Kleber <florian@nomacs.org>

 This file is part of nomacs.

 nomacs 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 3 of the License, or
 (at your option) any later version.

 nomacs 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 <http://www.gnu.org/licenses/>.

 related links:
 [1] http://www.nomacs.org/
 [2] https://github.com/nomacs/
 [3] http://download.nomacs.org
 *******************************************************************************************************/

#pragma once

#pragma warning(push, 0)	// no warnings from includes
#include <QString>
#include <QObject>
#include <QNetworkReply>
#pragma warning(pop)

#ifndef DllCoreExport
#ifdef DK_CORE_DLL_EXPORT
#define DllCoreExport Q_DECL_EXPORT
#elif DK_DLL_IMPORT
#define DllCoreExport Q_DECL_IMPORT
#else
#define DllCoreExport Q_DECL_IMPORT
#endif
#endif

// Qt defines
class QXmlStreamReader;
class QNetworkAccessManager;

namespace nmc {

// nomacs defines
class DkPackage {

public:
	DkPackage(const QString& name = "", const QString& version = "");

	bool isEmpty() const;
	bool operator==(const DkPackage& o) const;

	QString name() const;
	QString version() const;

protected:
	QString mName;
	QString mVersion;
};

class DkXmlUpdateChecker {

public:
	DkXmlUpdateChecker();

	QVector<DkPackage> updatesAvailable(QXmlStreamReader& localXml, QXmlStreamReader& remoteXml) const;

protected:
	QVector<DkPackage> parse(QXmlStreamReader& reader) const;
};

class DllCoreExport DkInstallUpdater : public QObject {
	Q_OBJECT

public:
	DkInstallUpdater(QObject* parent = 0);

	void checkForUpdates(bool silent = true);

	static bool updateNomacs(const QString& cmd = "");

	public slots:
	void replyFinished(QNetworkReply* reply);

protected:

	QNetworkAccessManager* mManager = 0;
	bool mSilent = true;

};

class DllCoreExport DkUpdater : public QObject {
	Q_OBJECT

public:
	bool silent;

	DkUpdater(QObject* parent = 0);

	public slots:
	void checkForUpdates();
	void replyFinished(QNetworkReply*);
	void replyError(QNetworkReply::NetworkError);
	void performUpdate();
	void downloadFinishedSlot(QNetworkReply* data);
	void updateDownloadProgress(qint64 received, qint64 total) { emit downloadProgress(received, total); };
	void cancelUpdate();

signals:
	void displayUpdateDialog(const QString& msg, const QString& title) const;
	void showUpdaterMessage(const QString& msg, const QString& title) const;
	void downloadFinished(const QString& filePath) const;
	void downloadProgress(qint64, qint64) const;

protected:
	void startDownload(QUrl downloadUrl);

	QNetworkAccessManager mAccessManagerVersion;
	QNetworkAccessManager mAccessManagerSetup;

	QNetworkReply* mReply = 0;
	QNetworkCookieJar* mCookie = 0;

	QUrl mNomacsSetupUrl;
	QString mSetupVersion;
	bool mUpdateAborted = false;
};

class DllCoreExport DkTranslationUpdater : public QObject {
	Q_OBJECT

public:
	DkTranslationUpdater(bool silent = false, QObject* parent = 0);
	bool silent;

	public slots:
	virtual void checkForUpdates();
	virtual void replyFinished(QNetworkReply*);
	void updateDownloadProgress(qint64 received, qint64 total);
	void updateDownloadProgressQt(qint64 received, qint64 total);
	void cancelUpdate();

signals:
	void translationUpdated();
	void showUpdaterMessage(const QString&, const QString&);
	void downloadProgress(qint64, qint64);
	void downloadFinished();

private:
	bool isRemoteFileNewer(QDateTime lastModifiedRemote, const QString& localTranslationName);
	bool updateAborted, updateAbortedQt;

	qint64 mTotal, mTotalQt, mReceived, mReceivedQt;
	QNetworkAccessManager mAccessManager;
	QNetworkReply* mReply = 0;
	QNetworkReply* mReplyQt = 0;
};

}