/*******************************************************************************
 * retroshare-gui/src/gui/msgs/MessageWidget.cpp                               *
 *                                                                             *
 * Copyright (C) 2011 by Retroshare Team     <retroshare.project@gmail.com>    *
 *                                                                             *
 * 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 <QMenu>
#include <QToolButton>
#include <QDateTime>
#include <QMessageBox>
#include <QPrinter>
#include <QPrintDialog>
#include <QFile>
#include <QTextStream>
#include <QTextCodec>
#include <QDesktopServices>
#include <QPlainTextEdit>
#include <QDialog>

#include "gui/notifyqt.h"
#include "gui/RetroShareLink.h"
#include "gui/common/TagDefs.h"
#include "gui/common/PeerDefs.h"
#include "gui/common/Emoticons.h"
#include "gui/common/FilesDefs.h"
#include "gui/settings/rsharesettings.h"
#include "MessageComposer.h"
#include "MessageWidget.h"
#include "MessageWindow.h"
#include "util/misc.h"
#include "util/printpreview.h"
#include "util/HandleRichText.h"
#include "util/DateTime.h"
#include "util/QtVersion.h"
#include "util/qtthreadsutils.h"

#include <retroshare/rspeers.h>
#include <retroshare/rsfiles.h>
#include <retroshare/rsmsgs.h>

/* Images for context menu icons */
#define IMAGE_DOWNLOAD         ":/icons/png/download.png"
#define IMAGE_DOWNLOADALL      ":/icons/mail/downloadall.png"

#define COLUMN_FILE_NAME   0
#define COLUMN_FILE_SIZE   1
#define COLUMN_FILE_HASH   2
#define COLUMN_FILE_COUNT  3

#include "gui/msgs/MessageInterface.h"

class RsHtmlMsg : public RsHtml
{
public:
	explicit RsHtmlMsg(uint msgFlags) : RsHtml()
	{
		this->msgFlags = msgFlags;
	}

protected:
	virtual void anchorTextForImg(QDomDocument &doc, QDomElement &element, const RetroShareLink &link, QString &text)
	{
		if (link.type() == RetroShareLink::TYPE_CERTIFICATE) {
			if (msgFlags & RS_MSG_USER_REQUEST) {
				text = QApplication::translate("MessageWidget", "Confirm %1 as friend").arg(link.name());
				return;
			}
			if (msgFlags & RS_MSG_FRIEND_RECOMMENDATION) {
				text = QApplication::translate("MessageWidget", "Add %1 as friend").arg(link.name());
				return;
			}
		}

		RsHtml::anchorTextForImg(doc, element, link, text);
	}

protected:
	uint msgFlags;
};

MessageWidget *MessageWidget::openMsg(const std::string &msgId, bool window)
{
	if (msgId.empty()) {
		return NULL;
	}

	MessageInfo msgInfo;
	if (!rsMail->getMessage(msgId, msgInfo)) {
		std::cerr << "MessageWidget::openMsg() Couldn't find Msg" << std::endl;
		return NULL;
	}

	MessageWindow *parent = NULL;
	if (window) {
		parent = new MessageWindow;
	}
	MessageWidget *msgWidget = new MessageWidget(false, parent);
	msgWidget->isWindow = window;
	msgWidget->fill(msgId);

    if (parent) {
		parent->addWidget(msgWidget);
	}

	if (parent) {
		parent->show();
		parent->activateWindow();
	}

	return msgWidget;
}

