//   Licensed to the Apache Software Foundation (ASF) under one or more
//   contributor license agreements.  See the NOTICE file distributed with
//   this work for additional information regarding copyright ownership.
//   The ASF licenses this file to You under the Apache License, Version 2.0
//   (the "License"); you may not use this file except in compliance with
//   the License.  You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//   $Id$ -->

// jscript to run FOP, adapted from the Jakarta-Ant project.

// rpm_mode is irrelevant on Windows
// var rpm_mode=true;
var fop_exec_args = "";
var no_config=false;
var fop_exec_debug=false;
var debug=false;
var keep_open=false;
var show_help=false;

var config_wanted = new Array("FOP_HOME", "CLASSPATH", "FOP_HYPHENATION_PATH", "FOP_OPTS", "JAVA_OPTS", "LOGCHOICE", "LOGLEVEL");

// parse command-line arguments
function read_args() {
  var args = WScript.Arguments;
  var named = new ActiveXObject("Scripting.Dictionary");
  for (i = 0; i < args.length; i++) {
	switch(args(i)) {
	case "--debug":
	  debug=true;
	  break;
	case "--execdebug":
	  fop_exec_debug=true;
	  break;
	case "--keepopen":
	  keep_open=true;
	  break;
	case "--noconfig":
	  no_config=true;
	  break;
	case "-h":
	case "--help":
	case "--h":
	case "-help":
	  show_help=true;
	  // fop_exec_args=fop_exec_args + " -h";
	  break;
	default:
	  fop_exec_args=fop_exec_args + " " + args(i);
	}
  }
  if (debug) {
	WScript.Echo("debug: " + debug);
	WScript.Echo("execdebug: " + fop_exec_debug);
 	WScript.Echo("keepopen: " + keep_open);
 	WScript.Echo("noconfig: " + no_config);
	WScript.Echo("help: " + show_help);
 	WScript.Echo("fop arguments: " + fop_exec_args);
  }
}

var help_text="Usage:\n"
  + WScript.ScriptFullName + " [script options] [FOP options]\n"
  + "Script Options:\n"
  + "  --help, -h             print this message and FOP help\n"
  + "  --debug                print debugging information for this launch script\n"
  + "  --execdebug            print FOP exec line generated by this launch script\n"
  + "  --keepopen             keep FOP's command window open\n"
  + "  --noconfig             suppress reading of configuration file and registry";

function read_environment() {
  for (i in config_wanted) {
	if (!config.Exists(config_wanted[i])) {
		var env_var_string = "%" + config_wanted[i] + "%";
		var env_var = shell.ExpandEnvironmentStrings(env_var_string);
		if (env_var != "" && env_var != env_var_string) {
		  config.Add(config_wanted[i], env_var);
		  if (debug) {
			WScript.Echo(config_wanted[i] + " env: "
						 + config.Item(config_wanted[i]));
		  }
		}
	}
  }
}

function read_desktop(dtname) {
  if (fs.FolderExists(dtname)) {
	var fopname = fs.GetFolder(dtname).ParentFolder.Path
	  + "\\Application Data\\Fop";
	if (fs.FolderExists(fopname)) {
	  var fop_conf_name = fs.GetFolder(fopname).Path + "\\fop.conf";
	  if (fs.FileExists(fop_conf_name)) {
		// source fop_conf_file
		var conf_file = fs.openTextFile(fs.GetFile(fop_conf_name));
		var conf_lines = new ActiveXObject("Scripting.Dictionary");
		while (!conf_file.AtEndOfStream) {
		  var line = conf_file.ReadLine();
		  var m = line.match(/(.+?)=(.+)/);
		  if (m != null) {
			conf_lines.Add(m[1], m[2]);
		  }
		}
		for (j in config_wanted) {
		  if (!config.Exists(config_wanted[j])
			  && conf_lines.Exists(config_wanted[j])) {
			config.Add(config_wanted[j], conf_lines.Item(config_wanted[j]));
			if (debug) {
			  WScript.Echo(config_wanted[j] + " " + dts[i] + ": "
						   + config.Item(config_wanted[i]));
			}
		  }
		}
	  }
	}
  }
}

