/**********************************************************************
 * 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 <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <QHeaderView>
#include <QFileDialog>
#include <QMessageBox>
#include <util/util.h>
#include <interfaces/core/icoreproxy.h>
#include <interfaces/core/itagsmanager.h>
#include "addtorrent.h"
#include "torrentfilesmodel.h"
#include "xmlsettingsmanager.h"
#include "core.h"

namespace LeechCraft
{
namespace Plugins
{
namespace BitTorrent
{
	AddTorrent::AddTorrent (QWidget *parent)
	: QDialog (parent)
	{
		setupUi (this);
		FilesModel_ = new TorrentFilesModel (this);
		FilesView_->header ()->setStretchLastSection (true);
		FilesView_->setModel (FilesModel_);
		OK_->setEnabled (false);
		connect (this,
				SIGNAL (on_TorrentFile__textChanged ()),
				this,
				SLOT (setOkEnabled ()));
		connect (this,
				SIGNAL (on_Destination__textChanged ()),
				this,
				SLOT (setOkEnabled ()));
		connect (this,
				SIGNAL (on_Destination__textChanged ()),
				this,
				SLOT (updateAvailableSpace ()));

		QFontMetrics fm = fontMetrics ();
		QHeaderView *header = FilesView_->header ();
		header->resizeSection (0, fm.width ("Thisisanaveragetorrentcontainedfilename,ormaybeevenbiggerthanthat!"));
		header->resizeSection (1, fm.width ("_999.9 MB_"));
	}

	void AddTorrent::Reinit ()
	{
		FilesModel_->Clear ();
		TorrentFile_->setText ("");
		TrackerURL_->setText (tr ("<unknown>"));
		Size_->setText (tr ("<unknown>"));
		Creator_->setText (tr ("<unknown>"));
		Comment_->setText (tr ("<unknown>"));
		Date_->setText (tr ("<unknown>"));

		const auto& dir = XmlSettingsManager::Instance ()->
				property ("LastSaveDirectory").toString ();
		Destination_->setText (dir);

		updateAvailableSpace ();
	}

	void AddTorrent::SetFilename (const QString& filename)
	{
		if (filename.isEmpty ())
			return;

		Reinit ();

		XmlSettingsManager::Instance ()->setProperty ("LastTorrentDirectory",
				QFileInfo (filename).absolutePath ());
		TorrentFile_->setText (filename);

		ParseBrowsed ();
	}

	void AddTorrent::SetSavePath (const QString& path)
	{
		Destination_->setText (path);
	}

	QString AddTorrent::GetFilename () const
	{
		return TorrentFile_->text ();
	}

	QString AddTorrent::GetSavePath () const
	{
		return Destination_->text ();
	}

	bool AddTorrent::GetTryLive () const
	{
		return TryLive_->checkState () == Qt::Checked;
	}

	QVector<bool> AddTorrent::GetSelectedFiles () const
	{
		return FilesModel_->GetSelectedFiles ();
	}

	Core::AddType AddTorrent::GetAddType () const
	{
		switch (AddTypeBox_->currentIndex ())
		{
		case 0:
			return Core::Started;
		case 1:
			return Core::Paused;
		default:
			return Core::Started;
		}
	}

	void AddTorrent::SetTags (const QStringList& ids)
	{
		auto tm = Core::Instance ()->GetProxy ()->GetTagsManager ();

		QStringList tags;
		Q_FOREACH (const auto& id, ids)
			tags <<tm->GetTag (id);
		TagsEdit_->setText (tm->Join (tags));
	}

	QStringList AddTorrent::GetTags () const
	{
		auto tm = Core::Instance ()->GetProxy ()->GetTagsManager ();

		QStringList result;
		for (const auto& tag : tm->Split (TagsEdit_->text ()))
			result << tm->GetID (tag);
		return result;
	}

	Util::TagsLineEdit* AddTorrent::GetEdit ()
	{
		return TagsEdit_;
	}

	void AddTorrent::setOkEnabled ()
	{
		OK_->setEnabled (QFileInfo (TorrentFile_->text ()).isReadable () &&
				QFileInfo (Destination_->text ()).exists ());
	}

	void AddTorrent::updateAvailableSpace ()
	{
		const QPair<quint64, quint64>& pair = GetAvailableSpaceInDestination ();
		const quint64 availableSpace = pair.first;
		const quint64 totalSpace = pair.second;

		if (availableSpace != static_cast<quint64> (-1))
		{
			AvailSpaceLabel_->setText (tr ("%1 free").arg (Util::MakePrettySize (availableSpace)));
			AvailSpaceBar_->show ();
			AvailSpaceBar_->setValue (100 - 100 * availableSpace / totalSpace);
		}
		else
		{
			AvailSpaceLabel_->setText (tr ("unknown"));
			AvailSpaceBar_->hide ();
		}
	}

	void AddTorrent::on_TorrentBrowse__released ()
	{
		const auto& filename = QFileDialog::getOpenFileName (this,
				tr ("Select torrent file"),
				XmlSettingsManager::Instance ()->property ("LastTorrentDirectory").toString (),
				tr ("Torrents (*.torrent);;All files (*.*)"));
		if (filename.isEmpty ())
			return;

		Reinit ();

		XmlSettingsManager::Instance ()->setProperty ("LastTorrentDirectory",
				QFileInfo (filename).absolutePath ());
		TorrentFile_->setText (filename);

		ParseBrowsed ();
	}

	void AddTorrent::on_DestinationBrowse__released ()
	{
		const auto& dir = QFileDialog::getExistingDirectory (this,
				tr ("Select save directory"),
				Destination_->text (),
				0);
		if (dir.isEmpty ())
			return;

		XmlSettingsManager::Instance ()->setProperty ("LastSaveDirectory", dir);
		Destination_->setText (dir);
	}

	void AddTorrent::on_MarkAll__released ()
	{
		FilesModel_->MarkAll ();
	}

	void AddTorrent::on_UnmarkAll__released ()
	{
		FilesModel_->UnmarkAll ();
	}

	void AddTorrent::on_MarkSelected__released ()
	{
		FilesModel_->MarkIndexes (FilesView_->selectionModel ()->selectedRows ());
	}

	void AddTorrent::on_UnmarkSelected__released ()
	{
		FilesModel_->UnmarkIndexes (FilesView_->selectionModel ()->selectedRows ());
	}

	void AddTorrent::ParseBrowsed ()
	{
		const auto& filename = TorrentFile_->text ();
		const auto& info = Core::Instance ()->GetTorrentInfo (filename);
		if (!info.is_valid ())
		{
			QMessageBox::critical (this,
					"LeechCraft",
					tr ("Looks like %1 is not a valid torrent file.")
						.arg ("<em>" + filename + "</em>"));
			return;
		}

		if (info.trackers ().size ())
			TrackerURL_->setText (QString::fromStdString (info.trackers ().at (0).url));
		else
			TrackerURL_->setText (tr ("<no trackers>"));
		Size_->setText (Util::MakePrettySize (info.total_size ()));

		QString creator = QString::fromUtf8 (info.creator ().c_str ()),
				comment = QString::fromUtf8 (info.comment ().c_str ());

		QString date;
		auto maybeDate = info.creation_date ();
		if (maybeDate)
#if LIBTORRENT_VERSION_NUM >= 1600
			date = QDateTime::fromTime_t (*maybeDate).toString ();
#else
			date = QString::fromStdString (boost::posix_time::to_simple_string (*maybeDate));
#endif

		if (!creator.isEmpty () && !creator.isNull ())
			Creator_->setText (creator);
		else
			Creator_->setText ("<>");
		if (!comment.isEmpty () && !comment.isNull ())
			Comment_->setText (comment);
		else
			Comment_->setText ("<>");
		if (!date.isEmpty () && !date.isNull ())
			Date_->setText (date);
		else
			Date_->setText ("<>");
		FilesModel_->ResetFiles (info.begin_files (), info.end_files (), info.files ());
		FilesView_->expandAll ();
	}

	QPair<quint64, quint64> AddTorrent::GetAvailableSpaceInDestination ()
	{
		try
		{
#ifdef Q_OS_WIN32
			const auto space = boost::filesystem::space (std::string (GetSavePath ().toUtf8 ().constData ()));
#else
			const auto space = boost::filesystem::space (GetSavePath ().toStdWString ());
#endif
			return qMakePair<quint64, quint64> (space.available, space.capacity);
		}
		catch (...)
		{
			return qMakePair<quint64, quint64> (-1, -1);
		}
	}
}
}
}
