/*
 * Connect Progress Dialog
 *
 * Copyright 2012-2013 by Robert Fernie.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License Version 2.1 as published by the Free Software Foundation.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 *
 * Please report all bugs and problems to "retroshare@lunamutt.com".
 *
 */


#include "gui/connect/ConnectProgressDialog.h"

#include <QTimer>

#include <map>
#include <time.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsconfig.h>
#include <retroshare/rsdht.h>

#include "gui/common/StatusDefs.h"

/* maintain one static dialog per SSL ID */

static std::map<std::string, ConnectProgressDialog *> instances;

int calcProgress(time_t now, time_t start, int period50, int period75, int period100);

ConnectProgressDialog *ConnectProgressDialog::instance(const std::string& peer_id)
{
	std::map<std::string, ConnectProgressDialog *>::iterator it;
	it = instances.find(peer_id);
	if (it != instances.end())
	{
		return it->second;
	}

	ConnectProgressDialog *d = new ConnectProgressDialog(peer_id);
	instances[peer_id] = d;
	return d;
}

ConnectProgressDialog::ConnectProgressDialog(const std::string& id, QWidget *parent, Qt::WindowFlags flags)
	:QDialog(parent, flags), mId(id), ui(new Ui::ConnectProgressDialog)
{
	ui->setupUi(this);
	setAttribute(Qt::WA_DeleteOnClose, true);

	ui->headerFrame->setHeaderImage(QPixmap(":/images/user/identityinfo64.png"));
	ui->headerFrame->setHeaderText(tr("Connection Assistant"));

	connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(stopAndClose()));
}

ConnectProgressDialog::~ConnectProgressDialog()
{
	std::map<std::string, ConnectProgressDialog *>::iterator it;
	it = instances.find(mId);
	if (it != instances.end())
	{
		instances.erase(it);
	}
}

void ConnectProgressDialog::showProgress(const std::string& peer_id)
{
    ConnectProgressDialog *d = instance(peer_id);

    d->initDialog();
    d->show();
    d->raise();
    d->activateWindow();

    /* window will destroy itself! */
}

const uint32_t CONNECT_STATE_INIT		= 0;
const uint32_t CONNECT_STATE_PROGRESS		= 1;
const uint32_t CONNECT_STATE_CONNECTED		= 2;
const uint32_t CONNECT_STATE_DENIED		= 3;
const uint32_t CONNECT_STATE_CLOSED		= 4;
const uint32_t CONNECT_STATE_FAILED		= 5;

const uint32_t CONNECT_DHT_INIT		= 0;
const uint32_t CONNECT_DHT_OKAY		= 2;

const uint32_t CONNECT_DHT_FAIL		= 3;
const uint32_t CONNECT_DHT_DISABLED	= 4;


const uint32_t CONNECT_LOOKUP_INIT		= 0;
const uint32_t CONNECT_LOOKUP_SEARCH		= 1;
const uint32_t CONNECT_LOOKUP_OFFLINE		= 2;
const uint32_t CONNECT_LOOKUP_UNREACHABLE	= 3;
const uint32_t CONNECT_LOOKUP_ONLINE		= 4;
const uint32_t CONNECT_LOOKUP_NODHTCONFIG	= 5;
const uint32_t CONNECT_LOOKUP_FAIL		= 6;

const uint32_t CONNECT_UDP_INIT			= 0;
const uint32_t CONNECT_UDP_PROGRESS		= 1;
const uint32_t CONNECT_UDP_FAIL			= 2;

const uint32_t CONNECT_CONTACT_NONE		= 0;
const uint32_t CONNECT_CONTACT_CONNECTED	= 1;

/* at a minimum allow 30 secs for TCP connections */
const int MINIMUM_CONNECT_PERIOD = 30;

/* overall timeout */
const int CONNECT_TIMEOUT_PERIOD = 1800;