/** Constructor */
MessageWidget::MessageWidget(bool controlled, QWidget *parent, Qt::WindowFlags flags)
  : QWidget(parent, flags), toolButtonReply(NULL)
{
	/* Invoke the Qt Designer generated object setup routine */
	ui.setupUi(this);

	isControlled = controlled;
	isWindow = false;
	currMsgFlags = 0;
	expandFiles = false;
	ui.expandButton->hide();

	ui.actionTextBesideIcon->setData(Qt::ToolButtonTextBesideIcon);
	ui.actionIconOnly->setData(Qt::ToolButtonIconOnly);

	connect(ui.msgList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(msgfilelistWidgetCostumPopupMenu(QPoint)));
	connect(ui.expandFilesButton, SIGNAL(clicked()), this, SLOT(togglefileview()));
	connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(getallrecommended()));
	connect(ui.msgText, SIGNAL(anchorClicked(QUrl)), this, SLOT(anchorClicked(QUrl)));
	connect(ui.sendInviteButton, SIGNAL(clicked()), this, SLOT(sendInvite()));
	connect(ui.expandButton, SIGNAL(clicked()), this, SLOT(expandTo()));

	connect(ui.replyButton, SIGNAL(clicked()), this, SLOT(reply()));
	connect(ui.replyallButton, SIGNAL(clicked()), this, SLOT(replyAll()));
	connect(ui.forwardButton, SIGNAL(clicked()), this, SLOT(forward()));
	connect(ui.deleteButton, SIGNAL(clicked()), this, SLOT(remove()));
	
	connect(ui.actionSaveAs, SIGNAL(triggered()), this, SLOT(saveAs()));
	connect(ui.actionPrint, SIGNAL(triggered()), this, SLOT(print()));
	connect(ui.actionPrintPreview, SIGNAL(triggered()), this, SLOT(printPreview()));
	connect(ui.actionIconOnly, SIGNAL(triggered()), this, SLOT(buttonStyle()));
	connect(ui.actionTextBesideIcon, SIGNAL(triggered()), this, SLOT(buttonStyle()));
	
	QAction *viewsource = new QAction(tr("View source"), this);
	viewsource->setShortcut(QKeySequence("CTRL+O"));
	connect(viewsource, SIGNAL(triggered()), this, SLOT(viewSource()));

	ui.imageBlockWidget->addButtonAction(tr("Load images always for this message"), this, SLOT(loadImagesAlways()), true);
	ui.msgText->setImageBlockWidget(ui.imageBlockWidget);

	/* hide the Tree +/- */
	ui.msgList->setRootIsDecorated( false );
	ui.msgList->setSelectionMode( QAbstractItemView::ExtendedSelection );

	/* Set header resize modes and initial section sizes */
	QHeaderView * msglheader = ui.msgList->header () ;
	QHeaderView_setSectionResizeModeColumn(msglheader, COLUMN_FILE_NAME, QHeaderView::Interactive);
	QHeaderView_setSectionResizeModeColumn(msglheader, COLUMN_FILE_SIZE, QHeaderView::Interactive);
	QHeaderView_setSectionResizeModeColumn(msglheader, COLUMN_FILE_HASH, QHeaderView::Interactive);

	msglheader->resizeSection (COLUMN_FILE_NAME, 200);
	msglheader->resizeSection (COLUMN_FILE_SIZE, 100);
	msglheader->resizeSection (COLUMN_FILE_HASH, 200);

	QMenu *moremenu = new QMenu();
	moremenu->addAction(viewsource);
	moremenu->addAction(ui.actionSaveAs);
	moremenu->addAction(ui.actionPrint);
	moremenu->addAction(ui.actionPrintPreview);
	moremenu->addSeparator();
	moremenu->addAction(ui.actionTextBesideIcon);
	moremenu->addAction(ui.actionIconOnly);
	ui.moreButton->setMenu(moremenu);

	QFont font = QFont("Arial", 10, QFont::Bold);
	ui.subjectText->setFont(font);

	ui.trans_ToText->setMaximumHeight(ui.trans_ToText->fontMetrics().lineSpacing()*1.5);
	ui.ccLabel->setVisible(false);
	ui.trans_CCText->setVisible(false);
	ui.trans_CCText->setMaximumHeight(ui.trans_CCText->fontMetrics().lineSpacing()*1.5);
	ui.bccLabel->setVisible(false);
	ui.trans_BCCText->setVisible(false);
	ui.trans_BCCText->setMaximumHeight(ui.trans_BCCText->fontMetrics().lineSpacing()*1.5);

	ui.tagsLabel->setVisible(false);

	ui.msgText->activateLinkClick(false);

	if (isControlled == false) {
		processSettings("MessageWidget", true);
	}

	ui.dateText-> setText("");
	
	ui.info_Frame_Invite->hide();

	mEventHandlerId = 0;
	rsEvents->registerEventsHandler( [this](std::shared_ptr<const RsEvent> event) { RsQThreadUtils::postToObject( [this,event]() { handleEvent_main_thread(event); }); }, mEventHandlerId, RsEventType::MAIL_STATUS );
}