function read_registry(section) {
  for (j in config_wanted) {
	if (!config.Exists(config_wanted[j])) {
	  var reg_var;
	  try {
		reg_var = shell.RegRead(section + "\\Software\\Fop\\"
								+ config_wanted[j]);
		config.Add(config_wanted[j], reg_var);
		if (debug) {
		  WScript.Echo(config_wanted[j] + " " + rks[i] + ": "
					   + config.Item(config_wanted[j]));
		}
	  } catch(e) {}
	}
  }
}

// construct FOP_HOME from the script folder
function get_fop_home() {
  if (!config.Exists("FOP_HOME")
	  || !fs.FolderExists(config.Item("FOP_HOME"))) {
	var fop_home = WScript.ScriptFullName;
	fop_home = fop_home.substring(0, fop_home.length
								  - WScript.ScriptName.length - 1);
	if (config.Exists("FOP_HOME")) {
	  config.Remove("FOP_HOME");
	}
	config.Add("FOP_HOME", fop_home);
	if (debug) {
	  WScript.Echo("FOP_HOME dyn: " + config.Item("FOP_HOME"));
	}
  }
}

function get_java_cmd() {
  var java_home = shell.ExpandEnvironmentStrings("%JAVA_HOME%");
  javacmd = "java";
  if (java_home != "" && typeof(java_home) != "undefined"
	  && fs.FolderExists(java_home)) {
	var javacmd_candidate = java_home + "\\bin\\java.exe";
	if (fs.FileExists(javacmd_candidate)) {
	  javacmd = javacmd_candidate;
	}
  }
  if (debug) {
	WScript.Echo("java command: " + javacmd);
  }
}

function get_local_classpath() {
  if (config.Exists("CLASSPATH")) {
	local_classpath = config.Item("CLASSPATH");
	if (debug) {
	  WScript.Echo("local classpath: " + local_classpath);
	}
  }

  // add fop.jar, fop-sandbox and fop-hyph.jar, which reside in $FOP_HOME/build
  var lcp = local_classpath;
  local_classpath = config.Item("FOP_HOME") + "\\build\\fop.jar;"
	+ config.Item("FOP_HOME") + "\\build\\fop-sandbox.jar;"
	+ config.Item("FOP_HOME") + "\\build\\fop-hyph.jar";
  if (lcp != "") {
	local_classpath += ";" + lcp;
  }
  if (debug) {
	WScript.Echo("local classpath: " + local_classpath);
  }

  // add in the dependency .jar files, which reside in $FOP_HOME/lib
  var libdir_name = config.Item("FOP_HOME") + "\\lib";
  var dirlibs;
  if (fs.FolderExists(libdir_name)) {
	dirlibs = fs.GetFolder(libdir_name).Files;
	var e = new Enumerator(dirlibs);
	for (; !e.atEnd(); e.moveNext()) {
	  if (e.item().Name.match("\.jar$")) {
		local_classpath = libdir_name + "\\" + e.item().Name + ";" + local_classpath;
	  }
	}
	if (debug) {
	  WScript.Echo("local classpath: " + local_classpath);
	}
  }

  // add in user-defined hyphenation JARs
  if (config.Exists("FOP_HYPHENATION_PATH")) {
	local_classpath += ";" + config.Item("FOP_HYPHENATION_PATH");
	if (debug) {
	  WScript.Echo("local classpath: " + local_classpath);
	}
  }
}

// Execute fop via shell.Exec
function fop_exec() {
  var fop_exec_command = "\"" + javacmd + "\" "
	+ (config.Exists("JAVA_OPTS")?config.Item("JAVA_OPTS") + " ":"")
	+ (config.Exists("LOGCHOICE")?config.Item("LOGCHOICE") + " ":"")
	+ (config.Exists("LOGLEVEL")?config.Item("LOGLEVEL") + " ":"")
	"-classpath \"" + local_classpath + "\" "
	+ (config.Exists("FOP_OPTS")?config.Item("FOP_OPTS"):"")
	+ "org.apache.fop.cli.Main " + fop_exec_args;
  if (debug || fop_exec_debug) {
	WScript.Echo(fop_exec_command);
  }

  var fop_run = shell.Exec(fop_exec_command);
  while (true) {
	while (!fop_run.StdOut.AtEndOfStream) {
	  WScript.Echo(fop_run.StdOut.ReadLine());
	}
	while (!fop_run.StdErr.AtEndOfStream) {
	  WScript.Echo(fop_run.StdErr.ReadLine());
	}
	if (fop_run.Status == 1) {
	  break;
	}
	WScript.Sleep(100);
  }
  if (debug) {
	WScript.Echo("exit status: " + fop_run.ExitCode);
  }
}

