// Copyright 2017 The Bazel Authors. All rights reserved.
//
// Licensed 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.

#include <memory>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>

#include "src/main/cpp/util/file.h"
#include "src/main/cpp/util/file_platform.h"
#include "src/main/cpp/util/path_platform.h"
#include "src/main/cpp/util/strings.h"
#include "src/main/native/windows/file.h"
#include "src/tools/launcher/java_launcher.h"
#include "src/tools/launcher/util/launcher_util.h"

namespace bazel {
namespace launcher {

using std::getline;
using std::ofstream;
using std::ostringstream;
using std::string;
using std::stringstream;
using std::vector;
using std::wstring;

// The runfile path of java binary, eg. local_jdk/bin/java.exe
static constexpr const char* JAVA_BIN_PATH = "java_bin_path";
static constexpr const char* JAR_BIN_PATH = "jar_bin_path";
static constexpr const char* CLASSPATH = "classpath";
static constexpr const char* JAVA_START_CLASS = "java_start_class";
static constexpr const char* JVM_FLAGS = "jvm_flags";

// Check if a string start with a certain prefix.
// If it's true, store the substring without the prefix in value.
// If value is quoted, then remove the quotes.
static bool GetFlagValue(const string& str, const string& prefix,
                         string* value_ptr) {
  if (str.compare(0, prefix.length(), prefix)) {
    return false;
  }
  string& value = *value_ptr;
  value = str.substr(prefix.length());
  int len = value.length();
  if (len >= 2 && value[0] == '"' && value[len - 1] == '"') {
    value = value.substr(1, len - 2);
  }
  return true;
}

// Parses one launcher flag and updates this object's state accordingly.
//
// Returns true if the flag is a valid launcher flag; false otherwise.
bool JavaBinaryLauncher::ProcessWrapperArgument(const string& argument) {
  string flag_value;
  if (argument.compare("--debug") == 0) {
    string default_jvm_debug_port;
    if (GetEnv("DEFAULT_JVM_DEBUG_PORT", &default_jvm_debug_port)) {
      this->jvm_debug_port = default_jvm_debug_port;
    } else {
      this->jvm_debug_port = "5005";
    }
  } else if (GetFlagValue(argument, "--debug=", &flag_value)) {
    this->jvm_debug_port = flag_value;
  } else if (GetFlagValue(argument, "--main_advice=", &flag_value)) {
    this->main_advice = flag_value;
  } else if (GetFlagValue(argument, "--main_advice_classpath=", &flag_value)) {
    this->main_advice_classpath = flag_value;
  } else if (GetFlagValue(argument, "--jvm_flag=", &flag_value)) {
    this->jvm_flags_cmdline.push_back(flag_value);
  } else if (GetFlagValue(argument, "--jvm_flags=", &flag_value)) {
    stringstream flag_value_ss(flag_value);
    string item;
    while (getline(flag_value_ss, item, ' ')) {
      this->jvm_flags_cmdline.push_back(item);
    }
  } else if (argument.compare("--singlejar") == 0) {
    this->singlejar = true;
  } else if (argument.compare("--print_javabin") == 0) {
    this->print_javabin = true;
  } else if (GetFlagValue(argument, "--classpath_limit=", &flag_value)) {
    this->classpath_limit = std::stoi(flag_value);
  } else {
    return false;
  }
  return true;
}

vector<string> JavaBinaryLauncher::ProcessesCommandLine() {
  vector<string> args;
  bool first = 1;
  for (const auto& arg : this->GetCommandlineArguments()) {
    // Skip the first arugment.
    if (first) {
      first = 0;
      continue;
    }
    string flag_value;
    // TODO(pcloudy): Should rename this flag to --native_launcher_flag.
    // But keep it as it is for now to be consistent with the shell script
    // launcher.
    if (GetFlagValue(arg, "--wrapper_script_flag=", &flag_value)) {
      if (!ProcessWrapperArgument(flag_value)) {
        die("invalid wrapper argument '%s'", arg.c_str());
      }
    } else if (!args.empty() || !ProcessWrapperArgument(arg)) {
      args.push_back(arg);
    }
  }
  return args;
}

// Return an absolute normalized path for the directory of manifest jar
static string GetManifestJarDir(const string& binary_base_path) {
  string abs_manifest_jar_dir;
  std::size_t slash = binary_base_path.find_last_of("/\\");
  if (slash == string::npos) {
    abs_manifest_jar_dir = "";
  } else {
    abs_manifest_jar_dir = binary_base_path.substr(0, slash);
  }
  if (!blaze_util::IsAbsolute(binary_base_path)) {
    abs_manifest_jar_dir = blaze_util::GetCwd() + "\\" + abs_manifest_jar_dir;
  }
  string result;
  if (!NormalizePath(abs_manifest_jar_dir, &result)) {
    die("GetManifestJarDir Failed");
  }
  return result;
}

static void WriteJarClasspath(const string& jar_path,
                              ostringstream* manifest_classpath) {
  *manifest_classpath << ' ';
  if (jar_path.find_first_of(" \\") != string::npos) {
    for (const auto& x : jar_path) {
      if (x == ' ') {
        *manifest_classpath << "%20";
      }
      if (x == '\\') {
        *manifest_classpath << "/";
      } else {
        *manifest_classpath << x;
      }
    }
  } else {
    *manifest_classpath << jar_path;
  }
}

string JavaBinaryLauncher::GetJunctionBaseDir() {
  string binary_base_path =
      GetBinaryPathWithExtension(this->GetCommandlineArguments()[0]);
  string result;
  if (!NormalizePath(binary_base_path + ".j", &result)) {
    die("Failed to get normalized junction base directory.");
  }
  return result;
}

void JavaBinaryLauncher::DeleteJunctionBaseDir() {
  string junction_base_dir_norm = GetJunctionBaseDir();
  if (!DoesDirectoryPathExist(junction_base_dir_norm.c_str())) {
    return;
  }
  vector<string> junctions;
  blaze_util::GetAllFilesUnder(junction_base_dir_norm, &junctions);
  for (const auto& junction : junctions) {
    if (!DeleteDirectoryByPath(junction.c_str())) {
      PrintError(GetLastErrorString().c_str());
    }
  }
  if (!DeleteDirectoryByPath(junction_base_dir_norm.c_str())) {
    PrintError(GetLastErrorString().c_str());
  }
}

string JavaBinaryLauncher::CreateClasspathJar(const string& classpath) {
  string binary_base_path =
      GetBinaryPathWithoutExtension(this->GetCommandlineArguments()[0]);
  string abs_manifest_jar_dir_norm = GetManifestJarDir(binary_base_path);

  ostringstream manifest_classpath;
  manifest_classpath << "Class-Path:";
  stringstream classpath_ss(classpath);
  string path, path_norm;

  // A set to store all junctions created.
  // The key is the target path, the value is the junction path.
  std::unordered_map<string, string> jar_dirs;
  string junction_base_dir_norm = GetJunctionBaseDir();
  int junction_count = 0;
  // Make sure the junction base directory doesn't exist already.
  DeleteJunctionBaseDir();
  blaze_util::MakeDirectories(junction_base_dir_norm, 0755);

  while (getline(classpath_ss, path, ';')) {
    if (blaze_util::IsAbsolute(path)) {
      if (!NormalizePath(path, &path_norm)) {
        die("CreateClasspathJar failed");
      }

      // If two paths are under different drives, we should create a junction to
      // the jar's directory
      if (path_norm[0] != abs_manifest_jar_dir_norm[0]) {
        string jar_dir = GetParentDirFromPath(path_norm);
        string jar_base_name = GetBaseNameFromPath(path_norm);
        string junction;
        auto search = jar_dirs.find(jar_dir);
        if (search == jar_dirs.end()) {
          junction =
              junction_base_dir_norm + "\\" + std::to_string(junction_count++);

          wstring wjar_dir(
              blaze_util::CstringToWstring(junction.c_str()).get());
          wstring wjunction(
              blaze_util::CstringToWstring(jar_dir.c_str()).get());
          wstring werror(bazel::windows::CreateJunction(wjar_dir, wjunction));
          if (!werror.empty()) {
            string error(werror.begin(), werror.end());
            die("CreateClasspathJar failed: %s", error.c_str());
          }

          jar_dirs.insert(std::make_pair(jar_dir, junction));
        } else {
          junction = search->second;
        }
        path_norm = junction + "\\" + jar_base_name;
      }

      if (!RelativeTo(path_norm, abs_manifest_jar_dir_norm, &path)) {
        die("CreateClasspathJar failed");
      }
    }
    WriteJarClasspath(path, &manifest_classpath);
  }

  string rand_id = "-" + GetRandomStr(10);
  string jar_manifest_file_path = binary_base_path + rand_id + ".jar_manifest";
  ofstream jar_manifest_file(jar_manifest_file_path);
  jar_manifest_file << "Manifest-Version: 1.0\n";
  // No line in the MANIFEST.MF file may be longer than 72 bytes.
  // A space prefix indicates the line is still the content of the last
  // attribute.
  string manifest_classpath_str = manifest_classpath.str();
  for (size_t i = 0; i < manifest_classpath_str.length(); i += 71) {
    if (i > 0) {
      jar_manifest_file << " ";
    }
    jar_manifest_file << manifest_classpath_str.substr(i, 71) << "\n";
  }
  jar_manifest_file.close();

  // Create the command for generating classpath jar.
  string manifest_jar_path = binary_base_path + rand_id + "-classpath.jar";
  string jar_bin = this->Rlocation(this->GetLaunchInfoByKey(JAR_BIN_PATH));
  vector<string> arguments;
  arguments.push_back("cvfm");
  arguments.push_back(manifest_jar_path);
  arguments.push_back(jar_manifest_file_path);

  if (this->LaunchProcess(jar_bin, arguments, /* suppressOutput */ true) != 0) {
    die("Couldn't create classpath jar: %s", manifest_jar_path.c_str());
  }

  // Delete jar_manifest_file after classpath jar is created.
  DeleteFileByPath(jar_manifest_file_path.c_str());

  return manifest_jar_path;
}

ExitCode JavaBinaryLauncher::Launch() {
  // Parse the original command line.
  vector<string> remaining_args = this->ProcessesCommandLine();

  // Set JAVA_RUNFILES
  string java_runfiles;
  if (!GetEnv("JAVA_RUNFILES", &java_runfiles)) {
    java_runfiles = this->GetRunfilesPath();
  }
  SetEnv("JAVA_RUNFILES", java_runfiles);

  // Print Java binary path if needed
  string java_bin = this->Rlocation(this->GetLaunchInfoByKey(JAVA_BIN_PATH),
                                    /*need_workspace_name =*/false);
  if (this->print_javabin ||
      this->GetLaunchInfoByKey(JAVA_START_CLASS) == "--print_javabin") {
    printf("%s\n", java_bin.c_str());
    return 0;
  }

  ostringstream classpath;

  // Run deploy jar if needed, otherwise generate the CLASSPATH by rlocation.
  if (this->singlejar) {
    string deploy_jar =
        GetBinaryPathWithoutExtension(this->GetCommandlineArguments()[0]) +
        "_deploy.jar";
    if (!DoesFilePathExist(deploy_jar.c_str())) {
      die("Option --singlejar was passed, but %s does not exist.\n  (You may "
          "need to build it explicitly.)",
          deploy_jar.c_str());
    }
    classpath << deploy_jar << ';';
  } else {
    // Add main advice classpath if exists
    if (!this->main_advice_classpath.empty()) {
      classpath << this->main_advice_classpath << ';';
    }
    string path;
    stringstream classpath_ss(this->GetLaunchInfoByKey(CLASSPATH));
    while (getline(classpath_ss, path, ';')) {
      classpath << this->Rlocation(path) << ';';
    }
  }

  // Set jvm debug options
  ostringstream jvm_debug_flags;
  if (!this->jvm_debug_port.empty()) {
    string jvm_debug_suspend;
    if (!GetEnv("DEFAULT_JVM_DEBUG_SUSPEND", &jvm_debug_suspend)) {
      jvm_debug_suspend = "y";
    }
    jvm_debug_flags << "-agentlib:jdwp=transport=dt_socket,server=y";
    jvm_debug_flags << ",suspend=" << jvm_debug_suspend;
    jvm_debug_flags << ",address=" << jvm_debug_port;

    string value;
    if (GetEnv("PERSISTENT_TEST_RUNNER", &value) && value == "true") {
      jvm_debug_flags << ",quiet=y";
    }
  }

  // Get jvm flags from JVM_FLAGS environment variable and JVM_FLAGS launch info
  vector<string> jvm_flags;
  string jvm_flags_env;
  GetEnv("JVM_FLAGS", &jvm_flags_env);
  string flag;
  stringstream jvm_flags_env_ss(jvm_flags_env);
  while (getline(jvm_flags_env_ss, flag, ' ')) {
    jvm_flags.push_back(flag);
  }
  stringstream jvm_flags_launch_info_ss(this->GetLaunchInfoByKey(JVM_FLAGS));
  while (getline(jvm_flags_launch_info_ss, flag, ' ')) {
    jvm_flags.push_back(flag);
  }

  // Check if TEST_TMPDIR is available to use for scratch.
  string test_tmpdir;
  if (GetEnv("TEST_TMPDIR", &test_tmpdir) &&
      DoesDirectoryPathExist(test_tmpdir.c_str())) {
    jvm_flags.push_back("-Djava.io.tmpdir=" + test_tmpdir);
  }

  // Construct the final command line arguments
  vector<string> arguments;
  // Add classpath flags
  arguments.push_back("-classpath");
  // Check if CLASSPATH is over classpath length limit.
  // If it does, then we create a classpath jar to pass CLASSPATH value.
  string classpath_str = classpath.str();
  string classpath_jar = "";
  if (classpath_str.length() > this->classpath_limit) {
    classpath_jar = CreateClasspathJar(classpath_str);
    arguments.push_back(classpath_jar);
  } else {
    arguments.push_back(classpath_str);
  }
  // Add JVM debug flags
  string jvm_debug_flags_str = jvm_debug_flags.str();
  if (!jvm_debug_flags_str.empty()) {
    arguments.push_back(jvm_debug_flags_str);
  }
  // Add JVM flags parsed from env and launch info.
  for (const auto& arg : jvm_flags) {
    arguments.push_back(arg);
  }
  // Add JVM flags parsed from command line.
  for (const auto& arg : this->jvm_flags_cmdline) {
    arguments.push_back(arg);
  }
  // Add main advice class
  if (!this->main_advice.empty()) {
    arguments.push_back(this->main_advice);
  }
  // Add java start class
  arguments.push_back(this->GetLaunchInfoByKey(JAVA_START_CLASS));
  // Add the remaininng arguements, they will be passed to the program.
  for (const auto& arg : remaining_args) {
    arguments.push_back(arg);
  }

  vector<string> escaped_arguments;
  // Quote the arguments if having spaces
  for (const auto& arg : arguments) {
    escaped_arguments.push_back(
        GetEscapedArgument(arg, /*escape_backslash = */ false));
  }

  ExitCode exit_code = this->LaunchProcess(java_bin, escaped_arguments);

  // Delete classpath jar file after execution.
  if (!classpath_jar.empty()) {
    DeleteFileByPath(classpath_jar.c_str());
    DeleteJunctionBaseDir();
  }

  return exit_code;
}

}  // namespace launcher
}  // namespace bazel
