importPackage(java.io);

//@include lib_Class.js

/**
 * Execution utils
 *
 * @eloas
 * @eloix
 * @elojc
 */
sol.define("sol.common.ExecUtils", {

  singleton: true,

  /**
   * Starts a process
   * @param {Array} args Arguments
   * @param {Object} config Config
   * @param {String} config.dir Directory
   * @param {Boolean} config.wait Wait
   * @return {Object} Result
   */
  startProcess: function (args, config) {
    var process,
        outputArr = [],
        processBuilder, scanner, returnCode;

    config = config || {};

    processBuilder = new java.lang.ProcessBuilder(java.util.Arrays.asList(args));
    processBuilder.redirectErrorStream(true);

    if (config.dir) {
      processBuilder.directory(new File(config.dir));
    }

    process = processBuilder.start();
    if (config.wait == false) {
      return;
    }
    scanner = new java.util.Scanner(process.inputStream).useDelimiter("\\Z");
    while (scanner.hasNextLine()) {
      outputArr.push(scanner.nextLine());
    }
    scanner.close();
    returnCode = process.waitFor();
    return {
      returnCode: returnCode,
      output: outputArr.join("\r\n")
    };
  },

  /**
   * Opens a file by "ShellExecute"
   * @param {String} path
   */
  open: function (path) {
    if (!path) {
      return;
    }
    var file = new File(path);
    if (!file.exists()) {
      return;
    }
    Packages.java.awt.Desktop.getDesktop().open(file);
  },

  /**
   * Returns the user profile directory
   * @return {String} Path of the user profile directory
   */
  getUserProfileDir: function () {
    return String(java.lang.System.getenv("UserProfile"));
  },

  /**
   * Returns the program files directory
   * @return {String} Path of the program files directory
   */
  getProgramFilesDir: function () {
    return String(java.lang.System.getenv("ProgramFiles"));
  },

  /**
   * Returns the Program files directory
   * @return {String} Path of the Program files directory
   */
  getProgramFilesX86Dir: function () {
    return String(java.lang.System.getenv("ProgramFiles(x86)"));
  },

  /**
   * Runs a batch file in a command window
   * @param {Array} args Arguments. The first element must be the batch file name
   * @param {Object} params Parameters
   * @param {String} params.dir Directory
   */
  runBatchFileInWindow: function (args, params) {
    var dir = null,
        cmdString, argsString;

    params = params || {};
    if (!args || (args.length == 0)) {
      throw "The batch file name is empty";
    }
    if (params.dir) {
      dir = new File(params.file);
    }

    cmdString = 'cmd.exe /c start cmd.exe /k \"{0}\"';

    args = args.map(function (arg) {
      return '"' + arg + '"';
    });
    argsString = args.join(" ");
    cmdString = cmdString.replace("{0}", argsString);

    java.lang.Runtime.runtime.exec(cmdString, null, dir);
  },

  /**
   * Detects if the script runs inside Tomcat
   * @return {Boolean}
   */
  insideTomcat: function () {
    try {
      java.lang.Class.forName("org.apache.catalina.util.ServerInfo");
      return true;
    } catch (ignore) {
      // ignore
    }
    return false;
  },

  /**
   * Logs system info
   * @param {de.elo.ix.client.IXConnection} conn IXConnection
   */
  logSystemInfo: function (conn) {
    var me = this,
        connTimeZone, connTimeZoneOffset;

    if (!me.logger.debugEnabled) {
      return;
    }

    conn = conn || ixConnect;

    me.logger.debug(["java.version={0}", me.getJavaVersion()]);
    me.logger.debug(["java.timezone={0}, java.timeZoneOffset={1}", me.getJavaTimeZoneString(), me.getJavaTimeZoneOffsetString()]);


    me.logger.debug(["conn.userName={0}, conn.userName={1}", conn.loginResult.user.id + "", conn.loginResult.user.name + ""]);

    connTimeZone = conn.loginResult.clientInfo.timeZone;
    connTimeZoneOffset = me.getTimeZoneOffsetString(connTimeZone);

    me.logger.debug(["conn.timeZone={0}, conn.timeZoneOffset={1}", connTimeZone + "", connTimeZoneOffset + ""]);
  },

  /**
   * Returns the Java version
   * @return {String} Java version
   */
  getJavaVersion: function () {
    var javaRuntimeName, javaRuntimeVersion, bitness, javaVersion;

    javaRuntimeName = String(java.lang.System.getProperty("java.runtime.name"));
    javaRuntimeVersion = String(java.lang.System.getProperty("java.runtime.version"));
    bitness = String(java.lang.System.getProperty("sun.arch.data.model"));
    javaVersion = javaRuntimeName + " " + javaRuntimeVersion + " - " + bitness + " bit";
    return javaVersion;
  },

  /**
   * Returns the Java main version number
   * @return {Integer} Java main version number
   */
  getJavaMainVersionNumber: function () {
    var versionString, mainVersionString, dotPos, mainVersionNumber;
    versionString = java.lang.System.getProperty("java.version") + "";
    if (versionString.indexOf("1.") == 0) {
      mainVersionString = versionString.substring(2, 3);
    } else {
      dotPos = versionString.indexOf(".");
      if (dotPos > -1) {
        mainVersionString = versionString.substring(0, dotPos);
      }
    }

    mainVersionNumber = parseInt(mainVersionString, 10);

    return mainVersionNumber;
  },

  /**
   * Returns the Java time zone string
   * @return {String} Java time zone string
   */
  getJavaTimeZoneString: function () {
    var timeZone;

    timeZone = java.time.ZoneId.systemDefault().toString();

    return timeZone;
  },

  /**
   * Returns the Java time zone offset string
   * @return {String} Java time zone offset string
   */
  getJavaTimeZoneOffsetString: function () {
    var zoneId, offsetString;

    zoneId = java.time.ZoneId.systemDefault();
    offsetString = zoneId.rules.getOffset(java.time.Instant.now()).toString();

    return offsetString;
  },

  /**
   * Returns the time zone offset string from a given time zone string
   * @param {String} timeZoneString Time zone string
   * @return {String} Time zone offset string
   */
  getTimeZoneOffsetString: function (timeZoneString) {
    var zoneId, offsetString;

    zoneId = java.time.ZoneId.of(timeZoneString);
    offsetString = zoneId.rules.getOffset(java.time.Instant.now()).toString();

    return offsetString;
  }
});