/*
 * Copyright (C) 2008 Remko Troncon
 * See COPYING file for the detailed license.
 */

#include <QApplication>
#include <QDir>
#include <QWidget>
#include <QPushButton>
#include <QTcpServer>
#include <QTcpSocket>
#include <QVBoxLayout>
#include <QFile>

#include "AutoUpdater/AutoUpdater.h"
#include "AutoUpdater/SparkleAutoUpdater.h"
#include "CocoaUtilities/CocoaInitializer.h"

class SimpleHTTPServer : public QObject
{
		Q_OBJECT

	public:
		SimpleHTTPServer(int port = 0) {
      tcpServer_ = new QTcpServer(this);
			if (!tcpServer_->listen(QHostAddress::Any, port)) {
				Q_ASSERT(false);
			}
		  connect(tcpServer_, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
		};

		~SimpleHTTPServer() {
			delete tcpServer_;
		}

		unsigned int getPort() {
			return tcpServer_->serverPort();
		}

		void setPage(const QString& url, const QByteArray& content) {
			pages_[url] = content;
		}

	public slots:
		void incomingConnection() {
			QTcpSocket* socket = tcpServer_->nextPendingConnection();
			connect(socket, SIGNAL(readyRead()), SLOT(readBytes()));
		}

		void readBytes() {
			QTcpSocket* socket = static_cast<QTcpSocket*>(sender());
			QByteArray data = socket->readAll();

			// FIXME: Only do this for the initial request.
			// Wait for the request to finish
			QList<QByteArray> tokens = data.split(' ');
			if (tokens[0] == QString("GET")) {
				if (!pages_.contains(tokens[1])) {
					socket->write("HTTP/1.1 404 Not Found\n\n");
					Q_ASSERT(false);
				}

				QByteArray responseData = pages_[tokens[1]];

				QString response;
				response += "HTTP/1.1 200 OK\n";
				if (tokens[1].endsWith(".html")) {
					response += "Content-Type: text/html\n";
				}
				if (tokens[1].endsWith(".xml")) {
					response += "Content-Type: application/xml\n";
				}
				else {
					response += "Content-Type: text/plain\n";
				}
				response += "Content-Length: " + QString::number(responseData.size()) + "\n";
				response += "\n";
				socket->write(response.toUtf8());
				socket->write(responseData);
			}
		}

	private:
		QTcpServer *tcpServer_;
		QMap<QString,QByteArray> pages_;
};

class UpdaterWidget : public QWidget
{
		Q_OBJECT

	public:
		UpdaterWidget() {
			QFile(QDir::homePath() + "/Library/Preferences/org.psi-im.autoupdater-test.plist").remove();
			QVBoxLayout* layout = new QVBoxLayout(this);

			QPushButton* newButton = new QPushButton("Check with new release", this);
			connect(newButton, SIGNAL(clicked()), this, SLOT(doCheckWithNew()));
			layout->addWidget(newButton);

			QPushButton* noNewButton = new QPushButton("Check without new release", this);
			connect(noNewButton, SIGNAL(clicked()), this, SLOT(doCheckWithoutNew()));
			layout->addWidget(noNewButton);

			server_ = new SimpleHTTPServer();

			QString baseURL = "http://localhost:" + QString::number(server_->getPort());
			appCastURL_ = baseURL + "/appcast.xml";
			releaseNotesURL_ = baseURL + "/releasenotes.html";
			releaseURL_ = baseURL + "/testapp-2.0.zip";

			QString releaseNotes = "<html><body><h2>My release notes</h2><ul><li>note 1</li><li>note 2</li></body></html>";

			server_->setPage("/releasenotes.html", releaseNotes.toUtf8());
			QFile app(":testapp-2.0.zip");
			app.open(QIODevice::ReadOnly);
			server_->setPage("/testapp-2.0.zip", app.readAll());
			app.close();

			updater_ = new SparkleAutoUpdater(appCastURL_);
		}

		~UpdaterWidget() {
			delete updater_;
			delete server_;
		}

		QByteArray createAppCast(bool withNewVersion = false)
		{
			QString appcast;
			appcast += "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
			appcast += "<rss version=\"2.0\" xmlns:sparkle=\"http://www.andymatuschak.org/xml-namespaces/sparkle\"  xmlns:dc=\"http://purl.org/dc/elements/1.1/\">";
			appcast += " <channel>";
			appcast += "  <title>Your Great App's Changelog</title>";
			appcast += "  <link>" + appCastURL_ + "</link>";
			appcast += "  <description>Most recent changes with links to updates.</description>";
			if (withNewVersion) {
				appcast += "  <item>";
				appcast += "   <title>Version 2.0 (2 bugs fixed; 3 new features)</title>";
				appcast += "   <sparkle:releaseNotesLink> " + releaseNotesURL_ + "</sparkle:releaseNotesLink>";
				appcast += "   <pubDate>Wed, 09 Jan 2006 19:20:11 +0000</pubDate>";
				appcast += "   <enclosure url=\"" + releaseURL_ + "\" sparkle:version=\"2.0\" length=\"1623481\" type=\"application/octet-stream\"/>";
				appcast += "  </item>";
			}

			appcast += "  <item>";
			appcast += "   <title>Version 1.0 (2 bugs fixed; 3 new features)</title>";
			appcast += "   <sparkle:releaseNotesLink> " + releaseNotesURL_ + "</sparkle:releaseNotesLink>";
			appcast += "   <pubDate>Wed, 08 Jan 2006 19:20:11 +0000</pubDate>";
			appcast += "   <enclosure url=\"" + releaseURL_ + "\" sparkle:version=\"1.0\" length=\"1623481\" type=\"application/octet-stream\"/>";
			appcast += "  </item>";

			appcast += " </channel>";
			appcast += "</rss>";
			return appcast.toUtf8();
		}


	public slots:
		void doCheckWithNew() {
			server_->setPage("/appcast.xml", createAppCast(true));
			updater_->checkForUpdates();
		}

		void doCheckWithoutNew() {
			server_->setPage("/appcast.xml", createAppCast(false));
			updater_->checkForUpdates();
		}

	private:
		AutoUpdater* updater_;
		SimpleHTTPServer* server_;
		QString appCastURL_, releaseNotesURL_, releaseURL_;
};

int main(int argc, char* argv[])
{
	QApplication app(argc, argv);
	CocoaInitializer initializer;
	UpdaterWidget w;
	w.show();
	app.exec();
	return 0;
}

#include "main.moc"