// Execute fop via shell.Run
function fop_run() {
  var fop_exec_command = "cmd /" + (keep_open?"K":"C") + " \""
	+ "\"" + javacmd + "\" " 
	+ (config.Exists("JAVA_OPTS")?config.Item("JAVA_OPTS") + " ":"")
	+ (config.Exists("LOGCHOICE")?config.Item("LOGCHOICE") + " ":"")
	+ (config.Exists("LOGLEVEL")?config.Item("LOGLEVEL") + " ":"")
	+ "-classpath \"" + local_classpath + "\" "
	+ (config.Exists("FOP_OPTS")?config.Item("FOP_OPTS") + " ":"")
	+ "org.apache.fop.cli.Main " + fop_exec_args + "\"";
  if (debug || fop_exec_debug) {
	WScript.Echo(fop_exec_command);
  }
  var exit_code = shell.Run(fop_exec_command, 1, 1);
  if (debug) {
	WScript.Echo("exit status: " + exit_code);
  } else {
	if (exit_code != 0) {
	  WScript.Echo("A FOP error occurred (FOP exit status: " + exit_code + ")\n"
	               + "Use option --keepopen to see FOP's output\n"
                       + "(that is two dashes)");
	}
  }
}

function get_log_choice() {
  // The default commons logger for JDK1.4 is JDK1.4Logger.
  // To use a different logger, uncomment the one desired below
  if (!config.Exists("LOGCHOICE")) {
	// config.Add("LOGCHOICE","\"-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.NoOpLog\"");
	// config.Add("LOGCHOICE","\"-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog\"");
	// config.Add("LOGCHOICE","\"-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger\"");
	if (debug && config.Exists("LOGCHOICE")) {
	  WScript.Echo("LOGCHOICE script: " + config.Item("LOGCHOICE"));
	}
  }
}

function get_log_level() {
  // Logging levels
  // Below option is only if you are using SimpleLog instead of the default JDK1.4 Logger.
  // To set logging levels for JDK 1.4 Logger, edit the %JAVA_HOME%/JRE/LIB/logging.properties 
  // file instead.
  // Possible SimpleLog values:  "trace", "debug", "info" (default), "warn", "error", or "fatal".
  if (!config.Exists("LOGLEVEL")) {
	// config.Add("LOGLEVEL","\"-Dorg.apache.commons.logging.simplelog.defaultlog=INFO\"");
	if (debug && config.Exists("LOGLEVEL")) {
	  WScript.Echo("LOGLEVEL script: " + config.Item("LOGLEVEL"));
	}
  }
}

var shell = WScript.CreateObject("WScript.Shell");
var fs = WScript.CreateObject("Scripting.FileSystemObject");

// configuration
var config = new ActiveXObject("Scripting.Dictionary");

read_args();
read_environment();
if (!no_config) {
  // read user and system-wide fop configurations
  var spec = shell.SpecialFolders;
  var dts = new Array("Desktop", "AllUsersDesktop");
  for (i in dts) {
	read_desktop(spec(dts[i]));
  }
  // read user and system-wide registry
  var rks = new Array("HKCU", "HKLM");
  for (i in rks) {
	read_registry(rks[i]);
  }
}

get_fop_home();
get_log_choice();
get_log_level();
var javacmd = "";
get_java_cmd();
var local_classpath = "";
get_local_classpath();

// Show script help if requested
if (show_help) {
  // fop_exec_args = "";
  keep_open = true;
  WScript.Echo(help_text);
}

// fop_exec();
fop_run();