var stdout = WScript.StdOut;
var fso = new ActiveXObject("Scripting.FileSystemObject");

var DEFINES = [
    "USE_WOLFSSL_IO",
    "HAVE_AESGCM",
    "WOLFSSL_TLS13",
    "HAVE_HKDF",
    "HAVE_FFDHE_4096",
    "WC_RSA_PSS",
    "WOLFSSL_DTLS",
    "WOLFSSL_DTLS13",
    "WOLFSSL_SEND_HRR_COOKIE",
    "WOLFSSL_DTLS_CID",
    "WOLF_C89",
    "NO_WOLF_C99",
    "WC_RSA_BLINDING",
    "NO_MULTIBYTE_PRINT",
    "HAVE_CRL",
    "HAVE_CRL_MONITOR",
    "OPENSSL_EXTRA",
    "HAVE_ECC",
    "XVSNPRINTF _vsnprintf"
];

var IGNORES = [
    "wolfssl/wolfcrypt/port/atmel",
    "wolfssl/wolfcrypt/port/af_alg",
    "wolfssl/wolfcrypt/port/kcapi",
    "wolfssl/wolfcrypt/port/devcrypto",
    "wolfssl/wolfcrypt/async.h",
    "wolfssl/wolfcrypt/wc_pkcs11.h",
    "wolfssl/wolfcrypt/pkcs11.h",
    "wolfssl/wolfcrypt/port/cavium",
    "wolfssl/wolfcrypt/port/intel",
    "wolfssl/wolfcrypt/sp.h",
    "wolfssl/wolfcrypt/sp_int.h",
    "wolfssl/wolfcrypt/selftest.h",
    "wolfssl/wolfcrypt/fips.h",
    "wolfssl/wolfcrypt/port/caam",
];

var IGNORE_RE = new RegExp("^(" + IGNORES.join(" | ") + ")");

function relative(root, path) {
    if (path.indexOf(root) == 0) {
        // without the root + path separator
        return path.substr(root.length + 1);
    } else {
        // out of bounds, ignore
        return path;
    }
}

function copyIncludes(root, dir, out) {
    for (var fc = new Enumerator(dir.Files);
        !fc.atEnd();
        fc.moveNext()) {
        var fci = fc.item();
        if (fci.Name.match(".h$") != null) {
            var relPath = relative(root, fc.item().Path);
            if (relPath.match(IGNORE_RE) == null) {
                stdout.WriteLine("->> " + relPath);
                fci.Copy(out.Path + "\\" + relPath, true);
            }
        }
    }
    for (var fc = new Enumerator(dir.SubFolders);
        !fc.atEnd();
        fc.moveNext()) {
        var dir = fc.item();
        var relPath = relative(root, dir.Path);
        if (relPath.match(IGNORE_RE) == null) {
            var newPath = out.Path + "\\" + relPath;
            try {
                fso.CreateFolder(newPath);
            } catch (e) {
                stdout.WriteLine("WARNING: couldn't create " + newPath +
                    ": " + e.description);
            }
            copyIncludes(root, dir, out);
        }
    }
}

// options.h file generator
function writeOptions(file) {
    file.WriteLine("/* auto-generated options file for win32 */");
    file.WriteLine("");
    file.WriteLine("#ifndef WOLFSSL_OPTIONS_H");
    file.WriteLine("#define WOLFSSL_OPTIONS_H");
    file.WriteLine("");
    file.WriteLine("#ifdef __cplusplus");
    file.WriteLine("extern \"C\" {");
    file.WriteLine("#endif");
    file.WriteLine("");
    for (var def in DEFINES) {
        file.WriteLine("#define " + DEFINES[def]);
    }
    file.WriteLine("");
    file.WriteLine("#ifdef __cplusplus");
    file.WriteLine("}");
    file.WriteLine("#endif");
    file.WriteLine("");
    file.WriteLine("#endif /* WOLFSSL_OPTIONS_H */");
}

if (WScript.Arguments.length < 2) {
    stdout.WriteLine("usage: install.js OUT-DIR Debug|Release");
    WScript.Quit(1);
}

var inRootPath = fso.GetParentFolderName(WScript.ScriptFullName);
var outPath = WScript.Arguments(0);
var profile = WScript.Arguments(1);

var inRoot = fso.GetFolder(inRootPath);
var wssl = fso.GetFolder(inRoot.Path + "\\wolfssl");
var inLibPath = inRoot.Path + "\\" + profile;
try {
    var inLibDir = fso.GetFolder(inLibPath);
} catch (e) {
    stdout.WriteLine("Couldn't find " + inLibPath + " (using profile "
+ profile + "): " + e.description);
    WScript.Quit(1);
}

stdout.WriteLine("Opening " + outPath);

if (fso.FolderExists(outPath)) {
    var outRoot = fso.GetFolder(outPath);
} else {
    var outRoot = fso.CreateFolder(outPath);
}

// Create the include dir and its prereq subdirs
var outIncludePath = outRoot.Path + "\\include";
if (fso.FolderExists(outIncludePath)) {
    var outInclude = fso.GetFolder(outIncludePath);
} else {
    var outInclude = fso.CreateFolder(outIncludePath);
}

if (!fso.FolderExists(outIncludePath + "\\wolfssl")) {
    fso.CreateFolder(outIncludePath + "\\wolfssl");
}

// Copy all exposed headers to the include path
copyIncludes(inRoot.Path, wssl, outInclude);

// Modify options.h with our pre-defined options
var optsPath = outIncludePath + "\\wolfssl\\options.h";
var optsFile = fso.CreateTextFile(optsPath, true);

stdout.WriteLine(">> Writing options.h")
writeOptions(optsFile);

// Create the lib dir
var outLibPath = outRoot.Path + "\\lib";
if (!fso.FolderExists(outLibPath)) {
    fso.CreateFolder(outLibPath);
}

stdout.WriteLine(">> Copying wolfssl.lib");
fso.CopyFile(inLibPath + "\\wolfssl.lib", outLibPath + "\\wolfssl.lib",
true);

stdout.WriteLine(">> Done!");
