//
// C++ Implementation: filenameview
//
// Description: 
//
//
// Author: Benjamin Mesing <bensmail@gmx.net>, (C) 2005
//
// Copyright: See COPYING file that comes with this distribution
//
//

#include "filenameview.h"

#include <assert.h>

#include <qapplication.h>
#include <qclipboard.h>
#include <qevent.h>
#include <qfileinfo.h>
#include <QMenu>
#include <qstatusbar.h>


#include <iprovider.h>

QString FilenameView::_seeCommand("/usr/bin/see");


FilenameView::FilenameView(QWidget *parent, const char *name, NPlugin::IProvider* pProvider)
 : QWidget(parent), Ui::FilenameView()
{
	setObjectName(name);
	_filterTextEmpty = true;
	_pProvider = pProvider;
	setupUi(this);
	_pErrorDisplay->setVisible(false);
	connect(_pShowButton, SIGNAL(clicked()), SIGNAL(showRequested()));
	connect( &_processContainer, SIGNAL(processExited(QProcess*)), this, SLOT(onProcessExited(QProcess*)) );

}


FilenameView::~FilenameView()
{
}


void FilenameView::viewFile(QString filename)
{
	_pProvider->statusBar()->showMessage(tr("Trying to view ") + filename, 4000);
	QFileInfo seeInfo(_seeCommand );
	if ( !seeInfo.isExecutable() )
	{
		_pProvider->reportError(
			_seeCommand + tr(" not available"), 
			tr("The <tt>") + _seeCommand + tr("</tt> command is not available.\n"
				"Please make sure that the <tt>mime-support</tt> package is installed "
				"and that you have permission to execute <tt>") + _seeCommand + tr("</tt>.")
		);
		return;
	}
	QProcess* pProcess = new QProcess(this);
	QStringList arguments;
	arguments.push_back(filename);
	_seeCommands[pProcess] = make_pair(filename, false);
	if (!_processContainer.start(pProcess, _seeCommand , arguments))
	{
		_pProvider->reportError
		(
			tr("Unable to launch ") + _seeCommand , 
			tr("Launching <tt>") + _seeCommand  + " " + filename + tr("</tt> failed due to an unknown reason.")
		);
	}
}


void FilenameView::onProcessExited(QProcess* pProcess )
{
	static const QString TEXT_PLAIN_PREFIX("text/plain:");
	
	qDebug("process exited");
	// if the "see" did not exit normally try again specifying mimetime text/plain
	pair<QString, bool> seeInformation = _seeCommands[pProcess];
	QString filename = seeInformation.first;
	// Holds if viewing the file using mimetype text/plain was already tried
	bool wasTriedAsTextPlain = seeInformation.second;
	if (pProcess->exitCode() != 0)
	{
		qDebug("non-normal exit");
		if (wasTriedAsTextPlain)
		{
			_seeCommands.erase(pProcess);
			pProcess->deleteLater();
			_pProvider->reportError( tr("Error viewing file"), tr("Unable to view file ") + filename
				+ tr("\nTried <tt>") + _seeCommand + " " + filename + tr("</tt> and\n<tt>") + _seeCommand + " " + 
				TEXT_PLAIN_PREFIX + filename + "</tt>" );
		//	qDebug("Error launching see " + pItem->text(0));
		}
		else
		{
			_seeCommands[pProcess] = make_pair(filename, true);
			_pProvider->statusBar()->showMessage(tr("Retrying to view ") + filename + tr(" with mimetype text/plain"),
				 4000);
			qDebug("%s", (QString("retrying process ") + filename).toLatin1().data());
			QStringList arguments;
			arguments.push_back(TEXT_PLAIN_PREFIX+filename);
			_processContainer.start(pProcess, "see", arguments);
		}
	}
	else
	{
 		qDebug("normal exit");
 		_pProvider->statusBar()->showMessage(tr("Finished viewing ") + filename, 4000);
		_seeCommands.erase(pProcess);
		pProcess->deleteLater();
	}
}

