/**********************************************************************
 * 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 "eventswidget.h"
#include <QStandardItemModel>
#include <QQuickWidget>
#include <QQmlContext>
#include <QQuickItem>
#include <QtDebug>
#include <interfaces/core/ipluginsmanager.h>
#include <interfaces/media/ieventsprovider.h>
#include <interfaces/iinfo.h>
#include <util/qml/colorthemeproxy.h>
#include <util/qml/standardnamfactory.h>
#include <util/sys/paths.h>
#include <util/models/rolenamesmixin.h>
#include "core.h"
#include "xmlsettingsmanager.h"
#include "util.h"

namespace LeechCraft
{
namespace LMP
{
	namespace
	{
		class EventsModel : public Util::RoleNamesMixin<QStandardItemModel>
		{
		public:
			enum Role
			{
				EventID = Qt::UserRole + 1,
				EventName,
				ImageThumbURL,
				ImageBigURL,
				Tags,
				Date,
				City,
				Place,
				Headliner,
				OtherArtists,
				CanBeAttended,
				IsAttended
			};

			EventsModel (QObject *parent = 0)
			: RoleNamesMixin<QStandardItemModel> (parent)
			{
				QHash<int, QByteArray> names;
				names [EventID] = "eventID";
				names [EventName] = "eventName";
				names [ImageThumbURL] = "eventImageThumbURL";
				names [ImageBigURL] = "eventImageBigURL";
				names [Tags] = "eventTags";
				names [Date] = "eventDate";
				names [City] = "eventCity";
				names [Place] = "eventPlace";
				names [Headliner] = "eventHeadliner";
				names [OtherArtists] = "eventArtists";
				names [CanBeAttended] = "canBeAttended";
				names [IsAttended] = "isAttended";
				setRoleNames (names);
			}
		};
	}

	EventsWidget::EventsWidget (QWidget *parent)
	: QWidget (parent)
	, View_ (new QQuickWidget)
	, Model_ (new EventsModel (this))
	{
		Ui_.setupUi (this);
		layout ()->addWidget (View_);

		new Util::StandardNAMFactory ("lmp/qml",
				[] { return 50 * 1024 * 1024; },
				View_->engine ());

		View_->setResizeMode (QQuickWidget::SizeRootObjectToView);

		View_->rootContext ()->setContextProperty ("eventsModel", Model_);
		View_->rootContext ()->setContextProperty ("attendSureTextString", tr ("Sure!"));
		View_->rootContext ()->setContextProperty ("attendMaybeTextString", tr ("Maybe"));
		View_->rootContext ()->setContextProperty ("unattendTextString", tr ("Unattend"));
		View_->rootContext ()->setContextProperty ("colorProxy",
				new Util::ColorThemeProxy (Core::Instance ().GetProxy ()->GetColorThemeManager (), this));

		View_->setSource (Util::GetSysPathUrl (Util::SysPath::QML, "lmp", "EventsView.qml"));

		connect (View_->rootObject (),
				SIGNAL (attendSure (int)),
				this,
				SLOT (handleAttendSure (int)));
		connect (View_->rootObject (),
				SIGNAL (attendMaybe (int)),
				this,
				SLOT (handleAttendMaybe (int)));
		connect (View_->rootObject (),
				SIGNAL (unattend (int)),
				this,
				SLOT (handleUnattend (int)));
	}

	void EventsWidget::InitializeProviders ()
	{
		const auto& lastProv = ShouldRememberProvs () ?
				XmlSettingsManager::Instance ()
					.Property ("LastUsedEventsProvider", QString ()).toString () :
				QString ();

		bool lastFound = false;

		const auto& roots = Core::Instance ().GetProxy ()->GetPluginsManager ()->
				GetAllCastableRoots<Media::IEventsProvider*> ();
		Q_FOREACH (auto root, roots)
		{
			auto scrob = qobject_cast<Media::IEventsProvider*> (root);
			if (!scrob)
				continue;

			const auto& icon = qobject_cast<IInfo*> (root)->GetIcon ();
			Ui_.Provider_->addItem (icon, scrob->GetServiceName ());
			Providers_ << qobject_cast<Media::IEventsProvider*> (root);

			connect (root,
					SIGNAL (gotRecommendedEvents (Media::EventInfos_t)),
					this,
					SLOT (handleEvents (Media::EventInfos_t)));

			if (scrob->GetServiceName () == lastProv)
			{
				const int idx = Providers_.size () - 1;
				Ui_.Provider_->setCurrentIndex (idx);
				on_Provider__activated (idx);
				lastFound = true;
			}
		}

		if (!lastFound)
			Ui_.Provider_->setCurrentIndex (-1);
	}

	void EventsWidget::on_Provider__activated (int index)
	{
		Model_->clear ();

		auto prov = Providers_.at (index);
		prov->UpdateRecommendedEvents ();

		XmlSettingsManager::Instance ().setProperty ("LastUsedEventsProvider", prov->GetServiceName ());
	}

	void EventsWidget::handleEvents (const Media::EventInfos_t& events)
	{
		const int provIdx = Ui_.Provider_->currentIndex ();
		if (provIdx < 0 ||
			qobject_cast<Media::IEventsProvider*> (sender ()) != Providers_.value (provIdx))
			return;

		Model_->clear ();

		Q_FOREACH (const auto& event_t, events)
		{
			Media::EventInfo event (event_t);

			auto item = new QStandardItem;
			item->setData (event.ID_, EventsModel::Role::EventID);
			item->setData (event.Name_, EventsModel::Role::EventName);
			item->setData (event.SmallImage_, EventsModel::Role::ImageThumbURL);
			item->setData (event.BigImage_, EventsModel::Role::ImageBigURL);
			item->setData (event.Tags_.join ("; "), EventsModel::Role::Tags);
			item->setData (event.Date_.toString (Qt::SystemLocaleLongDate), EventsModel::Role::Date);
			item->setData (event.PlaceName_, EventsModel::Role::Place);
			item->setData (event.City_, EventsModel::Role::City);

			if (!event.Headliner_.isEmpty ())
				item->setData (tr ("Headliner: %1").arg (event.Headliner_),
						EventsModel::Role::Headliner);

			auto otherArtists = event.Artists_;
			otherArtists.removeAll (event.Headliner_);
			item->setData (otherArtists.isEmpty () ?
						QString () :
						tr ("Other artists: %1").arg (otherArtists.join ("; ")),
					EventsModel::Role::OtherArtists);

			item->setData (event.CanBeAttended_, EventsModel::Role::CanBeAttended);
			item->setData (event.AttendType_ != Media::EventAttendType::None,
					EventsModel::Role::IsAttended);

			Model_->appendRow (item);
		}
	}

	void EventsWidget::handleAttendSure (int id)
	{
		auto prov = Providers_.value (Ui_.Provider_->currentIndex ());
		if (!prov)
			return;
		prov->AttendEvent (id, Media::EventAttendType::Surely);
	}

	void EventsWidget::handleAttendMaybe (int id)
	{
		auto prov = Providers_.value (Ui_.Provider_->currentIndex ());
		if (!prov)
			return;
		prov->AttendEvent (id, Media::EventAttendType::Maybe);
	}

	void EventsWidget::handleUnattend (int id)
	{
		auto prov = Providers_.value (Ui_.Provider_->currentIndex ());
		if (!prov)
			return;
		prov->AttendEvent (id, Media::EventAttendType::None);
	}
}
}
