/**********************************************************************
 * 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 "audiofindproxy.h"
#include <QAction>
#include <QTextCodec>
#include <QTime>
#include <QToolBar>
#include <QMenu>
#include "xmlsettingsmanager.h"

Q_DECLARE_METATYPE (QToolBar*)
Q_DECLARE_METATYPE (QMenu*)

namespace LeechCraft
{
namespace vGrabber
{
	namespace
	{
		QString Filter (QString str)
		{
			if (str.contains ("<a href='javascript"))
			{
				QRegExp unJS (".*<a href='javascript: showLyrics\\([0-9]*,[0-9]*\\);'>(.*)</a>");
				unJS.setMinimal (true);
				if (unJS.indexIn (str, 0) >= 0)
					str = unJS.cap (1);
			}

			str.replace ("&amp;", "&");
			str.replace ("&#39;", "'");

			return str;
		}
	};

	AudioFindProxy::AudioFindProxy (const Request& r, CategoriesSelector *cs)
	: FindProxy (r, cs, FPTAudio)
	{
		SetError (tr ("Searching for %1...")
				.arg (r.String_));
	}

	QVariant AudioFindProxy::data (const QModelIndex& index, int role) const
	{
		if (!index.isValid ())
			return QVariant ();

		switch (role)
		{
			case Qt::DisplayRole:
				if (Error_)
				{
					switch (index.column ())
					{
						case 0:
							return *Error_;
						case 1:
							return tr ("Audio vkontakte.ru");
						default:
							return QString ();
					}
				}
				else
				{
					const AudioResult& res = AudioResults_ [index.row ()];
					switch (index.column ())
					{
						case 0:
							return QString ("%1 - %2")
								.arg (res.Performer_)
								.arg (res.Title_);
						case 1:
							return QTime (0, 0, 0).addSecs (res.Length_ - 1).toString ();
						case 2:
							return res.URL_.toString ();
						default:
							return QString ();
					}
				}
			case LeechCraft::RoleControls:
				{
					UpdateURLActionsData (index.row ());
					return QVariant::fromValue<QToolBar*> (Toolbar_);
				}
			case LeechCraft::RoleContextMenu:
				{
					UpdateURLActionsData (index.row ());
					return QVariant::fromValue<QMenu*> (ContextMenu_);
				}
			default:
				return QVariant ();
		}
	}

	int AudioFindProxy::rowCount (const QModelIndex& parent) const
	{
		if (parent.isValid ())
			return 0;

		if (Error_)
			return 1;
		else
			return AudioResults_.size ();
	}

	void AudioFindProxy::UpdateURLActionsData (int row) const
	{
		QUrl url;
		if (AudioResults_.size () > row)
			url = AudioResults_ [row].URL_;
		if (!url.isEmpty ())
		{
			ActionDownload_->setData (url);
			ActionHandle_->setData (url);
			ActionCopyToClipboard_->setData (url);
		}
		ActionDownload_->setEnabled (!url.isEmpty ());
		ActionHandle_->setEnabled (!url.isEmpty ());
		ActionCopyToClipboard_->setEnabled (!url.isEmpty ());
	}

	QUrl AudioFindProxy::GetURL () const
	{
		QByteArray urlStr = "http://vk.com/gsearch.php?q=FIND&section=audio";
		urlStr.replace ("FIND",
				QTextCodec::codecForName ("Windows-1251")->fromUnicode (R_.String_).toPercentEncoding ());
		QUrl result = QUrl::fromEncoded (urlStr);
		return result;
	}

	void AudioFindProxy::Handle (const QString& contents)
	{
		QList<QUrl> urls;
		QList<int> lengths;

		int vnp = contents.indexOf ("var next_page = ");
		int startPos = contents.indexOf ('}', vnp);

		QRegExp links (".*onclick=\"return operate\\([0-9]*,([0-9]*),([0-9]*),'([0-9a-f]*)',([0-9]*)\\);\".*");
		links.setMinimal (true);
		int pos = startPos;
		while (pos >= 0)
		{
			if (contents.mid (pos).contains ("return operate"))
				pos = links.indexIn (contents, pos);
			else
				pos = -1;

			if (pos >= 0)
			{
				QStringList captured = links.capturedTexts ();
				captured.removeFirst ();
				urls << QUrl (QString ("http://cs%1.vkontakte.ru/u%2/audio/%3.mp3")
						.arg (captured.at (0))
						.arg (captured.at (1))
						.arg (captured.at (2)));
				lengths << captured.at (3).toInt ();
				pos += links.matchedLength ();
			}
		}

		QList<QPair<QString, QString>> infos;
		QRegExp names (".*performer[0-9]*\">(.*)</b><span>&nbsp;-&nbsp;</span><span id=\"title[0-9]*\">(.*)</spa.*");
		names.setMinimal (true);
		pos = startPos;
		while (pos >= 0)
		{
			if (contents.mid (pos).contains ("return operate"))
				pos = names.indexIn (contents, pos);
			else
				pos = -1;

			if (pos >= 0)
			{
				QStringList captured = names.capturedTexts ();
				captured.removeFirst ();
				infos << qMakePair<QString, QString> (captured.at (0), captured.at (1));
				pos += names.matchedLength ();
			}
		}

		if (AudioResults_.size ())
		{
			beginRemoveRows (QModelIndex (), 1, AudioResults_.size () - 1);
			AudioResults_.clear ();
			endRemoveRows ();
		}

		QList<AudioResult> tmp;

		int size = urls.size ();
		for (int i = 0; i < size; ++i)
		{
			if (XmlSettingsManager::Instance ()->
					property ("FilterSameURLs").toBool () &&
					urls.count (urls.at (i)) > 1)
				continue;

			QPair<QString, QString> pair = infos.at (i);
			int length = lengths.at (i);

			if (XmlSettingsManager::Instance ()->
					property ("FilterSamePTL").toBool () &&
					infos.count (pair) > 1 &&
					lengths.count (length) > 1)
				continue;

			AudioResult r =
			{
				urls.at (i),
				length,
				Filter (pair.first),
				Filter (pair.second)
			};
			tmp << r;
		}

		size = tmp.size ();

		if (size)
		{
			SetError (QString ());
			beginInsertRows (QModelIndex (), 0, size - 1);
			AudioResults_ = tmp;
			endInsertRows ();
		}
		else
			SetError (tr ("Nothing found for %1")
					.arg (R_.String_));
	}

	void AudioFindProxy::handleDownload ()
	{
		EmitWith (LeechCraft::OnlyDownload,
				qobject_cast<QAction*> (sender ())->data ().value<QUrl> ());
	}

	void AudioFindProxy::handleHandle ()
	{
		EmitWith (LeechCraft::OnlyHandle,
				qobject_cast<QAction*> (sender ())->data ().value<QUrl> ());
	}
}
}
