/*
 *  Copyright (C) 2007-2008 CMM Sigma Andrzej Chmielowiec <cmmsigma@cmmsigma.eu>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 3
 *  as published by the Free Software Foundation.
 *
 *  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 General Public License for more details.
 */

// FtpDistDialog.cpp: implementation of the FtpDistDialog class.
//
//////////////////////////////////////////////////////////////////////

#include "FtpDistDialog.h"

FtpDistDialog::FtpDistDialog(CaOptions::FTPConfig *ftpConfig, QByteArray *crlData, QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f)
{
	setWindowTitle(tr("Distributing CRL list via FTP"));
	
	QGridLayout *layout = new QGridLayout();

	mServerProgress = new QProgressBar();
	mFileProgress = new QProgressBar();
	mTransferProgress = new QProgressBar();
	
	layout->addWidget(new QLabel(tr("Servers")), 0, 0);
	layout->addWidget(mServerProgress, 0, 1);

	layout->addWidget(new QLabel(tr("Files")), 1, 0);
	layout->addWidget(mFileProgress, 1, 1);
	
	layout->addWidget(new QLabel(tr("Transferred")), 2, 0);
	layout->addWidget(mTransferProgress, 2, 1);

	layout->addWidget(new QLabel(), 3, 0, 1, 2);

	mLog = new QTextEdit();
	mLog->setReadOnly(true);
	layout->addWidget(new QLabel(tr("Distribute progress")), 4, 0, 1, 2);
	layout->addWidget(mLog, 5, 0, 1, 2);

	mBreak = new QPushButton(tr("Abort"));
	connect(mBreak, SIGNAL(clicked()), this, SLOT(reject()));
	layout->addWidget(mBreak, 6, 0, 1, 2, Qt::AlignRight);

	resize(500, 300);
	setLayout(layout);

	mFtpConfig = ftpConfig;
	mCrlData = crlData;
	mCurrServer = -1;
	mCurrFile = -1;
	mError = false;
	mFtp = 0;
	mIndexes = new QQueue<int>();
	
	if(mFtpConfig != 0 && crlData != 0)
	{
		for(int i=0; i<mFtpConfig->mAccounts.size(); i++)
		{
			if(mFtpConfig->mAccounts[i].mUseAccount)
			{
				mIndexes->enqueue(i);
			}
		}
		mServerProgress->setRange(0, mFtpConfig->getActiveCount());
		connect2NextServer();
	}
}

FtpDistDialog::~FtpDistDialog()
{
}

void
FtpDistDialog::ftpDataTransferProgress(qint64 readBytes, qint64 totalBytes)
{
    mTransferProgress->setMaximum(totalBytes);
    mTransferProgress->setValue(readBytes);
}

void
FtpDistDialog::ftpDone(bool error)
{
	if(error)
		mError = true;
}

void
FtpDistDialog::ftpCommandFinished(int, bool error)
{
	if(error)
		mError = true;
	
	QFtp::Command command = mFtp->currentCommand();
	
	if(command == QFtp::ConnectToHost)
	{
		if(!error)
		{
			login2Server();
		}
		else
		{
			mLog->insertHtml(tr("<font color=red><b>host not found</b></font><br>"));
			mLog->ensureCursorVisible();
			connect2NextServer();
		}
	}
	else if(command == QFtp::Login)
	{
		if(!error)
		{
			mFtp->rawCommand("pwd");
		}
		else
		{
			mLog->insertHtml(tr("<font color=red><b>incorrect login or user name</b></font><br>"));
			mLog->ensureCursorVisible();
			
			connect2NextServer();
		}
	}
	else if(command == QFtp::Cd)
	{
		if(error)
		{
			mLog->insertHtml(tr("- <font color=red><b>incorrect path on FTP server</b></font><br>"));
			mLog->ensureCursorVisible();
			mFtp->clearPendingCommands();
		
			sendNextFile();
		}
	}
	else if(command == QFtp::Put)
	{
		if(!error)
		{
			mLog->insertHtml(tr("- <font color=green><b>sent</b></font><br>"));
			mLog->ensureCursorVisible();
		}
		else
		{
			mLog->insertHtml(tr("- <font color=red><b>error writing file on server</b></font><br>"));
			mLog->ensureCursorVisible();
		}

		sendNextFile();
	}
}

