/**********************************************************************
 * 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 "hascirylsearcher.h"
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QHttpPart>
#include <QHttpMultiPart>
#include <util/network/lcserviceoverride.h>
#include <util/network/handlenetworkreply.h>
#include <util/sll/functor.h>
#include <util/sll/parsejson.h>

namespace LeechCraft
{
namespace DeadLyrics
{
	namespace
	{
		namespace
		{
			QString GetUrl (const QString& path)
			{
				return Util::GetServiceUrl ({ "127.0.0.1", 12001, "DL_HASCIRYL", false }, path);
			}
		}
	}

	HascirylSearcher::HascirylSearcher (QNetworkAccessManager *nam)
	: NAM_ { nam }
	{
	}

	void HascirylSearcher::Search (const Media::LyricsQuery& query, Media::QueryOptions)
	{
		using Util::operator*;

		const QNetworkRequest req { GetUrl ("lyrics/pages/urls") };

		QByteArray postData;
		auto append = [&postData] (const QByteArray& key, const QString& value)
		{
			if (value.isEmpty ())
				return;

			if (!postData.isEmpty ())
				postData += '&';
			postData += key + '=' + QUrl::toPercentEncoding (value);
		};
		append ("artist", query.Artist_);
		append ("album", query.Album_);
		append ("title", query.Title_);
		auto num = [] (int num) { return QString::number (num); };
		append ("year", (num * query.Year_).value_or (QString {}));
		append ("track", (num * query.Track_).value_or (QString {}));

		Util::HandleNetworkReply (this, NAM_->post (req, postData),
				[this, query] (const QByteArray& data) { HandleLyricsUrls (query, data); });
	}

	void HascirylSearcher::HandleLyricsUrls (const Media::LyricsQuery& origQuery,const QByteArray& data)
	{
		const auto& urls = Util::ParseJson (data, Q_FUNC_INFO).toList ();
		for (const auto& varMap : urls)
		{
			const auto& map = varMap.toMap ();
			const auto& prov = map ["provName"].toString ();
			const auto& url = map ["reqUrl"].toString ();

			Util::HandleNetworkReply (this, NAM_->get (QNetworkRequest { QUrl { url } }),
					[this, origQuery, prov] (const QByteArray& data)
						{ HandleLyricsPageFetched (origQuery, prov, data); });
		}
	}

	void HascirylSearcher::HandleLyricsPageFetched (const Media::LyricsQuery& origQuery,
			const QString& provName, const QByteArray& data)
	{
		QHttpPart servicePart;
		servicePart.setHeader (QNetworkRequest::ContentDispositionHeader, "form-data; name=\"service\"");
		servicePart.setBody (provName.toUtf8 ());

		QHttpPart contentsPart;
		contentsPart.setHeader (QNetworkRequest::ContentDispositionHeader,
				"form-data; name=\"contents\"; filename=\"contents\"");
		contentsPart.setBody (data);

		auto multipart = new QHttpMultiPart { QHttpMultiPart::FormDataType };
		multipart->append (servicePart);
		multipart->append (contentsPart);

		const auto reply = NAM_->post (QNetworkRequest { GetUrl ("lyrics/page/parse") }, multipart);
		multipart->setParent (reply);

		Util::HandleNetworkReply (this, reply,
				[this, origQuery, provName] (const QByteArray& data)
					{ HandleGotLyricsReply (origQuery, provName, data); });
	}

	void HascirylSearcher::HandleGotLyricsReply (const Media::LyricsQuery& origQuery,
			const QString& provName, const QByteArray& data)
	{
		const auto& reply = Util::ParseJson (data, Q_FUNC_INFO).toMap ();
		const auto& result = reply ["result"].toString ();
		if (result != "Success")
			return;

		const auto& lyrics = reply ["payload"].toString ();
		emit gotLyrics ({ origQuery, { { provName, lyrics } } });
	}
}
}
