/*
 * filelistretriever.cc
 *
 * Copyright (c) 2002, 2003 Frerich Raabe <raabe@kde.org>
 *
 * 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. For licensing and distribution details, check the
 * accompanying file 'COPYING'.
 */
#include "filelistretriever.h"
#include "port.h"
#include "portmgr.h"

#include <kapplication.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmainwindow.h>
#include <knotifyclient.h>
#include <kprocess.h>
#include <kstandarddirs.h>
#include <kstatusbar.h>

#include <qdir.h>

#include <stdlib.h> // for getenv()

using namespace Barry;

QStringList FileListRetriever::fileList( const PortInterface &port )
{
	FileListRetriever retriever( port );
	return retriever.fileList();
}

FileListRetriever::FileListRetriever( const PortInterface &port ):
	m_port( port )
{
}

QStringList FileListRetriever::fileList()
{
	m_sourceFile = m_port.directory() + QString::fromLatin1( "/Makefile" );

	QString cacheFile = m_port.directory();
	if ( cacheFile.startsWith( PortMgr::self().portRootDir() ) )
		cacheFile.remove( 0, PortMgr::self().portRootDir().length() + 1 );
	cacheFile.replace( QString::fromLatin1( "/" ), QString::fromLatin1( "-" ) );
	cacheFile += QString::fromLatin1( "-plist.cache" );

	m_cacheFile = ::locateLocal( "appdata",
	                             QString::fromLatin1( "cache/" ) + cacheFile );

	if ( !cacheIsValid() )
		rebuildCache();

	return processCache();
}

bool FileListRetriever::cacheIsValid() const
{
	return QFile::exists( m_cacheFile ) && sourceMTime() == cachedMTime();
}

QDateTime FileListRetriever::sourceMTime() const
{
	const QFileInfo fileInfo( m_sourceFile );
	return fileInfo.lastModified();
}

QDateTime FileListRetriever::cachedMTime() const
{
	QFile mtimeFile( m_cacheFile + QString::fromLatin1( "-mtime" ) );
	if ( !mtimeFile.open( IO_ReadOnly ) )
		return QDateTime();

	QDataStream stream( &mtimeFile );
	QDateTime mtime;
	stream >> mtime;

	return mtime;
}

void FileListRetriever::rebuildCache()
{
	if ( !QFile::exists( m_sourceFile ) ) {
		KNotifyClient::event( KNotifyClient::cannotOpenFile,
		i18n( "Couldn't open the port's Makefile in %1! "
		"Perhaps the port directory %1 isn't mounted properly?" )
		.arg( m_sourceFile )
		.arg( PortMgr::self().portRootDir() ) );
		return;
	}

	// There might be no main widget, think --rebuild-cache
	KMainWindow *mainWindow = dynamic_cast<KMainWindow *>( kapp->mainWidget() );
	if ( mainWindow )
		mainWindow->statusBar()->message( i18n( "Determining list of files..." ) );

	KProcess *proc = new KProcess;
	*proc << QString::fromLatin1( "make" );
	*proc << QString( QString::fromLatin1( "TMPPLIST=%1" ) ).arg( m_cacheFile );
	*proc << QString::fromLatin1( "generate-plist" );

	const QFileInfo fileInfo( m_sourceFile );
	proc->setWorkingDirectory( fileInfo.dirPath() );

	proc->start( KProcess::Block );

	if ( !proc->normalExit() || proc->exitStatus() != 0 ) {
		kdWarning() << "Failed to run 'make generate-plist' for port '"
		            << m_port.origin() << "'" << endl;
		if ( mainWindow )
			mainWindow->statusBar()->message( i18n( "Aborted!" ), 2000 );
		delete proc;
		return;
	}

	delete proc;

	if ( mainWindow )
		mainWindow->statusBar()->message( i18n( "Finished." ), 2000 );

	QFile mtimeFile( m_cacheFile + QString::fromLatin1( "-mtime" ) );
	if ( !mtimeFile.open( IO_WriteOnly ) )
		return;

	QDataStream stream( &mtimeFile );
	stream << sourceMTime();
}

QStringList FileListRetriever::processCache()
{
	QFile cache( m_cacheFile );
	if ( !cache.open( IO_ReadOnly ) )
		return QStringList();

	QStringList files;
	const QStringList lines( QStringList::split( '\n', cache.readAll() ) );
	QStringList::ConstIterator it = lines.begin();
	QStringList::ConstIterator end = lines.end();
	for ( ; it != end; ++it )
		if ( !( *it ).startsWith( QString::fromLatin1( "@" ) ) )
			files += m_port.prefix() + QString::fromLatin1( "/" ) + *it;

	return files;
}

// vim:ts=4:sw=4:noet:list