void
FtpDistDialog::ftpRawCommandReply(int replyCode, const QString & detail)
{
	if(replyCode == 257)
	{
		QStringList reply = detail.split('\"', QString::SkipEmptyParts);
		if(reply.size() > 0)
			mRootDir = reply[0];
		else
			mRootDir = "~";
		
		if(mRootDir == "/")
			mRootDir.clear();

		sendNextFile();
	}
}

void
FtpDistDialog::connect2NextServer()
{
	mCurrServer ++;
	if(mIndexes->isEmpty())
	{
		mServerProgress->setValue(mCurrServer);
		mBreak->setText(tr("Close"));

		mLog->insertHtml(mError ? tr("<br><font color=red><b>There are some errors occured during distributing CRL list.</b></font>")
				: tr("<br><font color=green><b>CRL list was distributed successfully.</font></b>"));
		mLog->ensureCursorVisible();
		
		return;
	}

	if(mCurrServer > 0)
	{
		mLog->insertHtml("<br>");
		mLog->ensureCursorVisible();
	}
	
	if(mFtp != 0)
	{
		mFtp->clearPendingCommands();
		if(mFtp->state() != QFtp::Unconnected)
			mFtp->close();
	}
	else
	{
		mFtp = new QFtp(this);
		connect(mFtp, SIGNAL(commandFinished(int, bool)), this, SLOT(ftpCommandFinished(int, bool)));
		connect(mFtp, SIGNAL(dataTransferProgress(qint64, qint64)), this, SLOT(ftpDataTransferProgress(qint64, qint64)));
		connect(mFtp, SIGNAL(done(bool)), this, SLOT(ftpDone(bool)));
		connect(mFtp, SIGNAL(rawCommandReply(int, const QString &)), this, SLOT(ftpRawCommandReply(int, const QString &)));
	}

	mCurrFile = -1;
	mCurrIndex = mIndexes->dequeue();
	CaOptions::FTPConfig::FTPAccount account = mFtpConfig->mAccounts[mCurrIndex];
	int pathCount = account.mPaths.size();

	mLog->insertHtml(tr("<b>Sending to server: <font color=blue><u>%1</u></font> (%2)</b><br>")
		.arg(account.mServer).arg(account.mName));
	mLog->ensureCursorVisible();

	mServerProgress->setValue(mCurrServer);
	mFileProgress->setRange(0, pathCount);
	mFileProgress->setValue(0);
	
	mFtp->connectToHost(account.mServer);
}

void
FtpDistDialog::login2Server()
{
	CaOptions::FTPConfig::FTPAccount account = mFtpConfig->mAccounts[mCurrIndex];

	mFtp->setTransferMode(QFtp::Passive);
	mFtp->login(account.mUser, account.mPass);
}

void
FtpDistDialog::sendNextFile()
{
	CaOptions::FTPConfig::FTPAccount account = mFtpConfig->mAccounts[mCurrIndex];
	int pathCount = account.mPaths.size();
	
	mCurrFile ++;
	mFileProgress->setValue(mCurrFile);

	if(mCurrFile >= pathCount)
	{
		connect2NextServer();
		return;
	}	
	
	QString path;
	if(pathCount > mCurrFile)
		path = account.mPaths[mCurrFile];

	mLog->insertHtml(path + ' ');
	mLog->ensureCursorVisible();

	if(!path.startsWith('/'))
		path.insert(0, '/');

	QStringList names = path.split('/', QString::SkipEmptyParts);
	mCurrFileName = names.last();
	path = path.left(path.lastIndexOf('/') + 1);

	mFtp->cd(mRootDir + path);
	mFtp->put(*mCrlData, mCurrFileName);
}