MessageWidget::~MessageWidget()
{
	if (isControlled == false) {
		processSettings("MessageWidget", false);
	}

	rsEvents->unregisterEventsHandler(mEventHandlerId);
}

void MessageWidget::handleEvent_main_thread(std::shared_ptr<const RsEvent> event)
{
	if(event->mType != RsEventType::MAIL_STATUS) {
		return;
	}

	const RsMailStatusEvent *fe = dynamic_cast<const RsMailStatusEvent*>(event.get());
	if (!fe) {
		return;
	}

	switch (fe->mMailStatusEventCode) {
	case RsMailStatusEventCode::MESSAGE_REMOVED:
		if (fe->mChangedMsgIds.find(currMsgId) != fe->mChangedMsgIds.end()) {
			if (isControlled) {
				/* processed by MessagesDialog */
				return;
			}

			/* messages was removed */
			if (isWindow) {
				window()->close();
			} else {
				deleteLater();
			}
		}
		break;
	case RsMailStatusEventCode::TAG_CHANGED:
		messagesTagsChanged();
		break;
	case RsMailStatusEventCode::MESSAGE_SENT:
	case RsMailStatusEventCode::MESSAGE_CHANGED:
	case RsMailStatusEventCode::NEW_MESSAGE:
	case RsMailStatusEventCode::MESSAGE_RECEIVED_ACK:
	case RsMailStatusEventCode::SIGNATURE_FAILED:
		break;
	}
}

void MessageWidget::connectAction(enumActionType actionType, QToolButton* button)
{
	switch (actionType) {
	case ACTION_REMOVE:
		connect(button, SIGNAL(clicked()), this, SLOT(remove()));
		break;
	case ACTION_REPLY:
		connect(button, SIGNAL(clicked()), this, SLOT(reply()));
		toolButtonReply = button;
		break;
	case ACTION_REPLY_ALL:
		connect(button, SIGNAL(clicked()), this, SLOT(replyAll()));
		break;
	case ACTION_FORWARD:
		connect(button, SIGNAL(clicked()), this, SLOT(forward()));
		break;
	case ACTION_PRINT:
		connect(button, SIGNAL(clicked()), this, SLOT(print()));
		break;
	case ACTION_PRINT_PREVIEW:
		connect(button, SIGNAL(clicked()), this, SLOT(printPreview()));
		break;
	case ACTION_SAVE_AS:
		connect(button, SIGNAL(clicked()), this, SLOT(saveAs()));
		break;
	}
}

void MessageWidget::connectAction(enumActionType actionType, QAction *action)
{
	switch (actionType) {
	case ACTION_REMOVE:
		connect(action, SIGNAL(triggered()), this, SLOT(remove()));
		break;
	case ACTION_REPLY:
		connect(action, SIGNAL(triggered()), this, SLOT(reply()));
		break;
	case ACTION_REPLY_ALL:
		connect(action, SIGNAL(triggered()), this, SLOT(replyAll()));
		break;
	case ACTION_FORWARD:
		connect(action, SIGNAL(triggered()), this, SLOT(forward()));
		break;
	case ACTION_PRINT:
		connect(action, SIGNAL(triggered()), this, SLOT(print()));
		break;
	case ACTION_PRINT_PREVIEW:
		connect(action, SIGNAL(triggered()), this, SLOT(printPreview()));
		break;
	case ACTION_SAVE_AS:
		connect(action, SIGNAL(triggered()), this, SLOT(saveAs()));
		break;
	}
}

void MessageWidget::processSettings(const QString &settingsGroup, bool load)
{
	Settings->beginGroup(settingsGroup);

	if (load) {
		// load settings

		// expandFiles
		expandFiles = Settings->value("expandFiles", false).toBool();
		
		// toolbar button style
		Qt::ToolButtonStyle style = (Qt::ToolButtonStyle) Settings->value("ToolButon_Style", Qt::ToolButtonTextBesideIcon).toInt();
		setToolbarButtonStyle(style);
	} else {
		// save settings

		// expandFiles
		Settings->setValue("expandFiles", expandFiles);

		//toolbar button style
		Settings->setValue("ToolButon_Style", ui.replyButton->toolButtonStyle());
	}

	Settings->endGroup();
}

