#include <stdlib.h>
#include <string.h>
#include "unixlauncher.h"
#include "utilsfuncs.h"

using namespace std;

extern "C" int nailgunClientMain(int argc, char *argv[], char *env[]);

UnixLauncher::UnixLauncher()
    : ArgParser()
{
}

UnixLauncher::UnixLauncher(const UnixLauncher& orig)
    : ArgParser(orig)
{
}

UnixLauncher::~UnixLauncher() {
}

int UnixLauncher::run(int argc, char* argv[], char* envp[]) {
    platformDir = argv[0];
    if (!initPlatformDir() || !parseArgs(argc - 1, argv + 1)) {
        return 255;
    }

    if (nailgunClient) {
        progArgs.push_front("org.jruby.util.NailMain");
        char ** nailArgv = convertToArgvArray(progArgs);
        if (printCommandLine) {
            return printArgvToConsole(nailArgv);
        }
        return nailgunClientMain(progArgs.size(), (char**)nailArgv, envp);
    }

    prepareOptions();

    string java("");

    if (getenv("JAVA_HOME") == NULL) {
      char *path;
      FILE *java_home_pipe;
      char java_home_path[256];

      path = getenv("PATH");
      if (path == NULL || strlen(path) == 0) {
        setenv("PATH", "/usr/bin:/usr/local/bin:/usr/local/jdk-1.7.0/bin", 1);
      } else {
        char *paths[3] = {(char *)"/usr/bin", (char *)"/usr/local/bin", (char *)"/usr/local/jdk-1.7.0/bin"};
        int modified = 0;
        int i;

        strlcpy(java_home_path, path, sizeof(java_home_path));
        for (i = 0; i < 3; i++) {
          if (strstr(path, paths[i]) == NULL) {
            modified = 1;
            strlcat(java_home_path, ":", sizeof(java_home_path));
            strlcat(java_home_path, paths[i], sizeof(java_home_path));
          }
        }

        if (modified == 1) {
          setenv("PATH", java_home_path, 1);
        }
      }

      if(java_home_pipe = popen("javaPathHelper -h jruby", "r")) {
        size_t bytes_read;
        bytes_read = fread(java_home_path, 1, 255, java_home_pipe);
        if (bytes_read > 0) { 
          java_home_path[bytes_read-1] = '\0';
          setenv("JAVA_HOME", java_home_path, 1);
        }
        pclose(java_home_pipe);
      }
    }

    if (getenv("JAVACMD") != NULL) {
        java = getenv("JAVACMD");
    } else {
        if (!jdkhome.empty()) {
            java = jdkhome + "/bin/java";
        } else if (getenv("JAVA_HOME") != NULL) {
            java = string(getenv("JAVA_HOME")) + "/bin/java";
        } else {
            java = findOnPath("java");
        }
    }

    if (java.empty()) {
        printToConsole("No `java' executable found on PATH.");
        return 255;
    }

    list<string> commandLine;
    commandLine.push_back(java);
    addOptionsToCommandLine(commandLine);

    logMsg("Command line:");
    for (list<string>::iterator it = commandLine.begin(); it != commandLine.end(); ++it) {
        logMsg(it->c_str());
    }

    char** newArgv = convertToArgvArray(commandLine);

    if (printCommandLine) {
        return printArgvToConsole(newArgv);
    }


    if (!fileExists(java.c_str())) {
        string msg = "No `java' exists at " + java + ", please double-check JAVA_HOME.\n";
        printToConsole(msg.c_str());
        return 255;
    }

    execv(java.c_str(), newArgv);

    // shouldn't get here unless something bad happened with execv
    logErr(true, true, "execv failed:");
    return 255;
}