void FilenameView::on__pFilenameView_itemDoubleClicked(QListWidgetItem* pItem)
{
	if (pItem == 0)
	{
		qDebug("Didn't hit an item");
		return;
	}
	QString filename = pItem->text();
	if (!isFileViewable(filename))
	{
		_pProvider->statusBar()->showMessage(tr("Can't view file ") + filename + tr(", it is not viewable"),
			5000);
		return;
	}
	viewFile(pItem->text());
}


void FilenameView::on__pFilterInput_textChanged( const QString & pattern )
{
	_filterTextEmpty = pattern.isEmpty();
	updateView();
}


void FilenameView::on__pFilenameView_customContextMenuRequested(const QPoint& pos)
{
	QListWidgetItem* pItem = _pFilenameView->currentItem();
	// if no item was selected return immidiately
	if (pItem == 0)
		return;
	QMenu menu(this);
	QString filename = pItem->text();
	QAction* pCopyToClipboard = menu.addAction(tr("Copy to clipboard"));
	QAction* pCopyAllToClipboard = menu.addAction(tr("Copy all filenames to clipboard"));
	QAction* pViewFile = menu.addAction(tr("View file (depends on settings in /etc/mailcap)"));
	if (!isFileViewable(filename))
		pViewFile->setEnabled(false);
	
	QAction* pResult = menu.exec(_pFilenameView->mapToGlobal(pos));
	if (pResult == pCopyToClipboard)
	{
		QClipboard *pCb = QApplication::clipboard();
		pCb->setText(filename, QClipboard::Clipboard);
		pCb->setText(filename, QClipboard::Selection);
	}
	else if (pResult == pCopyAllToClipboard)
	{
		QClipboard *pCb = QApplication::clipboard();
		QString itemsString = getAllVisibleItems().join("\n");
		pCb->setText(itemsString, QClipboard::Clipboard);
		pCb->setText(itemsString, QClipboard::Selection);
	}
	else if (pResult == pViewFile)
	{
		viewFile(filename);
	}
}


void FilenameView::clear()
{
	_errorMessage = "";
	_entries.clear();
	_pFilenameView->clear();
}

void FilenameView::setFilterText( const QString & pattern )
{
	_pFilterInput->setText(pattern);
}

void FilenameView::addEntry( const QString & entry )
{
	_entries.push_back(entry);
	insertItem(entry);
}

void FilenameView::updateView()
{
	_pFilenameView->clear();
	if (_errorMessage.isEmpty()) // if no error was indicated
	{
		_pFilenameView->setVisible(true);
		_pErrorDisplay->setVisible(false);
		
		for ( QStringList::iterator it = _entries.begin(); it != _entries.end(); ++it)
		{
			insertItem(*it);
		}
	}
	else
	{
		_pErrorDisplay->setHtml(_errorMessage);
		_pFilenameView->setVisible(false);
		_pErrorDisplay->setVisible(true);
	}
}

void FilenameView::setErrorMessage( const QString & errorMessage )
{
	/** The error message holds the error state. If it is empty no error has occured. */
	_errorMessage = errorMessage;
	updateView();
}

void FilenameView::insertItem( const QString & entry )
{
	if ( _filterTextEmpty || entry.contains(_pFilterInput->text()) )
	{
		new QListWidgetItem(entry, _pFilenameView);
	}
	_pFilenameView->setVisible(true);
	_pErrorDisplay->setVisible(false);
}

QStringList FilenameView::getAllVisibleItems()
{
	QStringList result;
	if (_errorMessage.isEmpty())
	{
		for ( int i = 0; i < _pFilenameView->count(); ++i)
		{
			QListWidgetItem* pItem = _pFilenameView->item(i);
            if (!pItem->isHidden())
				result.push_back(pItem->text());
		}
	}
	return result;
}


/** @brief Returns if the file is viewable (i.e. no directory and readable). */
bool FilenameView::isFileViewable(QString filename)
{
	QFileInfo fileinfo(filename);
	return fileinfo.isReadable() && !fileinfo.isDir();
}


void FilenameView::setShowButtonEnabled(bool enabled)
{
	_pShowButton->setEnabled(enabled);
}