QString MessageWidget::subject(bool noEmpty)
{
	QString subject = ui.subjectText->text();
	if (subject.isEmpty() && noEmpty) {
		return "[" + tr("No subject") + "]";
	}

	return subject;
}

void MessageWidget::msgfilelistWidgetCostumPopupMenu( QPoint /*point*/ )
{
	QMenu contextMnu(this);

    contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_DOWNLOAD), tr("Download"), this, SLOT(getcurrentrecommended()));
    contextMnu.addAction(FilesDefs::getIconFromQtResourcePath(IMAGE_DOWNLOADALL), tr("Download all"), this, SLOT(getallrecommended()));

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

void MessageWidget::togglefileview(bool noUpdate/*=false*/)
{
	/* if msg header visible -> change icon and tooltip
	* three widgets...
	*/

	if (ui.expandFilesButton->isChecked()) {
        ui.expandFilesButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/down-arrow.png")));
		ui.expandFilesButton->setToolTip(tr("Hide the attachment pane"));
	} else {
        ui.expandFilesButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/up-arrow.png")));
		ui.expandFilesButton->setToolTip(tr("Show the attachment pane"));
	}
	if (!noUpdate)
		expandFiles = ui.expandFilesButton->isChecked();

	ui.msgList->setVisible(ui.expandFilesButton->isChecked());
}

/* download the recommendations... */
void MessageWidget::getcurrentrecommended()
{
	MessageInfo msgInfo;
	if (rsMail->getMessage(currMsgId, msgInfo) == false) {
		return;
	}

    std::list<RsPeerId> srcIds;
    if(msgInfo.from.type()==MsgAddress::MSG_ADDRESS_TYPE_RSPEERID)
        srcIds.push_back(msgInfo.from.toRsPeerId());

	QModelIndexList list = ui.msgList->selectionModel()->selectedIndexes();

	std::map<int,FileInfo> files ;

	for (auto &it : list) {
		FileInfo& fi(files[it.row()]) ;

		switch (it.column()) {
		case COLUMN_FILE_NAME:
			fi.fname = it.data().toString().toUtf8().constData();
			break ;
		case COLUMN_FILE_SIZE:
			fi.size = it.data(Qt::UserRole).toULongLong() ;
			break ;
		case COLUMN_FILE_HASH:
			fi.hash = RsFileHash(it.data().toString().toStdString()) ;
			break ;
		}
	}

	for(std::map<int,FileInfo>::const_iterator it(files.begin());it!=files.end();++it) {
		const FileInfo& fi(it->second) ;
		std::cout << "Requesting file " << fi.fname << ", size=" << fi.size << ", hash=" << fi.hash << std::endl ;

		if (rsFiles->FileRequest(fi.fname, fi.hash, fi.size, "", RS_FILE_REQ_ANONYMOUS_ROUTING, srcIds) == false) {
			QMessageBox mb(QObject::tr("File Request canceled"), QObject::tr("The following has not been added to your download list, because you already have it:")+"\n    " + QString::fromUtf8(fi.fname.c_str()), QMessageBox::Critical, QMessageBox::Ok, 0, 0);
			mb.exec();
		}
	}
}

void MessageWidget::getallrecommended()
{
	/* get Message */
	MessageInfo msgInfo;
	if (rsMail->getMessage(currMsgId, msgInfo) == false) {
		return;
	}

	const std::list<FileInfo> &recList = msgInfo.files;
	std::list<FileInfo>::const_iterator it;

	/* do the requests */
	for(it = recList.begin(); it != recList.end(); ++it) {
		std::cerr << "MessageWidget::getallrecommended() Calling File Request" << std::endl;
        std::list<RsPeerId> srcIds;

        if(msgInfo.from.type()==MsgAddress::MSG_ADDRESS_TYPE_RSPEERID)
            srcIds.push_back(msgInfo.from.toRsPeerId());

		rsFiles->FileRequest(it->fname, it->hash, it->size, "", RS_FILE_REQ_ANONYMOUS_ROUTING, srcIds);
	}
}

void MessageWidget::messagesTagsChanged()
{
    showTagLabels();
}

