/*
 * Jakefile
 * EACalvin
 *
 * Created by You on October 21, 2016.
 * Copyright 2016, Your Company All rights reserved.
 */

var ENV = require("system").env,
    FILE = require("file"),
    JAKE = require("jake"),
    task = JAKE.task,
    FileList = JAKE.FileList,
    app = require("cappuccino/jake").app,
    configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
    OS = require("os"),
    projectName = "EACalvin";

app (projectName, function(task)
{
    ENV["OBJJ_INCLUDE_PATHS"] = "Frameworks";

    if (configuration === "Debug")
        ENV["OBJJ_INCLUDE_PATHS"] = FILE.join(ENV["OBJJ_INCLUDE_PATHS"], configuration);

    task.setBuildIntermediatesPath(FILE.join("Build", "EACalvin.build", configuration));
    task.setBuildPath(FILE.join("Build", configuration));

    task.setProductName("EACalvin");
    task.setIdentifier("com.yourcompany.EACalvin");
    task.setVersion("#"+get_commit_hash());
    task.setAuthor("Ericsson Research");
    task.setEmail("feedback @nospam@ yourcompany.com");
    task.setSummary("EACalvin");
    task.setSources(new FileList("**/*.j").exclude(FILE.join("Build", "**")).exclude(FILE.join("Frameworks", "Source", "**")));
    task.setResources(new FileList("Resources/**"));
    task.setIndexFilePath("index.html");
    task.setInfoPlistPath("Info.plist");

    if (configuration === "Debug")
        task.setCompilerFlags("-DDEBUG -g");
    else
        task.setCompilerFlags("-O2");
    print("Objj flags:" + task.compilerFlags())
});

function get_commit_hash()
{
    var cmd = ["git", "log", "--pretty=format:%h", "-n", "1"], res = null, err = null; 
    try {
        var p = OS.popen(cmd);
        if (p.wait() !== 0) {
            // CPLog.warn(cmd[0] + " failed. Ensure it's installed and on your PATH.");
            err = p.stderr.read();
        } else {
            res = p.stdout.read();
        }
    }
    finally {
        p.stdin.close();
        p.stdout.close();
        p.stderr.close();
    }
    if (err !== null) {
        throw new Error(err);
    }
    return res;    
}

task ("default", [projectName], function()
{
    printResults(configuration);
});

task ("build", ["default"], function()
{
    updateApplicationSize();
});

task ("debug", function()
{
    configuration = ENV["CONFIGURATION"] = "Debug";
    JAKE.subjake(["."], "build", ENV);
});

task ("release", function()
{
    configuration = ENV["CONFIGURATION"] = "Release";
    JAKE.subjake(["."], "build", ENV);
});

task ("run", ["debug"], function()
{
    OS.system(["open", FILE.join("Build", "Debug", projectName, "index.html")]);
});

task ("run-release", ["release"], function()
{
    OS.system(["open", FILE.join("Build", "Release", projectName, "index.html")]);
});

task ("deploy", ["release"], function()
{
    FILE.mkdirs(FILE.join("Build", "Deployment", projectName));
    OS.system(["press", "-f", FILE.join("Build", "Release", projectName), FILE.join("Build", "Deployment", projectName)]);
    printResults("Deployment")
});

task ("desktop", ["release"], function()
{
    FILE.mkdirs(FILE.join("Build", "Desktop", projectName));
    require("cappuccino/nativehost").buildNativeHost(FILE.join("Build", "Release", projectName), FILE.join("Build", "Desktop", projectName, "EACalvin.app"));
    printResults("Desktop")
});

task ("run-desktop", ["desktop"], function()
{
    OS.system([FILE.join("Build", "Desktop", projectName, "EACalvin.app", "Contents", "MacOS", "NativeHost"), "-i"]);
});

function printResults(configuration)
{
    print("----------------------------");
    print(configuration+" app built at path: "+FILE.join("Build", configuration, projectName));
    print("----------------------------");
}

task ("push", [], function()
{
    keypath = ENV["JAKE_KEYPATH"]
    dest = ENV["JAKE_DEPLOYPATH"]
    if (!keypath || !dest) {
      print("Must specify JAKE_KEYPATH (.ssh/jake.key) and JAKE_DEPLOYPATH (e.g. user@some.host:/var/www/html/), see task 'push'")
    } else {
      OS.system(["scp", "-i", keypath, "-r", FILE.join("Build", "Deployment", projectName), dest]);
    }
});