/* assume it will take 5 minute to complete DHT load (should take 30 secs, and 2-3 minutes from cold start) */
const int CONNECT_DHT_TYPICAL = 30;
const int CONNECT_DHT_SLOW   = 120;
const int CONNECT_DHT_PERIOD = 300;

/* need to shorten this time (DHT work) */
const int CONNECT_LOOKUP_TYPICAL = 200;
const int CONNECT_LOOKUP_SLOW    = 300;
const int CONNECT_LOOKUP_PERIOD  = 600;

/* Udp can take ages ... */
const int CONNECT_UDP_TYPICAL = 150;
const int CONNECT_UDP_SLOW   = 300;
const int CONNECT_UDP_PERIOD = 600;

/* connection must stay up for 5 seconds to be considered okay */
const int REQUIRED_CONTACT_PERIOD = 5;

void ConnectProgressDialog::initDialog()
{
	mTimer = new QTimer(this);
	connect(mTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
     	mTimer->start(250);

	mState = CONNECT_STATE_PROGRESS;
	mInitTS = time(NULL);
	mDhtStatus = CONNECT_DHT_INIT;

	mLookupTS = 0;
	mLookupStatus = CONNECT_LOOKUP_INIT;

	mContactTS = 0;
	mContactState = CONNECT_CONTACT_NONE;

	mUdpTS = 0;
	mUdpStatus = CONNECT_UDP_INIT;

	ui->progressFrame->setEnabled(true);
	/* initialise GUI data */
	ui->NetResult->setText(tr("N/A"));
	ui->ContactResult->setText(tr("N/A"));

	ui->DhtResult->setText(tr("DHT Startup"));
	ui->DhtProgressBar->setValue(0);

	ui->LookupResult->setText(tr("N/A"));
	ui->LookupProgressBar->setValue(0);

	ui->UdpResult->setText(tr("N/A"));
	ui->UdpProgressBar->setValue(0);

	sayInProgress();

	if (rsPeers->isFriend(mId))
	{
		/* okay */
		std::string name = rsPeers->getPeerName(mId);
		QString connectName = QString::fromUtf8(name.c_str());
		connectName += " (";
		connectName += QString::fromStdString(mId).left(10);
		connectName += "...)";
		ui->connectId->setText(connectName);
	}
	else
	{
		ui->connectId->setText(tr("Invalid Peer ID"));

		/* list Error */
		mState = CONNECT_STATE_FAILED;
		sayInvalidPeer();
		return;
	}

	if (rsPeers->isOnline(mId))
	{
		mState = CONNECT_STATE_CONNECTED;
		sayConnected();
		return;
	}
}

void ConnectProgressDialog::updateStatus()
{

	if (time(NULL) > mInitTS + CONNECT_TIMEOUT_PERIOD)
	{
		sayConnectTimeout();
		mState = CONNECT_STATE_FAILED;
	}

	switch(mState)
	{
		case CONNECT_STATE_PROGRESS:

			updateNetworkStatus();
			updateContactStatus();
			updateDhtStatus();
			updateLookupStatus();
			updateUdpStatus();

			return;
			break;

		default:
		case CONNECT_STATE_CLOSED:
		case CONNECT_STATE_FAILED:
		case CONNECT_STATE_DENIED:
		case CONNECT_STATE_CONNECTED:
			break;
	}

	/* shutdown actions */
	ui->progressFrame->setEnabled(false);
	mTimer->stop();
}


void ConnectProgressDialog::stopAndClose()
{
	mState = CONNECT_STATE_CLOSED;
	if (mTimer)
	{
		mTimer->stop();
	}
	close();
}

void ConnectProgressDialog::updateNetworkStatus()
{
	uint32_t netState = rsConfig->getNetState();

	QLabel *label = ui->NetResult;
	switch(netState)
	{
		case RSNET_NETSTATE_BAD_UNKNOWN:
			label->setText(tr("Unknown State"));
			break;
		case RSNET_NETSTATE_BAD_OFFLINE:
			label->setText(tr("Offline"));
			break;
		case RSNET_NETSTATE_BAD_NATSYM:
			label->setText(tr("Behind Symmetric NAT"));
			break;
		case RSNET_NETSTATE_BAD_NODHT_NAT:
			label->setText(tr("Behind NAT & No DHT"));
			break;
		case RSNET_NETSTATE_WARNING_RESTART:
			label->setText(tr("NET Restart"));
			break;
		case RSNET_NETSTATE_WARNING_NATTED:
			label->setText(tr("Behind NAT"));
			break;
		case RSNET_NETSTATE_WARNING_NODHT:
			label->setText(tr("No DHT"));
			break;
		case RSNET_NETSTATE_GOOD:
			label->setText(tr("NET STATE GOOD!"));
			break;
		case RSNET_NETSTATE_ADV_FORWARD:
			label->setText(tr("UNVERIFIABLE FORWARD!"));
			break;
		case RSNET_NETSTATE_ADV_DARK_FORWARD:
			label->setText(tr("UNVERIFIABLE FORWARD & NO DHT"));
			break;
	}
}

void ConnectProgressDialog::updateContactStatus()
{
	/* lookup peer details - and try those addresses */

	RsPeerDetails details;
	if (!rsPeers->getPeerDetails(mId, details))
		return;

	QString status = StatusDefs::connectStateString(details);
	ui->ContactResult->setText(status);

	time_t now = time(NULL);

	/* now if it says connected - Alter overall state, after REQUIRED CONTACT PERIOD */
	if (rsPeers->isOnline(mId))
	{
		switch(mContactState)
		{
			default:
			case CONNECT_CONTACT_NONE:
				{
					mContactTS = now;
					mContactState = CONNECT_CONTACT_CONNECTED;
				}
				break;
			case CONNECT_CONTACT_CONNECTED:
				if (now > mContactTS + REQUIRED_CONTACT_PERIOD)
				{
					/* still connected, flag as SUCCESS */
					mState = CONNECT_STATE_CONNECTED;
					sayConnected();
				}
				break;
		}
	}
	else if (details.wasDeniedConnection)
	{
		if (details.deniedTS > mInitTS)
		{
			/* connection dropped, flag as DENIED */
			mState = CONNECT_STATE_DENIED;
			sayDenied();
		}
	}
}


void ConnectProgressDialog::updateDhtStatus()
{
	/* if DHT is disabled -> mark bad */
	/* if DHT is red -> mark bad, probable cause missing bdboot.txt */
	/* if DHT is starting, run progress bar */

	time_t now = time(NULL);
	switch(mDhtStatus)
	{
		case CONNECT_DHT_OKAY:
		case CONNECT_DHT_FAIL:
			return;
			break;

		case CONNECT_DHT_DISABLED:

			/* Ensure minimum time for direct TCP connections */
			if (now > mInitTS + MINIMUM_CONNECT_PERIOD)
			{
				mState = CONNECT_STATE_FAILED;
				sayDHTOffline();
			}
			return;
			break;

		default: /* still in progress */
		case CONNECT_DHT_INIT:
			if (now > mInitTS + CONNECT_DHT_PERIOD)
			{
				ui->DhtProgressBar->setValue(100);
				ui->DhtResult->setText(tr("DHT Failed"));
				mDhtStatus = CONNECT_DHT_FAIL;
				mState = CONNECT_STATE_FAILED;
		
				sayDHTFailed();
				return;
			}
			break;
	}



	RsConfigNetStatus status;
	rsConfig->getConfigNetStatus(status);

	if (!status.DHTActive)
	{
		mDhtStatus = CONNECT_DHT_DISABLED;
		
		/* ERROR message */
		ui->DhtProgressBar->setValue(100);
		ui->DhtResult->setText(tr("DHT Disabled"));

		return;
	}

	if (status.netDhtOk && (status.netDhtNetSize > 100))
	{
		if (status.netDhtRsNetSize > 10)
		{
			ui->DhtProgressBar->setValue(100);
			ui->DhtResult->setText(tr("DHT Okay"));
			mDhtStatus = CONNECT_DHT_OKAY;
			return;
		}
		ui->DhtResult->setText(tr("Finding RS Peers"));
	}

	ui->DhtProgressBar->setValue(calcProgress(now, mInitTS, CONNECT_DHT_TYPICAL, CONNECT_DHT_SLOW, CONNECT_DHT_PERIOD));

	return;
}


void ConnectProgressDialog::updateLookupStatus()
{
	switch(mLookupStatus)
	{
		case CONNECT_LOOKUP_OFFLINE:
		case CONNECT_LOOKUP_NODHTCONFIG:

			/* Ensure minimum time for direct TCP connections */
			if (time(NULL) > mInitTS + MINIMUM_CONNECT_PERIOD)
			{
				mState = CONNECT_STATE_FAILED;

				if (mLookupStatus == CONNECT_LOOKUP_NODHTCONFIG)
				{
					sayPeerNoDhtConfig();
				}
				else
				{
					sayPeerOffline();
				}
			}

		case CONNECT_LOOKUP_FAIL:
		case CONNECT_LOOKUP_ONLINE:
		case CONNECT_LOOKUP_UNREACHABLE:
			return;
			break;

		default:
			break;
	}

	time_t now = time(NULL);
	switch(mDhtStatus)
	{
		case CONNECT_DHT_DISABLED:
		case CONNECT_DHT_FAIL:
			mLookupStatus = CONNECT_LOOKUP_FAIL;
			ui->LookupProgressBar->setValue(0);
			ui->LookupResult->setText(tr("Lookup requires DHT"));

		case CONNECT_DHT_INIT:

			return;
			break;

		case CONNECT_DHT_OKAY:
	
			if (mLookupStatus == CONNECT_LOOKUP_INIT)
			{
				mLookupStatus = CONNECT_LOOKUP_SEARCH;
				ui->LookupResult->setText(tr("Searching DHT"));
				mLookupTS = now;
			}
	}




	if (now > mLookupTS + CONNECT_LOOKUP_PERIOD)
	{
		ui->LookupProgressBar->setValue(100);
		ui->LookupResult->setText(tr("Lookup Timeout"));
		mLookupStatus = CONNECT_LOOKUP_FAIL;

		mState = CONNECT_STATE_FAILED;
		sayLookupTimeout();

		return;
	}

	ui->LookupProgressBar->setValue(calcProgress(now, mLookupTS, CONNECT_LOOKUP_TYPICAL, CONNECT_LOOKUP_SLOW, CONNECT_LOOKUP_PERIOD));

	/* now actually look at the DHT Details */
	RsDhtNetPeer status;
	rsDht->getNetPeerStatus(mId, status);

	switch(status.mDhtState)
	{
		default:
		case RSDHT_PEERDHT_NOT_ACTIVE:
			ui->LookupProgressBar->setValue(0);
			ui->LookupResult->setText(tr("Peer DHT NOT ACTIVE"));
			mLookupStatus = CONNECT_LOOKUP_NODHTCONFIG;
			break;
		case RSDHT_PEERDHT_SEARCHING:
			ui->LookupResult->setText(tr("Searching"));
			break;
		case RSDHT_PEERDHT_FAILURE:
			ui->LookupProgressBar->setValue(0);
			ui->LookupResult->setText(tr("Lookup Failure"));
			mLookupStatus = CONNECT_LOOKUP_FAIL;
			break;
		case RSDHT_PEERDHT_OFFLINE:
			ui->LookupProgressBar->setValue(100);
			ui->LookupResult->setText(tr("Peer Offline"));
			mLookupStatus = CONNECT_LOOKUP_OFFLINE;
			break;
		case RSDHT_PEERDHT_UNREACHABLE:
			ui->LookupProgressBar->setValue(100);
			ui->LookupResult->setText(tr("Peer Firewalled"));
			mLookupStatus = CONNECT_LOOKUP_UNREACHABLE;
			break;
		case RSDHT_PEERDHT_ONLINE:
			ui->LookupProgressBar->setValue(100);
			ui->LookupResult->setText(tr("Peer Online"));
			mLookupStatus = CONNECT_LOOKUP_ONLINE;
			break;
	}
}



void ConnectProgressDialog::updateUdpStatus()
{

	switch(mLookupStatus)
	{
		default:
		case CONNECT_LOOKUP_OFFLINE:
		case CONNECT_LOOKUP_NODHTCONFIG:
		case CONNECT_LOOKUP_FAIL:
			return;
			break;

		case CONNECT_LOOKUP_ONLINE:
		case CONNECT_LOOKUP_UNREACHABLE:
			break;
	}

	switch(mUdpStatus)
	{
		case CONNECT_UDP_FAIL:
			return;
			break;
		case CONNECT_UDP_INIT:
			mUdpTS = time(NULL);
			mUdpStatus = CONNECT_UDP_PROGRESS;
			ui->UdpResult->setText(tr("UDP Setup"));
			break;
		default:
		case CONNECT_UDP_PROGRESS:
			break;
	}


	time_t now = time(NULL);
	if (now > mUdpTS + CONNECT_UDP_PERIOD)
	{
		ui->UdpProgressBar->setValue(100);
		ui->UdpResult->setText(tr("UDP Connect Timeout"));
		mUdpStatus = CONNECT_UDP_FAIL;

		mState = CONNECT_STATE_FAILED;
		sayUdpTimeout();

		return;
	}

	ui->UdpProgressBar->setValue(calcProgress(now, mUdpTS, CONNECT_UDP_TYPICAL, CONNECT_UDP_SLOW, CONNECT_UDP_PERIOD));

	/* now lookup details from Dht */
	RsDhtNetPeer status;
	rsDht->getNetPeerStatus(mId, status);

	QString fullString = QString::fromStdString(status.mConnectState);
	QString connectString = fullString.section(':',0,0);
	ui->UdpResult->setText(connectString);

	if (connectString == "Failed Wait")
	{
		/* Ensure minimum time for direct TCP connections */
		if (now > mInitTS + MINIMUM_CONNECT_PERIOD)
		{
			if (status.mCbPeerMsg == "ERROR : END:AUTH_DENIED")
			{
				/* disaster - connection not allowed */
				mState = CONNECT_STATE_DENIED;
				sayUdpDenied();
			}
			else
			{
				/* disaster - udp failed */
				mState = CONNECT_STATE_FAILED;
				sayUdpFailed();
			}
		}
	}
}


int calcProgress(time_t now, time_t start, int period50, int period75, int period100)
{
	int dt = now - start;
	if (dt < 0)
		return 0;
	if (dt > period100)
		return 100;

	if (dt < period50)
	{
		return 50 * (dt / (float) period50);
	}

	if (dt < period75)
	{
		return 50  + 25 * ((dt - period50) / (float) (period75 - period50));
	}
	return 75  + 25 * ((dt - period75) / (float) (period100 - period75));
}



	













/*********** Status ***********/


const uint32_t MESSAGE_STATUS_INPROGRESS	= 1;
const uint32_t MESSAGE_STATUS_SUCCESS		= 2;
const uint32_t MESSAGE_STATUS_CONFIG_ERROR	= 3;
const uint32_t MESSAGE_STATUS_PEER_ERROR	= 4;
const uint32_t MESSAGE_STATUS_UNKNOWN_ERROR	= 5;

void ConnectProgressDialog::sayInProgress()
{
	QString title = tr("Connection In Progress");
	QString message = tr("Initial connections can take a while, please be patient");
	message += "\n\n";
	message += tr("If an error is detected it will be displayed here");
	message += "\n\n";
	message += tr("You can close this dialog at any time");
	message += "\n";
	message += tr("Retroshare will continue connecting in the background");

	setStatusMessage(MESSAGE_STATUS_INPROGRESS, title, message);
}


void ConnectProgressDialog::sayConnectTimeout()
{
	QString title = tr("Connection Timeout");
	QString message = tr("Connection Attempt has taken too long");
	message += "\n";
	message += tr("But no error has been detected");
	message += "\n\n";
	message += tr("Try again shortly, Retroshare will continue connecting in the background");
	message += "\n\n";
	message += tr("If you continue to get this message, please contact developers");

	setStatusMessage(MESSAGE_STATUS_UNKNOWN_ERROR, title, message);
}


void ConnectProgressDialog::sayLookupTimeout()
{
	QString title = tr("DHT Lookup Timeout");
	QString message = tr("DHT Lookup has taken too long");
	message += "\n\n";
	message += tr("Try again shortly, Retroshare will continue connecting in the background");
	message += "\n\n";
	message += tr("If you continue to get this message, please contact developers");

	setStatusMessage(MESSAGE_STATUS_UNKNOWN_ERROR, title, message);
}

void ConnectProgressDialog::sayUdpTimeout()
{
	QString title = tr("UDP Connection Timeout");
	QString message = tr("UDP Connection has taken too long");
	message += "\n\n";
	message += tr("Try again shortly, Retroshare will continue connecting in the background");
	message += "\n\n";
	message += tr("If you continue to get this message, please contact developers");

	setStatusMessage(MESSAGE_STATUS_UNKNOWN_ERROR, title, message);
}


void ConnectProgressDialog::sayUdpFailed()
{
	QString title = tr("UDP Connection Failed");
	QString message = tr("We are continually working to improve connectivity.");
	message += "\n";
	message += tr("In this case the UDP connection attempt has failed.");
	message += "\n\n";
	message += tr("Improve connectivity by opening a Port in your Firewall.");
	message += "\n\n";
	message += tr("Retroshare will continue connecting in the background");
	message += "\n";
	message += tr("If you continue to get this message, please contact developers");

	setStatusMessage(MESSAGE_STATUS_UNKNOWN_ERROR, title, message);
}



void ConnectProgressDialog::sayConnected()
{
	QString title = tr("Connected");
	QString message = tr("Congratulations, you are connected");

	setStatusMessage(MESSAGE_STATUS_SUCCESS, title, message);
}

void ConnectProgressDialog::sayDHTFailed()
{
	QString title = tr("DHT startup Failed");
	QString message = tr("Your DHT has not started properly");
	message += "\n\n";
	message += tr("Common causes of this problem are:");
	message += "\n";
	message += tr("     - You are not connected to the Internet");
	message += "\n";
	message += tr("     - You have a missing or out-of-date DHT bootstrap file (bdboot.txt)");

	setStatusMessage(MESSAGE_STATUS_CONFIG_ERROR, title, message);
}

void ConnectProgressDialog::sayDHTOffline()
{
	QString title = tr("DHT is Disabled");
	QString message = tr("The DHT is OFF, so Retroshare cannot find your Friends.");
	message += "\n\n";
	message += tr("Retroshare has tried All Known Addresses, with no success");
	message += "\n";
	message += tr("The DHT is needed if your friends have Dynamic IP Addresses.");
	message += "\n";
	message += tr("Only Advanced Retroshare users should switch off the DHT.");
	message += "\n\n";
	message += tr("Go to Settings->Server and change config to \"Public: DHT and Discovery\"");

	setStatusMessage(MESSAGE_STATUS_CONFIG_ERROR, title, message);
}

void ConnectProgressDialog::sayDenied()
{
	QString title = tr("Peer Denied Connection");
	QString message = tr("We successfully reached your Friend.");
	message += "\n";
	message += tr("but they have not added you as a Friend.");
	message += "\n\n";
	message += tr("Please contact them to add your Certificate");
	message += "\n\n";
	message += tr("Your Retroshare Node is configured Okay");

	setStatusMessage(MESSAGE_STATUS_PEER_ERROR, title, message);
}


void ConnectProgressDialog::sayUdpDenied()
{
	QString title = tr("Peer Denied Connection");
	QString message = tr("We successfully reached your Friend via UDP.");
	message += "\n";
	message += tr("but they have not added you as a Friend.");
	message += "\n\n";
	message += tr("Please contact them to add your Full Certificate");
	message += "\n";
	message += tr("They need a Certificate + Location for UDP connections to succeed");
	message += "\n\n";
	message += tr("Your Retroshare Node is configured Okay");

	setStatusMessage(MESSAGE_STATUS_PEER_ERROR, title, message);
}


void ConnectProgressDialog::sayPeerOffline()
{
	QString title = tr("Peer Offline");
	QString message = tr("We Cannot find your Friend.");
	message += "\n\n";
	message += tr("They are either offline or their DHT is Off");
	message += "\n\n";
	message += tr("Your Retroshare Node is configured Okay");

	setStatusMessage(MESSAGE_STATUS_PEER_ERROR, title, message);
}


void ConnectProgressDialog::sayPeerNoDhtConfig()
{
	QString title = tr("Peer DHT is Disabled");
	QString message = tr("Your Friend has configured Retroshare with DHT Disabled.");
	message += "\n\n";
	message += tr("You have previously connected to this Friend");
	message += "\n";
	message += tr("Retroshare has determined that they have DHT switched off");
	message += "\n";
	message += tr("Without the DHT it is hard for Retroshare to locate your friend");
	message += "\n\n";
	message += tr("Try importing a fresh Certificate to get up-to-date connection information");
	message += "\n\n";
	message += tr("If you continue to get this message, please contact developers");

	setStatusMessage(MESSAGE_STATUS_PEER_ERROR, title, message);
}


void ConnectProgressDialog::sayInvalidPeer()
{
	QString title = tr("Incomplete Friend Details");
	QString message = tr("You have imported an incomplete Certificate");
	message += "\n\n";
	message += tr("Retroshare cannot connect without this information");
	message += "\n\n";
	message += tr("Please retry importing the full Certificate");

	setStatusMessage(MESSAGE_STATUS_CONFIG_ERROR, title, message);
}


void ConnectProgressDialog::setStatusMessage(uint32_t status, const QString &title, const QString &message)
{
	switch(status)
	{
		case MESSAGE_STATUS_INPROGRESS:
			{
				QPixmap pm(":/images/graph-blue.png");
				ui->statusIcon->setPixmap(pm.scaledToWidth(40));
			}
			break;
		case MESSAGE_STATUS_SUCCESS:
			{
				QPixmap pm(":/images/graph-downloaded.png");
				ui->statusIcon->setPixmap(pm.scaledToWidth(40));
			}
			break;
		case MESSAGE_STATUS_CONFIG_ERROR:
			{
				QPixmap pm(":/images/graph-downloading.png");
				ui->statusIcon->setPixmap(pm.scaledToWidth(40));
			}
			break;
		case MESSAGE_STATUS_PEER_ERROR:
			{
				QPixmap pm(":/images/graph-checking.png");
				ui->statusIcon->setPixmap(pm.scaledToWidth(40));
			}
			break;
		case MESSAGE_STATUS_UNKNOWN_ERROR:
			{
				QPixmap pm(":/images/graph-checking.png");
				ui->statusIcon->setPixmap(pm.scaledToWidth(40));
			}
			break;
	}

	ui->statusTitle->setText(title);
	ui->textBrowser->setText(message);
}



