/*******************************************************************************
 * plugins/FeedReader/gui/FeedReaderDialog.cpp                                 *
 *                                                                             *
 * Copyright (C) 2012 by Thunder                                               *
 *                                                                             *
 * This program is free software: you can redistribute it and/or modify        *
 * it under the terms of the GNU Affero General Public License as              *
 * published by the Free Software Foundation, either version 3 of the          *
 * License, or (at your option) any later version.                             *
 *                                                                             *
 * This program is distributed in the hope that it will be useful,             *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of              *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                *
 * GNU Affero General Public License for more details.                         *
 *                                                                             *
 * You should have received a copy of the GNU Affero General Public License    *
 * along with this program. If not, see <https://www.gnu.org/licenses/>.       *
 *                                                                             *
 *******************************************************************************/

#include <QKeyEvent>
#include <QMenu>
#include <QInputDialog>
#include <QPainter>
#include <QMessageBox>
#include <QBuffer>

#include "FeedReaderDialog.h"
#include "FeedReaderMessageWidget.h"
#include "ui_FeedReaderDialog.h"
#include "FeedReaderNotify.h"
#include "FeedReaderConfig.h"
#include "AddFeedDialog.h"
#include "FeedReaderStringDefs.h"
#include "gui/common/RSTreeWidgetItem.h"
#include "gui/settings/rsharesettings.h"
#include "gui/notifyqt.h"
#include "FeedReaderUserNotify.h"
#include "gui/Posted/PostedCreatePostDialog.h"
#include "util/imageutil.h"

#include "interface/rsFeedReader.h"
#include "retroshare/rsiface.h"

#define COLUMN_FEED_COUNT   1
#define COLUMN_FEED_NAME    0
#define COLUMN_FEED_DATA    0

#define ROLE_FEED_ID          Qt::UserRole
#define ROLE_FEED_SORT        Qt::UserRole + 1
#define ROLE_FEED_FOLDER      Qt::UserRole + 2
#define ROLE_FEED_UNREAD      Qt::UserRole + 3
#define ROLE_FEED_NEW         Qt::UserRole + 4
#define ROLE_FEED_NAME        Qt::UserRole + 5
#define ROLE_FEED_WORKSTATE   Qt::UserRole + 6
#define ROLE_FEED_LOADING     Qt::UserRole + 7
#define ROLE_FEED_ICON        Qt::UserRole + 8
#define ROLE_FEED_ERROR       Qt::UserRole + 9
#define ROLE_FEED_DEACTIVATED Qt::UserRole + 10

const int MAXMESSAGESIZE = RsSerialiser::MAX_SERIAL_SIZE - 70000;