void MessageWidget::clearTagLabels()
{
	/* clear all tags */
	qDeleteAll(tagLabels);
	tagLabels.clear();

	misc::clearLayout(ui.tagLayout);

	ui.tagsLabel->setVisible(false);
}

void MessageWidget::showTagLabels()
{
	clearTagLabels();

	if (currMsgId.empty()) {
		return;
	}

	MsgTagInfo tagInfo;
	rsMail->getMessageTag(currMsgId, tagInfo);

    if (!tagInfo.empty())
    {
		ui.tagsLabel->setVisible(true);

		MsgTagType Tags;
		rsMail->getMessageTagTypes(Tags);

		std::map<uint32_t, std::pair<std::string, uint32_t> >::iterator Tag;
        for (auto tag:tagInfo)
        {
            Tag = Tags.types.find(tag);
			if (Tag != Tags.types.end()) {
				QLabel *tagLabel = new QLabel(TagDefs::name(Tag->first, Tag->second.first), this);
				tagLabel->setMaximumHeight(16);
				tagLabel->setStyleSheet(TagDefs::labelStyleSheet(Tag->second.second));
				tagLabels.push_back(tagLabel);
				ui.tagLayout->addWidget(tagLabel);
				ui.tagLayout->addSpacing(3);
			}
		}
		ui.tagLayout->addStretch();
	} else {
		ui.tagsLabel->setVisible(false);
	}
}