task ("push-release", ["deploy", "push"], function()
{
    print("----------------------------");
    print("Push-Release completed");
    print("----------------------------");
});

task ("calvin", [], function()
{
    OS.system(["rm", "-rf", FILE.join("Build", "Deployment", projectName, "Frameworks", "Debug")]);
    OS.system(["rm", "-rf", FILE.join("Build", "Deployment", projectName, "Frameworks", "AppKit", "Resources", "Aristo.blend")]);
    OS.system(["rm", "-rf", FILE.join("Build", "GUI")]);
    OS.system(["mkdir", "-p", FILE.join("Build", "GUI")]);
    OS.system(["cp", "-a", FILE.join("Build", "Deployment", projectName, ""), FILE.join("Build", "GUI", "")]);
});

task ("calvin-release", ["deploy", "calvin"], function()
{
    print("----------------------------");
    print("calvin-release completed");
    print("----------------------------");
});


function updateApplicationSize()
{
    print("Calculating application file sizes...");

    var contents = FILE.read(FILE.join("Build", configuration, projectName, "Info.plist"), { charset:"UTF-8" }),
        format = CFPropertyList.sniffedFormatOfString(contents),
        plist = CFPropertyList.propertyListFromString(contents),
        totalBytes = {executable:0, data:0, mhtml:0};

    // Get the size of all framework executables and sprite data
    var frameworksDir = "Frameworks";

    if (configuration === "Debug")
        frameworksDir = FILE.join(frameworksDir, "Debug");

    var frameworks = FILE.list(frameworksDir);

    frameworks.forEach(function(framework)
    {
        if (framework !== "Source")
            addBundleFileSizes(FILE.join(frameworksDir, framework), totalBytes);
    });

    // Read in the default theme name, and attempt to get its size
    var themeName = plist.valueForKey("CPDefaultTheme") || "Aristo2",
        themePath = nil;

    if (themeName === "Aristo" || themeName === "Aristo2")
        themePath = FILE.join(frameworksDir, "AppKit", "Resources", themeName + ".blend");
    else
        themePath = FILE.join("Frameworks", "Resources", themeName + ".blend");

    if (FILE.isDirectory(themePath))
        addBundleFileSizes(themePath, totalBytes);

    // Add sizes for the app
    addBundleFileSizes(FILE.join("Build", configuration, projectName), totalBytes);

    print("Executables: " + totalBytes.executable + ", sprite data: " + totalBytes.data + ", total: " + (totalBytes.executable + totalBytes.data));

    var dict = new CFMutableDictionary();

    dict.setValueForKey("executable", totalBytes.executable);
    dict.setValueForKey("data", totalBytes.data);
    dict.setValueForKey("mhtml", totalBytes.mhtml);

    plist.setValueForKey("CPApplicationSize", dict);

    FILE.write(FILE.join("Build", configuration, projectName, "Info.plist"), CFPropertyList.stringFromPropertyList(plist, format), { charset:"UTF-8" });
}

function addBundleFileSizes(bundlePath, totalBytes)
{
    var bundleName = FILE.basename(bundlePath),
        environment = bundleName === "Foundation" ? "Objj" : "Browser",
        bundlePath = FILE.join(bundlePath, environment + ".environment");

    if (FILE.isDirectory(bundlePath))
    {
        var filename = bundleName + ".sj",
            filePath = new FILE.Path(FILE.join(bundlePath, filename));

        if (filePath.exists())
            totalBytes.executable += filePath.size();

        filePath = new FILE.Path(FILE.join(bundlePath, "dataURLs.txt"));

        if (filePath.exists())
            totalBytes.data += filePath.size();

        filePath = new FILE.Path(FILE.join(bundlePath, "MHTMLData.txt"));

        if (filePath.exists())
            totalBytes.mhtml += filePath.size();

        filePath = new FILE.Path(FILE.join(bundlePath, "MHTMLPaths.txt"));

        if (filePath.exists())
            totalBytes.mhtml += filePath.size();
    }
}
