#include "core/session.h"
#include "core/strings.h"
#include "gui/dialog/settings.h"

#include <QListWidget>
#include <QListWidgetItem>
#include <QGroupBox>
#include <QCheckBox>
#include <QLabel>
#include <QSizePolicy>
#include <QVBoxLayout>
#include <QDir>
#include <QFileDialog>
#include <QFileInfo>
#include <QPushButton>
#include <QDropEvent>
#include <QMimeData>

#include <algorithm>
#include <iostream>

class DroppableListWidget : public QListWidget {
	Q_OBJECT

public:
	explicit DroppableListWidget(QWidget* parent);

signals:
	void FilesDropped(QStringList list);

protected:
	void dragEnterEvent(QDragEnterEvent* event) override;
	void dragMoveEvent(QDragMoveEvent* event) override;
	void dropEvent(QDropEvent* event) override;
};

DroppableListWidget::DroppableListWidget(QWidget* parent) : QListWidget(parent) {
	setAcceptDrops(true);
}

void DroppableListWidget::dragMoveEvent(QDragMoveEvent* event) {
    if (event->mimeData()->hasUrls())
        event->acceptProposedAction();
}

void DroppableListWidget::dragEnterEvent(QDragEnterEvent* event) {
    if (event->mimeData()->hasUrls())
        event->acceptProposedAction();
}

void DroppableListWidget::dropEvent(QDropEvent* event) {
	const QMimeData* mime_data = event->mimeData();

	if (!mime_data->hasUrls())
		return;

	QStringList path_list;
	QList<QUrl> url_list = mime_data->urls();

	for (const auto& url : url_list) {
		if (!url.isLocalFile())
			continue;

		const QString file = url.toLocalFile();
		const QFileInfo fileinfo(file);
		if (fileinfo.exists() && fileinfo.isDir())
			path_list.append(file);
	}

	if (!path_list.isEmpty())
		emit FilesDropped(path_list);

	event->acceptProposedAction();
}

QWidget* SettingsPageLibrary::CreateFoldersWidget() {
	QWidget* result = new QWidget(this);
	result->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);

	QVBoxLayout* full_layout = new QVBoxLayout(result);

	{
		QGroupBox* group_box = new QGroupBox(tr("Library folders"), result);
		group_box->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);

		QVBoxLayout* group_box_layout = new QVBoxLayout(group_box);

		{
			QLabel* label = new QLabel(tr("These folders will be scanned and monitored for new episodes."), group_box);
			group_box_layout->addWidget(label);
		}

		{
			DroppableListWidget* listwidget = new DroppableListWidget(group_box);
			listwidget->setSelectionMode(QAbstractItemView::ExtendedSelection);

			for (const auto& path : paths) {
				QListWidgetItem* item = new QListWidgetItem(listwidget);
				item->setText(Strings::ToQString(path));
				/* add icons as well soon */
			}

			connect(listwidget, &DroppableListWidget::FilesDropped, this, [this, listwidget](QStringList list){
				for (const auto& dir : list) {
					paths.insert(Strings::ToUtf8String(dir));
					QListWidgetItem* item = new QListWidgetItem(listwidget);
					item->setText(dir);
				}
			});

			group_box_layout->addWidget(listwidget);

			{
				QWidget* widget = new QWidget(group_box);
				QHBoxLayout* widget_layout = new QHBoxLayout(widget);

				{
					QLabel* label = new QLabel(tr("Tip: You can drag and drop folders here."), widget);
					widget_layout->addWidget(label);
				}

				widget_layout->addStretch();

				{
					QPushButton* button = new QPushButton(tr("Add new..."), widget);

					connect(button, &QPushButton::clicked, this, [this, listwidget]{
						const QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"),
																			QDir::homePath(),
																			QFileDialog::ShowDirsOnly
																			| QFileDialog::DontResolveSymlinks);
						if (dir.isEmpty())
							return;
						paths.insert(Strings::ToUtf8String(dir));
						QListWidgetItem* item = new QListWidgetItem(listwidget);
						item->setText(dir);
					});

					widget_layout->addWidget(button);
				}

				{
					QPushButton* button = new QPushButton(tr("Remove"), widget);

					connect(listwidget, &QListWidget::itemSelectionChanged, this, [button, listwidget]{
						QList<QListWidgetItem*> selection = listwidget->selectedItems();
						button->setEnabled(selection.size() > 0);
					});

					connect(button, &QPushButton::clicked, this, [this, listwidget]{
						QList<QListWidgetItem*> selection = listwidget->selectedItems();
						for (const auto& item : selection) {
							paths.erase(Strings::ToUtf8String(item->text()));
							delete item;
						}
					});

					widget_layout->addWidget(button);
				}

				group_box_layout->addWidget(widget);
			}
		}

		full_layout->addWidget(group_box);
	}

	{
		QGroupBox* group_box = new QGroupBox(tr("Real-time monitor"), result);
		group_box->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);

		QVBoxLayout* group_box_layout = new QVBoxLayout(group_box);

		{
			QCheckBox* checkbox = new QCheckBox(tr("Detect new files and folders under library folders"), group_box);
			checkbox->setCheckState(real_time_monitor ? Qt::Checked : Qt::Unchecked);

			connect(checkbox, &QCheckBox::stateChanged, this, [this](int state) {
				real_time_monitor = (state != Qt::Unchecked);
			});

			group_box_layout->addWidget(checkbox);
		}

		full_layout->addWidget(group_box);
	}

	full_layout->setSpacing(10);
	full_layout->addStretch();

	return result;
}

void SettingsPageLibrary::SaveInfo() {
	session.config.library.paths = paths;
	session.config.library.real_time_monitor = real_time_monitor;
}

SettingsPageLibrary::SettingsPageLibrary(QWidget* parent)
	: SettingsPage(parent, tr("Library")),
	  paths(session.config.library.paths) {
	real_time_monitor = session.config.library.real_time_monitor;
	AddTab(CreateFoldersWidget(), tr("Folder"));
}

#include "gui/dialog/settings/library.moc"