void MessageWidget::refill()
{
	//uint32_t msg_id = currMsgId ;
	//currMsgId = 0 ;

	//fill(msg_id) ;
}
void MessageWidget::fill(const std::string &msgId)
{
//	if (currMsgId == msgId) {
//		// message doesn't changed
//		return;
//	}

	currMsgId = msgId;

	if (currMsgId.empty()) {
		/* blank it */
		ui.dateText-> setText("");
		ui.trans_ToText->setText("");
		ui.fromText->setText("");
		ui.filesText->setText("");

		ui.ccLabel->setVisible(false);
		ui.trans_CCText->setVisible(false);
		ui.trans_CCText->clear();

		ui.bccLabel->setVisible(false);
		ui.trans_BCCText->setVisible(false);
		ui.trans_BCCText->clear();

		ui.subjectText->setText("");
		ui.msgList->clear();
		ui.msgText->clear();
		ui.msgText->resetImagesStatus(false);

		clearTagLabels();
		checkLength();

		ui.info_Frame_Invite->hide();
		ui.expandFilesButton->setChecked(false);
		ui.downloadButton->setEnabled(false);
		togglefileview(true);

		ui.replyButton->setEnabled(false);
		ui.replyallButton->setEnabled(false);
		ui.forwardButton->setEnabled(false);
		ui.deleteButton->setEnabled(false);
		ui.moreButton->setEnabled(false);

		ui.expandButton->hide();
		ui.trans_ToText->setMaximumHeight(ui.trans_ToText->fontMetrics().lineSpacing()*1.5);

		currMsgFlags = 0;

		return;
	}

	clearTagLabels();


	ui.replyButton->setEnabled(true);
	ui.replyallButton->setEnabled(true);
	ui.forwardButton->setEnabled(true);
	ui.deleteButton->setEnabled(true);
	ui.moreButton->setEnabled(true);

	MessageInfo msgInfo;
	if (rsMail->getMessage(currMsgId, msgInfo) == false) {
		std::cerr << "MessageWidget::fill() Couldn't find Msg" << std::endl;
		return;
	}
	
    if (msgInfo.msgflags & RS_MSG_USER_REQUEST)
        if(msgInfo.from.type() == MsgAddress::MSG_ADDRESS_TYPE_RSPEERID)
        {
            ui.info_Frame_Invite->show();
            ui.sendInviteButton->hide();
            ui.infoLabel_Invite->setText(tr("You got an invite to make friend! You may accept this request."));
        }
        else
        {
            ui.info_Frame_Invite->show();
            ui.sendInviteButton->show();
            ui.infoLabel_Invite->setText(tr("You got an invite to make friend! You may accept this request and send your own Certificate back"));
        }
    else
        ui.info_Frame_Invite->hide();

	const std::list<FileInfo> &recList = msgInfo.files;
	std::list<FileInfo>::const_iterator it;

	ui.msgList->clear();

	QList<QTreeWidgetItem*> items;
	for (it = recList.begin(); it != recList.end(); ++it) {
		QTreeWidgetItem *item = new QTreeWidgetItem;
		item->setText(COLUMN_FILE_NAME, QString::fromUtf8(it->fname.c_str()));
		item->setIcon(COLUMN_FILE_NAME, FilesDefs::getIconFromFileType(it->fname.c_str()));
		item->setText(COLUMN_FILE_SIZE, misc::friendlyUnit(it->size));
		item->setData(COLUMN_FILE_SIZE, Qt::UserRole, QVariant(qulonglong(it->size)) );
		item->setText(COLUMN_FILE_HASH, QString::fromStdString(it->hash.toStdString()));
		item->setTextAlignment( COLUMN_FILE_SIZE, Qt::AlignRight );

		/* add to the list */
		items.append(item);
	}

	/* add the items in! */
	ui.msgList->insertTopLevelItems(0, items);
	ui.expandFilesButton->setChecked(expandFiles && (items.count()>0) );
	ui.downloadButton->setEnabled(items.count()>0);
	togglefileview(true);

	/* iterate through the sources */
	RetroShareLink link;
    QString to_text,cc_text,bcc_text;

    for(auto m:msgInfo.destinations)
    {
        if(m.type()==MsgAddress::MSG_ADDRESS_TYPE_RSGXSID)
            link = RetroShareLink::createMessage(m.toGxsId(), "");
        else
            link = RetroShareLink::createMessage(m.toRsPeerId(), "");

		if (link.valid())
            switch(m.mode())
            {
            case MsgAddress::MSG_ADDRESS_MODE_TO: to_text += link.toHtml() + "   "; break;
            case MsgAddress::MSG_ADDRESS_MODE_CC: cc_text += link.toHtml() + "   "; break;
            case MsgAddress::MSG_ADDRESS_MODE_BCC: bcc_text += link.toHtml() + "   "; break;
            default: break;
            }
    }

    ui.trans_ToText->setText(to_text);

	int recipientsCount = ui.trans_ToText->toPlainText().split(QRegExp("(\\s|\\n|\\r)+"), QString::SkipEmptyParts).count();
	ui.expandButton->setText( QString::number(recipientsCount)+ " " + tr("more"));

	if (recipientsCount >=20) {
		ui.expandButton->show();
	} else {
		ui.expandButton->hide();
		ui.expandButton->setChecked(false);
		ui.trans_ToText->setMaximumHeight(ui.trans_ToText->fontMetrics().lineSpacing()*1.5);
	}

    if (!cc_text.isNull())
	{
		ui.ccLabel->setVisible(true);
		ui.trans_CCText->setVisible(true);

        ui.trans_CCText->setText(cc_text);
	} else {
		ui.ccLabel->setVisible(false);
		ui.trans_CCText->setVisible(false);
		ui.trans_CCText->clear();
	}

    if (!bcc_text.isNull())
	{
		ui.bccLabel->setVisible(true);
		ui.trans_BCCText->setVisible(true);

        ui.trans_BCCText->setText(bcc_text);
	} else {
		ui.bccLabel->setVisible(false);
		ui.trans_BCCText->setVisible(false);
		ui.trans_BCCText->clear();
	}

	ui.dateText->setText(DateTime::formatDateTime(msgInfo.ts));

    RsPeerId ownId = rsPeers->getOwnId();
	QString tooltip_string ;

//	if ((msgInfo.msgflags & RS_MSG_BOXMASK) == RS_MSG_OUTBOX) // outgoing message are from me
//	{
//		tooltip_string = PeerDefs::rsidFromId(ownId) ;
//		link.createMessage(ownId, "");
//	}

    if(msgInfo.from.type()==Rs::Msgs::MsgAddress::MSG_ADDRESS_TYPE_RSGXSID)	// distant message
	{
        tooltip_string = PeerDefs::rsidFromId(msgInfo.from.toGxsId()) ;
        link = RetroShareLink::createMessage(msgInfo.from.toGxsId(), "");
	}
	else
	{
        tooltip_string = PeerDefs::rsidFromId(msgInfo.from.toRsPeerId()) ;
        link = RetroShareLink::createMessage(msgInfo.from.toRsPeerId(), "");
	}

    if ((msgInfo.msgflags & RS_MSG_SYSTEM) && msgInfo.from.toRsPeerId() == ownId)
    {
		ui.fromText->setText("[Notification]");
		if (toolButtonReply) toolButtonReply->setEnabled(false);
    }
    else
    {
		ui.fromText->setText(link.toHtml());
		ui.fromText->setToolTip(tooltip_string) ;
		if (toolButtonReply) toolButtonReply->setEnabled(true);
	}

	ui.subjectText->setText(QString::fromUtf8(msgInfo.title.c_str()));
	
	unsigned int formatTextFlag = RSHTML_FORMATTEXT_EMBED_LINKS ;

	// embed smileys ?
	if (Settings->valueFromGroup(QString("Messages"), QString::fromUtf8("Emoticons"), true).toBool()) {
		formatTextFlag |= RSHTML_FORMATTEXT_EMBED_SMILEYS ;
	}
    QString text = RsHtmlMsg(msgInfo.msgflags).formatText(ui.msgText->document(), QString::fromUtf8(msgInfo.msg.c_str()), formatTextFlag);
	ui.msgText->resetImagesStatus(Settings->getMsgLoadEmbeddedImages() || (msgInfo.msgflags & RS_MSG_LOAD_EMBEDDED_IMAGES));
	ui.msgText->setHtml(text);

	ui.filesText->setText(QString("%1").arg(msgInfo.count));
	ui.filesSize->setText(QString(misc::friendlyUnit(msgInfo.size)));

	showTagLabels();
	checkLength();

	currMsgFlags = msgInfo.msgflags;
}

