/*
-----BEGIN QCMOD-----
name: QCA >= 2.0
arg: with-qca-inc=[path],Path to QCA include files
arg: with-qca-lib=[path],Path to QCA library or framework files
-----END QCMOD-----
*/

// adapted from crypto.prf
static QString internal_crypto_prf(const QString &incdir, const QString &libdir, const QString &frameworkdir)
{
    QString out = QString(
"QCA_INCDIR = %1\n"
"QCA_LIBDIR = %2\n"
"QMAKE_RPATHDIR = %2\n"
"QCA_FRAMEWORKDIR = %3\n"
"\n"
"CONFIG *= qt\n"
"\n"
"LINKAGE =\n"
"QCA_NAME = qca-qt5\n"
"\n"
"!isEmpty(QCA_FRAMEWORKDIR): {\n"
"    framework_dir = $$QCA_FRAMEWORKDIR\n"
"    exists($$framework_dir/$${QCA_NAME}.framework) {\n"
"    	#QMAKE_FRAMEWORKPATH *= $$framework_dir\n"
"    	LIBS *= -F$$framework_dir\n"
"    	INCLUDEPATH += $$framework_dir/$${QCA_NAME}.framework/Headers\n"
"    	LINKAGE = -framework $${QCA_NAME}\n"
"    }\n"
"}\n"
"\n"
"# else, link normally\n"
"isEmpty(LINKAGE) {\n"
"    !isEmpty(QCA_INCDIR):INCLUDEPATH += $$QCA_INCDIR/QtCrypto\n"
"    !isEmpty(QCA_LIBDIR):LIBS += -L$$QCA_LIBDIR\n"
"    LINKAGE = -l$${QCA_NAME}\n"
"    CONFIG(debug, debug|release) {\n"
"    	windows:LINKAGE = -l$${QCA_NAME}d\n"
"    	mac:LINKAGE = -l$${QCA_NAME}_debug\n"
"    }\n"
"}\n"
"\n"
"LIBS += $$LINKAGE\n"
    ).arg(incdir, libdir, frameworkdir);
    return out;
}

// set either libdir or frameworkdir, but not both
static bool qca_try(Conf *conf, const QString &incdir, const QString &libdir, const QString &frameworkdir, bool release, bool debug, QString *_prf)
{
    QString proextra;
    QString prf;
    if (!incdir.isEmpty() || !libdir.isEmpty() || !frameworkdir.isEmpty()) {
    	prf = internal_crypto_prf(conf->escapePath(incdir), conf->escapePath(libdir), frameworkdir);
    } else {
    	prf = "CONFIG += crypto\n";
    }
    proextra =
    "CONFIG += qt\n"
    "CONFIG -= debug_and_release debug release\n"
    "QT -= gui\n";
    proextra += prf;

    QString str =
    "#include <QtCrypto>\n"
    "\n"
    "int main()\n"
    "{\n"
    "	unsigned long x = QCA_VERSION;\n"
    "	if(x >= 0x020000 && x < 0x030000) return 0; else return 1;\n"
    "}\n";

    // test desired versions, potentially both release and debug

    if(release)
    {
    	int ret;
    	if(!conf->doCompileAndLink(str, QStringList(), QString(), proextra + "CONFIG += release\n", &ret) || ret != 0)
    		return false;
    }

    if(debug)
    {
    	int ret;
    	if(!conf->doCompileAndLink(str, QStringList(), QString(), proextra + "CONFIG += debug\n", &ret) || ret != 0)
    		return false;
    }

    *_prf = prf;
    return true;
}

static bool qca_try_lib(Conf *conf, const QString &incdir, const QString &libdir, bool release, bool debug, QString *prf)
{
    return qca_try(conf, incdir, libdir, QString(), release, debug, prf) ||
            qca_try(conf, incdir + "/Qca-qt5", libdir, QString(), release, debug, prf);
}

static bool qca_try_framework(Conf *conf, const QString &frameworkdir, bool release, bool debug, QString *prf)
{
    return qca_try(conf, QString(), QString(), frameworkdir, release, debug, prf);
}

static bool qca_try_ext_prf(Conf *conf, bool release, bool debug, QString *prf)
{
    return qca_try(conf, QString(), QString(), QString(), release, debug, prf);
}

//----------------------------------------------------------------------------
// qc_qca
//----------------------------------------------------------------------------
class qc_qca : public ConfObj
{
public:
    qc_qca(Conf *c) : ConfObj(c) {}
    QString name() const { return "QCA >= 2.0"; }
    QString shortname() const { return "qca"; }
    bool exec()
    {
    	// get the build mode
#ifdef QC_BUILDMODE
    	bool release = qc_buildmode_release;
    	bool debug = qc_buildmode_debug;
#else
    	// else, default to just release mode
    	bool release = true;
    	bool debug = false;
#endif

    	QString qca_incdir, qca_libdir, qca_crypto_prf;
    	qca_incdir = conf->getenv("QC_WITH_QCA_INC");
    	qca_libdir = conf->getenv("QC_WITH_QCA_LIB");

#if defined(Q_OS_MAC)
    	if(!qca_libdir.isEmpty() && qca_try_framework(conf, qca_libdir, release, debug, &qca_crypto_prf))
    	{
    		conf->addExtra(qca_crypto_prf);
    		return true;
    	}
#endif

    	if(!qca_incdir.isEmpty() && !qca_libdir.isEmpty() && qca_try_lib(conf, qca_incdir, qca_libdir, release, debug, &qca_crypto_prf))
    	{
    		conf->addExtra(qca_crypto_prf);
    		return true;
    	}
    	
    	if (qca_try_ext_prf(conf, release, debug, &qca_crypto_prf))
    	{
    		conf->addExtra(qca_crypto_prf);
    		return true;
    	}

    	QStringList incs;
    	QString version, libs, other;

        if(conf->findPkgConfig("qca2-qt5", VersionMin, "2.0.0", &version, &incs, &libs, &other))
        {
            for(int n = 0; n < incs.count(); ++n)
                conf->addIncludePath(incs[n]);
            if(!libs.isEmpty())
                conf->addLib(libs);
            return true;
        }

    	QStringList prefixes;
#ifndef Q_OS_WIN
        prefixes += "/usr";
    	prefixes += "/usr/local";
#endif
        QString prefix = conf->getenv("PREFIX");
        if (!prefix.isEmpty()) {
            prefixes += prefix;
        }

    	for(int n = 0; n < prefixes.count(); ++n)
    	{
    		const QString &prefix = prefixes[n];
    		if(qca_try_lib(conf, prefix + "/include", prefix + "/lib", release, debug, &qca_crypto_prf))
    		{
    			conf->addExtra(qca_crypto_prf);
    			return true;
    		}
    	}

    	return false;
    }
};
