#include "configutils.h"

#include <qapplication.h>
#include <qprocess.h>
#include <qobject.h>
#include <qfile.h>
#include <qdir.h>
#include <qregexp.h>
#ifdef Q_WS_WIN
#include <windows.h>
#endif
#ifdef Q_OS_UNIX
#include <stdlib.h>
#endif

QString *qtDir = 0;
int processes = 0;
int errors = 0;
int warnings = 0;
bool autoShutdown = TRUE;

static QStringList static_messages;

/** Which program to invoke as qmake. Default is "qmake" */
QString qmake = "qmake";

/** Set program to be used as qmake */
void setQMake( const QString &str ) {
    message ( QString("Using qmake: ") + str);
    qmake = str;
}

void message( const QString &str )
{
    static_messages.append( str );
}

QStringList messages()
{
    return static_messages;
}

class BlockingProcess : public QProcess
{
    Q_OBJECT

public:
    BlockingProcess()
    {
	connect(this, SIGNAL(readyReadStdout()), this, SLOT(readOut()));
	connect(this, SIGNAL(readyReadStderr()), this, SLOT(readErr()));
	connect(this, SIGNAL(processExited()), this, SLOT(exited()));
	outUsed = errUsed = 0;
    }

public slots:
    void readOut()
    {
 	QByteArray rout = readStdout();
	if (outUsed + rout.size() > out.size())
	    out.resize(outUsed + rout.size());
	memcpy(out.data() + outUsed, rout, rout.size());
	outUsed += rout.size();
    }

    void readErr()
    {
 	QByteArray rerr = readStderr();
	if (errUsed + rerr.size() > err.size())
	    err.resize(errUsed + rerr.size());
	memcpy(err.data() + errUsed, rerr, rerr.size());
	errUsed += rerr.size();
    }

    void exited()
    {
	qApp->exit_loop();
    }

public:
    QByteArray out;
    QByteArray err;
    int outUsed;
    int errUsed;
};


static bool execute( const QStringList &args )
{
    BlockingProcess bp;
    bp.setArguments(args);
    if (!bp.start())
	return FALSE;
    qApp->enter_loop();
    return !bp.exitStatus() && bp.normalExit();
}

static void runQMake(const QString &d,
                     const QStringList &configs,
                     const QStringList &antiConfigs,
                     const QString &prefix,
                     const QString &target)
{
    QDir dir(d);
    QString runDir = dir.absPath();
    dir.cdUp();
    QString oldDir = dir.absPath();
    QDir::setCurrent(runDir);
    // make the top level Makefile
    QStringList args;
    args.append( qmake );
    if ( !prefix.isEmpty() )
	args.append( "QSA_INSTALL_PREFIX=" + prefix );
    if (!target.isNull()) {
        args.append("-o");
        args.append(target);
    }

    args.append("-after");
    if (!configs.isEmpty())
        args.append( "CONFIG+=" + configs.join( " " ) );
    if (!antiConfigs.isEmpty())
        args << "CONFIG-=" + antiConfigs.join(" ");
    //Need to pass QMAKE to qmake subprocesses
    args.append( "QMAKE=" + qmake );

    if( !execute( args ) )
	warnings++;
    QDir::setCurrent(oldDir);
}


void runQMake( const QStringList &configs, const QStringList &antiConfigs, const QString &prefix )
{
    runQMake(".", configs, antiConfigs, prefix, "Makefile.qsa");
}

void mkDir( const QString &dir )
{
    QDir current;
    current.mkdir( dir );
}

bool writeQSConfig( bool buildIde )
{
    QFile file( "src/qsa/qsconfig.h" );
    if( !file.open( IO_WriteOnly ) ) {
	message( "Failed to open 'src/qsa/qsconfig.h' for writing." );
	return FALSE;
    }
    QTextStream txt( &file );
    txt << "// This file is autogenerated by QSA configure, do not modify it!\n"
	<< "#ifndef QS_CONFIG_H\n"
	<< "#define QS_CONFIG_H\n"
	<< "\n";
    if( !buildIde )
	txt << "#define QSA_NO_IDE\n";
    txt << "\n"
	<< "#endif\n";
    return TRUE;
}

#include "configutils.moc"