FeedReaderDialog::FeedReaderDialog(RsFeedReader *feedReader, FeedReaderNotify *notify, QWidget *parent)
	: MainPage(parent), mFeedReader(feedReader), mNotify(notify), ui(new Ui::FeedReaderDialog)
{
	/* Invoke the Qt Designer generated object setup routine */
	ui->setupUi(this);

	mProcessSettings = false;
	mOpenFeedIds = NULL;
	mMessageWidget = NULL;

	connect(mNotify, &FeedReaderNotify::feedChanged, this, &FeedReaderDialog::feedChanged, Qt::QueuedConnection);
	connect(mNotify, &FeedReaderNotify::optimizeImage, this, &FeedReaderDialog::optimizeImage, Qt::QueuedConnection);

	connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged()));

	/* connect signals */
	connect(ui->feedTreeWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(feedTreeItemActivated(QTreeWidgetItem*)));
	if (!style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, NULL, this)) {
		// need signal itemClicked too
		connect(ui->feedTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(feedTreeItemActivated(QTreeWidgetItem*)));
	}
	connect(ui->feedTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(feedTreeCustomPopupMenu(QPoint)));
	connect(ui->feedTreeWidget, SIGNAL(signalMouseMiddleButtonClicked(QTreeWidgetItem*)), this, SLOT(feedTreeMiddleButtonClicked(QTreeWidgetItem*)));

	connect(ui->messageTabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(messageTabCloseRequested(int)));
	connect(ui->messageTabWidget, SIGNAL(currentChanged(int)), this, SLOT(messageTabChanged(int)));

	connect(ui->feedAddButton, SIGNAL(clicked()), this, SLOT(newFeed()));
	connect(ui->feedProcessButton, SIGNAL(clicked()), this, SLOT(processFeed()));

	connect(ui->feedTreeWidget, SIGNAL(feedReparent(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(feedTreeReparent(QTreeWidgetItem*,QTreeWidgetItem*)));

	mFeedCompareRole = new RSTreeWidgetItemCompareRole;
	mFeedCompareRole->setRole(COLUMN_FEED_NAME, ROLE_FEED_SORT);

	/* enable drag and drop */
	ui->feedTreeWidget->setAcceptDrops(true);
	ui->feedTreeWidget->setDragEnabled(true);
	ui->feedTreeWidget->setDragDropMode(QAbstractItemView::InternalMove);

	/* initialize root item */
	mRootItem = new QTreeWidgetItem(ui->feedTreeWidget);
	QString name = tr("Message Folders");
	mRootItem->setText(COLUMN_FEED_NAME, name);
	mRootItem->setIcon(COLUMN_FEED_NAME, QIcon(":/images/Root.png"));
	mRootItem->setData(COLUMN_FEED_DATA, ROLE_FEED_NAME, name);
	mRootItem->setData(COLUMN_FEED_DATA, ROLE_FEED_FOLDER, true);
	mRootItem->setData(COLUMN_FEED_DATA, ROLE_FEED_ICON, QIcon(":/images/Root.png"));
	mRootItem->setExpanded(true);

	/* set initial size the splitter */
	ui->splitter->setStretchFactor(0, 0);
	ui->splitter->setStretchFactor(1, 1);

	QList<int> sizes;
	sizes << 300 << width(); // Qt calculates the right sizes
	ui->splitter->setSizes(sizes);

	/* load settings */
	processSettings(true);

	/* initialize feed list */
	ui->feedTreeWidget->sortItems(COLUMN_FEED_NAME, Qt::AscendingOrder);

	ui->feedTreeWidget->installEventFilter(this);

	settingsChanged();

	feedTreeItemActivated(NULL);
}

FeedReaderDialog::~FeedReaderDialog()
{
	/* save settings */
	processSettings(false);

	delete(mFeedCompareRole);
	delete(ui);

	if (mOpenFeedIds) {
		delete mOpenFeedIds;
		mOpenFeedIds = NULL;
	}
}

UserNotify *FeedReaderDialog::createUserNotify(QObject *parent)
{
	return new FeedReaderUserNotify(this, mFeedReader, mNotify, parent);
}

void FeedReaderDialog::processSettings(bool load)
{
	mProcessSettings = true;
	Settings->beginGroup(QString("FeedReaderDialog"));

	if (load) {
		// load settings

		// state of splitter
		ui->splitter->restoreState(Settings->value("Splitter").toByteArray());

		// open feeds
		int arrayIndex = Settings->beginReadArray("Feeds");
		for (int index = 0; index < arrayIndex; index++) {
			Settings->setArrayIndex(index);
			addFeedToExpand(Settings->value("open").toUInt());
		}
		Settings->endArray();
	} else {
		// save settings

		// state of splitter
		Settings->setValue("Splitter", ui->splitter->saveState());

		// open groups
		Settings->beginWriteArray("Feeds");
		int arrayIndex = 0;
		QList<uint32_t> expandedFeedIds;
		getExpandedFeedIds(expandedFeedIds);
		foreach (uint32_t feedId, expandedFeedIds) {
			Settings->setArrayIndex(arrayIndex++);
			Settings->setValue("open", feedId);
		}
		Settings->endArray();
	}

	Settings->endGroup();
	mProcessSettings = false;
}

void FeedReaderDialog::settingsChanged()
{
	if (FeedReaderSetting_OpenAllInNewTab()) {
		if (mMessageWidget) {
			delete(mMessageWidget);
			mMessageWidget = NULL;
		}
	} else {
		if (!mMessageWidget) {
			mMessageWidget = createMessageWidget(0);
			// remove close button of the the first tab
			ui->messageTabWidget->hideCloseButton(ui->messageTabWidget->indexOf(mMessageWidget));
		}
	}
}

void FeedReaderDialog::addFeedToExpand(uint32_t feedId)
{
	if (mOpenFeedIds == NULL) {
		mOpenFeedIds = new QList<uint32_t>;
	}
	if (mOpenFeedIds->contains(feedId)) {
		return;
	}
	mOpenFeedIds->push_back(feedId);
}

void FeedReaderDialog::getExpandedFeedIds(QList<uint32_t> &feedIds)
{
	QTreeWidgetItemIterator it(ui->feedTreeWidget);
	QTreeWidgetItem *item;
	while ((item = *it) != NULL) {
		++it;
		if (!item->isExpanded()) {
			continue;
		}
		if (!item->data(COLUMN_FEED_DATA, ROLE_FEED_FOLDER).toBool()) {
			continue;
		}
		uint32_t feedId = item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt();
		if (feedId == 0) {
			continue;
		}
		feedIds.push_back(feedId);
	}
}

void FeedReaderDialog::showEvent(QShowEvent */*event*/)
{
	updateFeeds(0, mRootItem);
}

bool FeedReaderDialog::eventFilter(QObject *obj, QEvent *event)
{
	if (obj == ui->feedTreeWidget) {
		if (event->type() == QEvent::KeyPress) {
			QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
			if (keyEvent) {
				if (keyEvent->key() == Qt::Key_Delete) {
					/* Delete pressed */
					removeFeed();
					return true; // eat event
				}
			}
		}
	}
	/* pass the event on to the parent class */
	return MainPage::eventFilter(obj, event);
}

uint32_t FeedReaderDialog::currentFeedId()
{
	QTreeWidgetItem *item = ui->feedTreeWidget->currentItem();
	if (!item) {
		return 0;
	}

	return item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt();
}

void FeedReaderDialog::setCurrentFeedId(uint32_t feedId)
{
	if (feedId == 0) {
		return;
	}

	QTreeWidgetItemIterator it(ui->feedTreeWidget);
	QTreeWidgetItem *item;
	while ((item = *it) != NULL) {
		if (item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt() == feedId) {
			ui->feedTreeWidget->setCurrentItem(item);
			break;
		}
		++it;
	}
}

void FeedReaderDialog::feedTreeCustomPopupMenu(QPoint /*point*/)
{
	QMenu contextMnu(this);

	bool folder = false;
	uint32_t feedId;
	QTreeWidgetItem *item = ui->feedTreeWidget->currentItem();
	if (item) {
		folder = item->data(COLUMN_FEED_DATA, ROLE_FEED_FOLDER).toBool();
		feedId = item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt();
	}

	QMenu *menu = contextMnu.addMenu(QIcon(""), tr("New"));
	QAction *action = menu->addAction(QIcon(":/images/FeedAdd.png"), tr("Feed"), this, SLOT(newFeed()));
	if (!item || !folder) {
		action->setEnabled(false);
	}
	action = menu->addAction(QIcon(":/images/FolderAdd.png"), tr("Folder"), this, SLOT(newFolder()));
	if (!item || !folder) {
		action->setEnabled(false);
	}

	if (!FeedReaderSetting_OpenAllInNewTab()) {
		contextMnu.addSeparator();

		action = contextMnu.addAction(QIcon(""), tr("Open in new tab"), this, SLOT(openInNewTab()));
		if (!item || folder || feedMessageWidget(feedId)) {
			action->setEnabled(false);
		}
	}

	contextMnu.addSeparator();

	action = contextMnu.addAction(QIcon(":/images/edit_16.png"), tr("Edit"), this, SLOT(editFeed()));
	if (!item || item == mRootItem) {
		action->setEnabled(false);
	}

	action = contextMnu.addAction(QIcon(":/images/delete.png"), tr("Delete"), this, SLOT(removeFeed()));
	if (!item || item == mRootItem) {
		action->setEnabled(false);
	}

	contextMnu.addSeparator();

	bool deactivated = false;
	if (!folder && item) {
		deactivated = item->data(COLUMN_FEED_DATA, ROLE_FEED_DEACTIVATED).toBool();
	}

	action = contextMnu.addAction(QIcon(":/images/Update.png"), tr("Update"), this, SLOT(processFeed()));
	action->setEnabled(!deactivated);

	action = contextMnu.addAction(QIcon(""), deactivated ? tr("Activate") : tr("Deactivate"), this, SLOT(activateFeed()));
	if (!item || item == mRootItem || folder) {
		action->setEnabled(false);
	}

	contextMnu.exec(QCursor::pos());
}

void FeedReaderDialog::updateFeeds(uint32_t parentId, QTreeWidgetItem *parentItem)
{
	if (!parentItem) {
		return;
	}

	/* get feed infos */
	std::list<FeedInfo> feedInfos;
	mFeedReader->getFeedList(parentId, feedInfos);

	int index = 0;
	QTreeWidgetItem *item;
	std::list<FeedInfo>::iterator feedIt;

	/* update existing and delete not existing feeds */
	while (index < parentItem->childCount()) {
		item = parentItem->child(index);
		uint32_t feedId = item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt();

		/* search existing feed */
		int found = -1;
		for (feedIt = feedInfos.begin (); feedIt != feedInfos.end (); ++feedIt) {
			if (feedIt->feedId == feedId) {
				/* found it, update it */
				updateFeedItem(item, *feedIt);

				if (feedIt->flag.folder) {
					/* process child feeds */
					updateFeeds(feedIt->feedId, item);
				}

				feedInfos.erase(feedIt);
				found = index;
				break;
			}
		}
		if (found >= 0) {
			++index;
		} else {
			delete(parentItem->takeChild(index));
		}
	}

	/* add new feeds */
	for (feedIt = feedInfos.begin (); feedIt != feedInfos.end (); ++feedIt) {
		item = new RSTreeWidgetItem(mFeedCompareRole);
		parentItem->addChild(item);
		updateFeedItem(item, *feedIt);

		if (feedIt->flag.folder) {
			/* process child feeds */
			updateFeeds(feedIt->feedId, item);

			if (mOpenFeedIds) {
				int index = mOpenFeedIds->indexOf(feedIt->feedId);
				if (index >= 0) {
					item->setExpanded(true);
					mOpenFeedIds->removeAt(index);
				}
			}
		} else {
			/* disable drop */
			item->setFlags(item->flags() & ~Qt::ItemIsDropEnabled);
		}
	}

	if (mOpenFeedIds && mOpenFeedIds->empty()) {
		delete mOpenFeedIds;
		mOpenFeedIds = NULL;
	}

	calculateFeedItems();
}

void FeedReaderDialog::calculateFeedItem(QTreeWidgetItem *item, uint32_t &unreadCount, uint32_t &newCount, bool &loading)
{
	uint32_t unreadCountItem = 0;
	uint32_t newCountItem = 0;
	bool loadingItem = false;

	if (item->data(COLUMN_FEED_DATA, ROLE_FEED_FOLDER).toBool()) {
		int childCount = item->childCount();
		for (int index = 0; index < childCount; ++index) {
			calculateFeedItem(item->child(index), unreadCountItem, newCountItem, loadingItem);
		}
	} else {
		unreadCountItem = item->data(COLUMN_FEED_DATA, ROLE_FEED_UNREAD).toUInt();
		newCountItem = item->data(COLUMN_FEED_DATA, ROLE_FEED_NEW).toUInt();
		loadingItem = item->data(COLUMN_FEED_DATA, ROLE_FEED_LOADING).toBool();
	}

	unreadCount += unreadCountItem;
	newCount += newCountItem;
	loading = loading || loadingItem;

	QString name = item->data(COLUMN_FEED_DATA, ROLE_FEED_NAME).toString();
	QString workState = item->data(COLUMN_FEED_DATA, ROLE_FEED_WORKSTATE).toString();

	if (unreadCountItem) {
		name += QString(" (%1)").arg(unreadCountItem);
	}
	if (!workState.isEmpty()) {
		name += QString(" (%1)").arg(workState);
	}

	item->setText(COLUMN_FEED_NAME, name);

	bool deactivated = item->data(COLUMN_FEED_DATA, ROLE_FEED_DEACTIVATED).toBool();

	QColor colorActivated = ui->feedTreeWidget->palette().color(QPalette::Active, QPalette::Text);
	QColor color = ui->feedTreeWidget->palette().color(QPalette::Active, QPalette::Base);
	QColor colorDeactivated;
	colorDeactivated.setRgbF((color.redF() + colorActivated.redF()) / 2, (color.greenF() + colorActivated.greenF()) / 2, (color.blueF() + colorActivated.blueF()) / 2);

	for (int i = 0; i < COLUMN_FEED_COUNT; i++) {
		QFont font = item->font(i);
		font.setBold(unreadCountItem != 0);
		item->setFont(i, font);

		item->setData(COLUMN_FEED_NAME, Qt::ForegroundRole, deactivated ? colorDeactivated : colorActivated);
	}

	QIcon icon = item->data(COLUMN_FEED_DATA, ROLE_FEED_ICON).value<QIcon>();

	if (deactivated) {
		/* create disabled icon */
		icon = icon.pixmap(QSize(16, 16), QIcon::Disabled);
	}

	QImage overlayIcon;
	if (loadingItem) {
		/* overlaying icon */
		overlayIcon = QImage(":/images/FeedProcessOverlay.png");
	} else if (item->data(COLUMN_FEED_DATA, ROLE_FEED_ERROR).toBool()) {
		overlayIcon = QImage(":/images/FeedErrorOverlay.png");
	} else if (newCountItem) {
		overlayIcon = QImage(":/images/FeedNewOverlay.png");
	}
	if (!overlayIcon.isNull()) {
		if (icon.isNull()) {
			icon = QPixmap::fromImage(overlayIcon);
		} else {
			QPixmap pixmap = icon.pixmap(QSize(16, 16));
			QPainter painter(&pixmap);
			painter.drawImage(0, 0, overlayIcon.scaled(pixmap.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
			painter.end();
			icon = pixmap;
		}
	}

	item->setIcon(COLUMN_FEED_NAME, icon);
}

void FeedReaderDialog::calculateFeedItems()
{
	uint32_t unreadCount = 0;
	uint32_t newCount = 0;
	bool loading = false;

	calculateFeedItem(mRootItem, unreadCount, newCount, loading);
	ui->feedTreeWidget->sortItems(COLUMN_FEED_NAME, Qt::AscendingOrder);
}

QIcon FeedReaderDialog::iconFromFeed(const FeedInfo &feedInfo)
{
	QIcon icon;
	if (feedInfo.flag.folder) {
		/* use folder icon */
		icon = QIcon(":/images/Folder.png");
	} else {
		if (feedInfo.icon.empty()) {
			/* use standard icon */
			icon = QIcon(":/images/Feed.png");
		} else {
			/* use icon from feed */
			QPixmap pixmap;
			if (pixmap.loadFromData(QByteArray::fromBase64(feedInfo.icon.c_str()))) {
				icon = pixmap.scaled(16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
			}
		}
	}

	return icon;
}

void FeedReaderDialog::updateFeedItem(QTreeWidgetItem *item, const FeedInfo &feedInfo)
{
	item->setData(COLUMN_FEED_DATA, ROLE_FEED_ICON, iconFromFeed(feedInfo));

	QString name = QString::fromUtf8(feedInfo.name.c_str());
	item->setData(COLUMN_FEED_DATA, ROLE_FEED_NAME, name.isEmpty() ? tr("No name") : name);
	item->setData(COLUMN_FEED_DATA, ROLE_FEED_WORKSTATE, FeedReaderStringDefs::workState(feedInfo.workstate));

	uint32_t unreadCount;
	uint32_t newCount;
	mFeedReader->getMessageCount(feedInfo.feedId, NULL, &newCount, &unreadCount);

	item->setData(COLUMN_FEED_NAME, ROLE_FEED_SORT, QString("%1_%2").arg(QString(feedInfo.flag.folder ? "0" : "1"), name));
	item->setData(COLUMN_FEED_DATA, ROLE_FEED_UNREAD, unreadCount);
	item->setData(COLUMN_FEED_DATA, ROLE_FEED_NEW, newCount);
	item->setData(COLUMN_FEED_DATA, ROLE_FEED_LOADING, feedInfo.workstate != FeedInfo::WAITING);
	item->setData(COLUMN_FEED_DATA, ROLE_FEED_ID, feedInfo.feedId);
	item->setData(COLUMN_FEED_DATA, ROLE_FEED_FOLDER, feedInfo.flag.folder);
	item->setData(COLUMN_FEED_DATA, ROLE_FEED_DEACTIVATED, feedInfo.flag.deactivated);
	item->setData(COLUMN_FEED_DATA, ROLE_FEED_ERROR, (bool) (feedInfo.errorState != RS_FEED_ERRORSTATE_OK));
	item->setToolTip(COLUMN_FEED_NAME, (feedInfo.errorState != RS_FEED_ERRORSTATE_OK) ? FeedReaderStringDefs::errorString(feedInfo) : "");
}

void FeedReaderDialog::feedChanged(uint32_t feedId, int type)
{
	if (!isVisible()) {
		/* complete update in showEvent */
		return;
	}

	if (feedId == 0) {
		return;
	}

	FeedInfo feedInfo;
	if (type != NOTIFY_TYPE_DEL) {
		if (!mFeedReader->getFeedInfo(feedId, feedInfo)) {
			return;
		}

		if (feedInfo.flag.preview) {
			return;
		}
	}

	if (type == NOTIFY_TYPE_MOD || type == NOTIFY_TYPE_DEL) {
		QTreeWidgetItemIterator it(ui->feedTreeWidget);
		QTreeWidgetItem *item;
		while ((item = *it) != NULL) {
			if (item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt() == feedId) {
				if (type == NOTIFY_TYPE_MOD) {
					updateFeedItem(item, feedInfo);
				} else {
					delete(item);
				}
				break;
			}
			++it;
		}
	}

	if (type == NOTIFY_TYPE_ADD) {
		QTreeWidgetItemIterator it(ui->feedTreeWidget);
		QTreeWidgetItem *itemParent;
		while ((itemParent = *it) != NULL) {
			if (itemParent->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt() == feedInfo.parentId) {
				QTreeWidgetItem *item = new RSTreeWidgetItem(mFeedCompareRole);
				itemParent->addChild(item);
				updateFeedItem(item, feedInfo);
				break;
			}
			++it;
		}
	}
	calculateFeedItems();
}

void FeedReaderDialog::optimizeImage()
{
	while (true) {
		FeedReaderOptimizeImageTask *optimizeImageTask = mFeedReader->getOptimizeImageTask();

		if (!optimizeImageTask) {
			return;
		}

		optimizeImageTask->mResult = false;

		QImage image;
		if (image.loadFromData(optimizeImageTask->mImage.data(), optimizeImageTask->mImage.size())) {
			QByteArray optimizedImageData;
			std::string optimizedImageMimeType;
			QImage imageOptDummy;

			switch (optimizeImageTask->mType) {
			case FeedReaderOptimizeImageTask::POSTED:
				if (PostedCreatePostDialog::optimizeImage(image, optimizedImageData, imageOptDummy)) {
					optimizedImageMimeType = "image/jpeg";
					optimizeImageTask->mResult = true;
				}
				break;
			case FeedReaderOptimizeImageTask::SIZE:
				if (ImageUtil::optimizeSizeBytes(optimizedImageData, image, imageOptDummy, "JPG", 0, MAXMESSAGESIZE)) {
					optimizedImageMimeType = "image/jpg";
					optimizeImageTask->mResult = true;
				}
				break;
			}

			if (optimizeImageTask->mResult) {
				if (optimizedImageData.size() < (ssize_t) optimizeImageTask->mImage.size()) {
					/* use optimized image */
					optimizeImageTask->mImageResult.assign(optimizedImageData.begin(), optimizedImageData.end());
					optimizeImageTask->mMimeTypeResult = optimizedImageMimeType;
				} else {
					/* use original image */
					optimizeImageTask->mImageResult = optimizeImageTask->mImage;
					optimizeImageTask->mMimeTypeResult = optimizeImageTask->mMimeType;
				}
			}
		}

		mFeedReader->setOptimizeImageTaskResult(optimizeImageTask);
	}
}

FeedReaderMessageWidget *FeedReaderDialog::feedMessageWidget(uint32_t id)
{
	int tabCount = ui->messageTabWidget->count();
	for (int index = 0; index < tabCount; ++index) {
		FeedReaderMessageWidget *childWidget = dynamic_cast<FeedReaderMessageWidget*>(ui->messageTabWidget->widget(index));
		if (mMessageWidget && childWidget == mMessageWidget) {
			continue;
		}
		if (childWidget && childWidget->feedId() == id) {
			return childWidget;
		}
	}

	return NULL;
}

FeedReaderMessageWidget *FeedReaderDialog::createMessageWidget(uint32_t feedId)
{
	FeedReaderMessageWidget *messageWidget = new FeedReaderMessageWidget(feedId, mFeedReader, mNotify);
	int index = ui->messageTabWidget->addTab(messageWidget, messageWidget->feedName(true));
	ui->messageTabWidget->setTabIcon(index, messageWidget->feedIcon());
	connect(messageWidget, SIGNAL(feedMessageChanged(QWidget*)), this, SLOT(messageTabInfoChanged(QWidget*)));

	return messageWidget;
}

void FeedReaderDialog::feedTreeItemActivated(QTreeWidgetItem *item)
{
	if (!item) {
		ui->feedAddButton->setEnabled(false);
		ui->feedProcessButton->setEnabled(false);
		return;
	}

	ui->feedProcessButton->setEnabled(true);

	if (item->data(COLUMN_FEED_DATA, ROLE_FEED_FOLDER).toBool()) {
		ui->feedAddButton->setEnabled(true);
		return;
	}

	ui->feedAddButton->setEnabled(false);

	uint32_t feedId = item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt();
	/* search exisiting tab */
	FeedReaderMessageWidget *messageWidget = feedMessageWidget(feedId);
	if (!messageWidget) {
		if (mMessageWidget) {
			/* not found, use standard tab */
			messageWidget = mMessageWidget;
			messageWidget->setFeedId(feedId);
		} else {
			/* create new tab */
			messageWidget = createMessageWidget(feedId);
		}
	}

	ui->messageTabWidget->setCurrentWidget(messageWidget);
}

void FeedReaderDialog::feedTreeMiddleButtonClicked(QTreeWidgetItem *item)
{
	if (!item) {
		return;
	}

	openFeedInNewTab(item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt());
}

void FeedReaderDialog::openInNewTab()
{
	openFeedInNewTab(currentFeedId());
}

void FeedReaderDialog::openFeedInNewTab(uint32_t feedId)
{
	if (feedId == 0) {
		return;
	}

	/* search exisiting tab */
	FeedReaderMessageWidget *messageWidget = feedMessageWidget(feedId);
	if (!messageWidget) {
		/* not found, create new tab */
		messageWidget = createMessageWidget(feedId);
	}

	ui->messageTabWidget->setCurrentWidget(messageWidget);
}

void FeedReaderDialog::messageTabCloseRequested(int index)
{
	FeedReaderMessageWidget *messageWidget = dynamic_cast<FeedReaderMessageWidget*>(ui->messageTabWidget->widget(index));
	if (!messageWidget) {
		return;
	}

	if (messageWidget == mMessageWidget) {
		return;
	}

	delete(messageWidget);
}

void FeedReaderDialog::messageTabChanged(int index)
{
	FeedReaderMessageWidget *messageWidget = dynamic_cast<FeedReaderMessageWidget*>(ui->messageTabWidget->widget(index));
	if (!messageWidget) {
		return;
	}

	setCurrentFeedId(messageWidget->feedId());
}

void FeedReaderDialog::messageTabInfoChanged(QWidget *widget)
{
	int index = ui->messageTabWidget->indexOf(widget);
	if (index < 0) {
		return;
	}

	FeedReaderMessageWidget *messageWidget = dynamic_cast<FeedReaderMessageWidget*>(ui->messageTabWidget->widget(index));
	if (!messageWidget) {
		return;
	}

	if (messageWidget != mMessageWidget && messageWidget->feedId() == 0) {
		messageWidget->deleteLater();
		return;
	}

	ui->messageTabWidget->setTabText(index, messageWidget->feedName(true));
	ui->messageTabWidget->setTabIcon(index, messageWidget->feedIcon());
}

void FeedReaderDialog::newFolder()
{
	QInputDialog dialog;
	dialog.setWindowTitle(tr("Add new folder"));
	dialog.setLabelText(tr("Please enter a name for the folder"));
	dialog.setWindowIcon(QIcon(":/images/FeedReader.png"));

	if (dialog.exec() == QDialog::Accepted && !dialog.textValue().isEmpty()) {
		uint32_t feedId;
		RsFeedResult result = mFeedReader->addFolder(currentFeedId(), dialog.textValue().toUtf8().constData(), feedId);
		FeedReaderStringDefs::showError(this, result, tr("Create folder"), tr("Cannot create folder."));
	}
}

void FeedReaderDialog::newFeed()
{
	AddFeedDialog dialog(mFeedReader, mNotify, this);
	dialog.setParent(currentFeedId());
	dialog.exec();
}

void FeedReaderDialog::removeFeed()
{
	uint32_t feedId = currentFeedId();
	if (feedId == 0) {
		return;
	}

	QTreeWidgetItem *item = ui->feedTreeWidget->currentItem();
	if (!item) {
		return;
	}

	bool folder = item->data(COLUMN_FEED_DATA, ROLE_FEED_FOLDER).toBool();
	QString name = item->data(COLUMN_FEED_DATA, ROLE_FEED_NAME).toString();

	if (QMessageBox::question(this, folder ? tr("Remove folder") : tr("Remove feed"), folder ? tr("Do you want to remove the folder %1?").arg(name) : tr("Do you want to remove the feed %1?").arg(name), QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) {
		mFeedReader->removeFeed(feedId);
	}
}

void FeedReaderDialog::editFeed()
{
	uint32_t feedId = currentFeedId();
	if (feedId == 0) {
		return;
	}

	QTreeWidgetItem *item = ui->feedTreeWidget->currentItem();
	if (!item) {
		return;
	}

	bool folder = item->data(COLUMN_FEED_DATA, ROLE_FEED_FOLDER).toBool();
	if (folder) {
		QInputDialog dialog;
		dialog.setWindowTitle(tr("Edit folder"));
		dialog.setLabelText(tr("Please enter a new name for the folder"));
		dialog.setWindowIcon(QIcon(":/images/FeedReader.png"));
		dialog.setTextValue(item->data(COLUMN_FEED_DATA, ROLE_FEED_NAME).toString());

		if (dialog.exec() == QDialog::Accepted && !dialog.textValue().isEmpty()) {
			RsFeedResult result = mFeedReader->setFolder(feedId, dialog.textValue().toUtf8().constData());
			FeedReaderStringDefs::showError(this, result, tr("Create folder"), tr("Cannot create folder."));
		}
	} else {
		AddFeedDialog dialog(mFeedReader, mNotify, this);
		if (!dialog.fillFeed(feedId)) {
			return;
		}
		dialog.exec();

	}
}

void FeedReaderDialog::activateFeed()
{
	uint32_t feedId = currentFeedId();
	if (feedId == 0) {
		return;
	}

	FeedInfo feedInfo;
	if (!mFeedReader->getFeedInfo(feedId, feedInfo)) {
		return;
	}

	if (feedInfo.flag.folder) {
		return;
	}

	feedInfo.flag.deactivated = !feedInfo.flag.deactivated;

	mFeedReader->setFeed(feedId, feedInfo);
}

void FeedReaderDialog::processFeed()
{
	uint32_t feedId = currentFeedId();
	/* empty feed id process all feeds */

	mFeedReader->processFeed(feedId);
}

void FeedReaderDialog::feedTreeReparent(QTreeWidgetItem *item, QTreeWidgetItem *newParent)
{
	if (!item || ! newParent) {
		return;
	}

	uint32_t feedId = item->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt();
	uint32_t parentId = newParent->data(COLUMN_FEED_DATA, ROLE_FEED_ID).toUInt();

	if (feedId == 0) {
		return;
	}

	RsFeedResult result = mFeedReader->setParent(feedId, parentId);
	if (FeedReaderStringDefs::showError(this, result, tr("Move feed"), tr("Cannot move feed."))) {
		return;
	}

	bool expanded = item->isExpanded();
	item->parent()->removeChild(item);
	newParent->addChild(item);
	item->setExpanded(expanded);
	newParent->setExpanded(true);

	calculateFeedItems();
}