void MessageWidget::remove()
{
	MessageInfo msgInfo;
	if (rsMail->getMessage(currMsgId, msgInfo) == false) {
		std::cerr << "MessageWidget::fill() Couldn't find Msg" << std::endl;
		return;
	}

#ifdef TO_REMOVE
    bool deleteReal = false;
	if (msgInfo.msgflags & RS_MSG_TRASH) {
		deleteReal = true;
	} else {
		if (QApplication::keyboardModifiers() & Qt::ShiftModifier) {
			deleteReal = true;
		}
	}

	if (deleteReal) {
		rsMail->MessageDelete(currMsgId);
	} else {
		rsMail->MessageToTrash(currMsgId, true);
	}

	if (isWindow) {
		window()->close();
	} else {
		if (isControlled) {
			currMsgId.clear();
			fill(currMsgId);
		} else {
			deleteLater();
		}
	}
#endif
    emit messageRemovalRequested(currMsgId);
}

void MessageWidget::print()
{
#ifndef QT_NO_PRINTER
	QPrinter printer(QPrinter::HighResolution);
	printer.setFullPage(true);
	QPrintDialog *dlg = new QPrintDialog(&printer, this);
	if (ui.msgText->textCursor().hasSelection())
		dlg->addEnabledOption(QAbstractPrintDialog::PrintSelection);
	dlg->setWindowTitle(tr("Print Document"));
	if (dlg->exec() == QDialog::Accepted) {
		ui.msgText->print(&printer);
	}
	delete dlg;
#endif
}

void MessageWidget::printPreview()
{
	PrintPreview *preview = new PrintPreview(ui.msgText->document(), this);
	preview->setWindowModality(Qt::WindowModal);
	preview->setAttribute(Qt::WA_DeleteOnClose);
	preview->show();

	/* window will destroy itself! */
}

void MessageWidget::saveAs()
{
	QString filename;
	if (misc::getSaveFileName(window(), RshareSettings::LASTDIR_MESSAGES, tr("Save as..."), tr("HTML-Files (*.htm *.html);;All Files (*)"), filename)) {
		QFile file(filename);
		if (!file.open(QFile::WriteOnly))
			return;
		QTextStream ts(&file);
		ts.setCodec(QTextCodec::codecForName("UTF-8"));
		ts << ui.msgText->document()->toHtml("UTF-8");
		ui.msgText->document()->setModified(false);
	}
}

void MessageWidget::reply()
{
	/* put msg on msgBoard, and switch to it. */

	if (currMsgId.empty()) {
		return;
	}

	MessageComposer *msgComposer = MessageComposer::replyMsg(currMsgId, false);
	if (msgComposer == NULL) {
		return;
	}

	msgComposer->show();
	msgComposer->activateWindow();

	/* window will destroy itself! */
}

void MessageWidget::replyAll()
{
	/* put msg on msgBoard, and switch to it. */

	if (currMsgId.empty()) {
		return;
	}

	MessageComposer *msgComposer = MessageComposer::replyMsg(currMsgId, true);
	if (msgComposer == NULL) {
		return;
	}

	msgComposer->show();
	msgComposer->activateWindow();

	/* window will destroy itself! */
}

void MessageWidget::forward()
{
	/* put msg on msgBoard, and switch to it. */

	if (currMsgId.empty()) {
		return;
	}

	MessageComposer *msgComposer = MessageComposer::forwardMsg(currMsgId);
	if (msgComposer == NULL) {
		return;
	}

	msgComposer->show();
	msgComposer->activateWindow();

	/* window will destroy itself! */
}

void MessageWidget::anchorClicked(const QUrl &url)
{
	RetroShareLink link(url);

	if(link.valid())
	{
		if (link.type() == RetroShareLink::TYPE_CERTIFICATE && currMsgFlags & RS_MSG_USER_REQUEST) {
			std::cerr << "(WW) Calling some disabled code in MessageWidget::anchorClicked(). Please contact the developpers." << std::endl;
			//	link.setSubType(RSLINK_SUBTYPE_CERTIFICATE_USER_REQUEST);
		}

		QList<RetroShareLink> links;
		links.append(link);
		RetroShareLink::process(links);
	}
    else
		QDesktopServices::openUrl(url) ;
}

void MessageWidget::loadImagesAlways()
{
	if (currMsgId.empty()) {
		return;
	}

	rsMail->MessageLoadEmbeddedImages(currMsgId, true);
}

void MessageWidget::sendInvite()
{
    MessageInfo mi;

    if (!rsMail)
        return;

    if (!rsMail->getMessage(currMsgId, mi))
        return;

    if(mi.from.type()!=MsgAddress::MSG_ADDRESS_TYPE_RSGXSID)
        return;

    //if ((QMessageBox::question(this, tr("Send invite?"),tr("Do you really want to send an invite with your Certificate?"),QMessageBox::Yes, QMessageBox::No))== QMessageBox::Yes)
    MessageComposer::sendInvite(mi.from.toGxsId(),false);
}

void MessageWidget::setToolbarButtonStyle(Qt::ToolButtonStyle style)
{
	ui.deleteButton->setToolButtonStyle(style);
	ui.replyButton->setToolButtonStyle(style);
	ui.replyallButton->setToolButtonStyle(style);
	ui.forwardButton->setToolButtonStyle(style);
	ui.moreButton->setToolButtonStyle(style);
}

void MessageWidget::buttonStyle()
{
	setToolbarButtonStyle((Qt::ToolButtonStyle) dynamic_cast<QAction*>(sender())->data().toInt());
}

void MessageWidget::viewSource()
{
	QDialog *dialog = new QDialog(this);
	QPlainTextEdit *pte = new QPlainTextEdit(dialog);
	pte->setPlainText( ui.msgText->toHtml() );
	QGridLayout *gl = new QGridLayout(dialog);
	gl->addWidget(pte,0,0,1,1);
	dialog->setWindowTitle(tr("Document source"));
	dialog->resize(500, 400);

	dialog->exec();

	ui.msgText->setHtml(pte->toPlainText());

	delete dialog;
}

void MessageWidget::checkLength()
{
	QString text;
	RsHtml::optimizeHtml(ui.msgText, text);
	std::wstring msg = text.toStdWString();
	int charlength = msg.length();

	text = tr("%1 (%2) ").arg(charlength).arg(misc::friendlyUnit(charlength));

	ui.sizeLabel->setText(text);
}

void MessageWidget::expandTo()
{
	if (ui.expandButton->isChecked()) {
		ui.trans_ToText->setMaximumHeight(ui.trans_ToText->fontMetrics().lineSpacing()*3.5);
		ui.expandButton->setToolTip(tr("Show less"));
	} else {
		ui.trans_ToText->setMaximumHeight(ui.trans_ToText->fontMetrics().lineSpacing()*1.5);
		ui.expandButton->setToolTip(tr("Show more"));
	}
}
