/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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.
 */

#ifndef ART_CMDLINE_CMDLINE_H_
#define ART_CMDLINE_CMDLINE_H_

#include <stdio.h>
#include <stdlib.h>

#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
#include <vector>

#include "android-base/stringprintf.h"
#include "android-base/strings.h"
#include "base/file_utils.h"
#include "base/logging.h"
#include "base/mutex.h"
#include "base/string_view_cpp20.h"
#include "base/utils.h"
#include "noop_compiler_callbacks.h"
#include "oat_file_assistant_context.h"
#include "runtime.h"

#if !defined(NDEBUG)
#define DBG_LOG LOG(INFO)
#else
#define DBG_LOG LOG(DEBUG)
#endif

namespace art {

static Runtime* StartRuntime(const std::vector<std::string>& boot_image_locations,
                             InstructionSet instruction_set,
                             const std::vector<const char*>& runtime_args) {
  RuntimeOptions options;

  // We are more like a compiler than a run-time. We don't want to execute code.
  {
    static NoopCompilerCallbacks callbacks;
    options.push_back(std::make_pair("compilercallbacks", &callbacks));
  }

  // Boot image location.
  {
    std::string boot_image_option = "-Ximage:";
    if (!boot_image_locations.empty()) {
      boot_image_option += android::base::Join(boot_image_locations, ':');
    } else {
      boot_image_option += GetJitZygoteBootImageLocation();
    }
    options.push_back(std::make_pair(boot_image_option, nullptr));
  }

  // Instruction set.
  options.push_back(
      std::make_pair("imageinstructionset",
                     reinterpret_cast<const void*>(GetInstructionSetString(instruction_set))));

  // Explicit runtime args.
  for (const char* runtime_arg : runtime_args) {
    options.push_back(std::make_pair(runtime_arg, nullptr));
  }

  // None of the command line tools need sig chain. If this changes we'll need
  // to upgrade this option to a proper parameter.
  options.push_back(std::make_pair("-Xno-sig-chain", nullptr));
  if (!Runtime::Create(options, false)) {
    fprintf(stderr, "Failed to create runtime\n");
    return nullptr;
  }

  // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
  // give it away now and then switch to a more manageable ScopedObjectAccess.
  Thread::Current()->TransitionFromRunnableToSuspended(ThreadState::kNative);

  return Runtime::Current();
}

struct CmdlineArgs {
  enum ParseStatus {
    kParseOk,               // Parse successful. Do not set the error message.
    kParseUnknownArgument,  // Unknown argument. Do not set the error message.
    kParseError,            // Parse ok, but failed elsewhere. Print the set error message.
  };

  bool Parse(int argc, char** argv) {
    // Skip over argv[0].
    argv++;
    argc--;

    if (argc == 0) {
      fprintf(stderr, "No arguments specified\n");
      PrintUsage();
      return false;
    }

    std::string error_msg;
    for (int i = 0; i < argc; i++) {
      const char* const raw_option = argv[i];
      const std::string_view option(raw_option);
      if (StartsWith(option, "--boot-image=")) {
        Split(raw_option + strlen("--boot-image="), ':', &boot_image_locations_);
      } else if (StartsWith(option, "--instruction-set=")) {
        const char* const instruction_set_str = raw_option + strlen("--instruction-set=");
        instruction_set_ = GetInstructionSetFromString(instruction_set_str);
        if (instruction_set_ == InstructionSet::kNone) {
          fprintf(stderr, "Unsupported instruction set %s\n", instruction_set_str);
          PrintUsage();
          return false;
        }
      } else if (option == "--runtime-arg") {
        if (i + 1 == argc) {
          fprintf(stderr, "Missing argument for --runtime-arg\n");
          PrintUsage();
          return false;
        }
        ++i;
        runtime_args_.push_back(argv[i]);
      } else if (StartsWith(option, "--output=")) {
        output_name_ = std::string(option.substr(strlen("--output=")));
        const char* filename = output_name_.c_str();
        out_.reset(new std::ofstream(filename));
        if (!out_->good()) {
          fprintf(stderr, "Failed to open output filename %s\n", filename);
          PrintUsage();
          return false;
        }
        os_ = out_.get();
      } else {
        ParseStatus parse_status = ParseCustom(raw_option, option.length(), &error_msg);

        if (parse_status == kParseUnknownArgument) {
          fprintf(stderr, "Unknown argument %s\n", option.data());
        }

        if (parse_status != kParseOk) {
          fprintf(stderr, "%s\n", error_msg.c_str());
          PrintUsage();
          return false;
        }
      }
    }

    if (instruction_set_ == InstructionSet::kNone) {
      LOG(WARNING) << "No instruction set given, assuming " << GetInstructionSetString(kRuntimeISA);
      instruction_set_ = kRuntimeISA;
    }

    DBG_LOG << "will call parse checks";

    {
      ParseStatus checks_status = ParseChecks(&error_msg);
      if (checks_status != kParseOk) {
          fprintf(stderr, "%s\n", error_msg.c_str());
          PrintUsage();
          return false;
      }
    }

    return true;
  }

  virtual std::string GetUsage() const {
    std::string usage;

    usage +=  // Required.
        "  --boot-image=<file.art>: provide the image location for the boot class path.\n"
        "      Do not include the arch as part of the name, it is added automatically.\n"
        "      Example: --boot-image=/system/framework/boot.art\n"
        "               (specifies /system/framework/<arch>/boot.art as the image file)\n"
        "\n";
    usage += android::base::StringPrintf(  // Optional.
        "  --instruction-set=(arm|arm64|x86|x86_64): for locating the image\n"
        "      file based on the image location set.\n"
        "      Example: --instruction-set=x86\n"
        "      Default: %s\n"
        "\n",
        GetInstructionSetString(kRuntimeISA));
    usage +=
        "  --runtime-arg <argument> used to specify various arguments for the runtime\n"
        "      such as initial heap size, maximum heap size, and verbose output.\n"
        "      Use a separate --runtime-arg switch for each argument.\n"
        "      Example: --runtime-arg -Xms256m\n"
        "\n";
    usage +=  // Optional.
        "  --output=<file> may be used to send the output to a file.\n"
        "      Example: --output=/tmp/oatdump.txt\n"
        "\n";

    return usage;
  }

  // Specified by --runtime-arg -Xbootclasspath or default.
  std::vector<std::string> boot_class_path_;
  // Specified by --runtime-arg -Xbootclasspath-locations or default.
  std::vector<std::string> boot_class_path_locations_;
  // True if `boot_class_path_` is the default one.
  bool is_default_boot_class_path_ = false;
  // Specified by --boot-image or inferred.
  std::vector<std::string> boot_image_locations_;
  // Specified by --instruction-set.
  InstructionSet instruction_set_ = InstructionSet::kNone;
  // Runtime arguments specified by --runtime-arg.
  std::vector<const char*> runtime_args_;
  // Specified by --output.
  std::ostream* os_ = &std::cout;
  std::unique_ptr<std::ofstream> out_;  // If something besides cout is used
  std::string output_name_;

  virtual ~CmdlineArgs() {}

  // Checks for --boot-image location.
  bool ParseCheckBootImage(std::string* error_msg) {
    if (boot_image_locations_.empty()) {
      LOG(WARNING) << "--boot-image not specified. Starting runtime in imageless mode";
      return true;
    }

    const std::string& boot_image_location = boot_image_locations_[0];
    size_t file_name_idx = boot_image_location.rfind('/');
    if (file_name_idx == std::string::npos) {  // Prevent a InsertIsaDirectory check failure.
      *error_msg = "Boot image location must have a / in it";
      return false;
    }

    // Don't let image locations with the 'arch' in it through, since it's not a location.
    // This prevents a common error "Could not create an image space..." when initing the Runtime.
    if (file_name_idx > 0) {
      size_t ancestor_dirs_idx = boot_image_location.rfind('/', file_name_idx - 1);

      std::string parent_dir_name;
      if (ancestor_dirs_idx != std::string::npos) {
          parent_dir_name = boot_image_location.substr(/*pos=*/ancestor_dirs_idx + 1,
                                                       /*n=*/file_name_idx - ancestor_dirs_idx - 1);
      } else {
          parent_dir_name = boot_image_location.substr(/*pos=*/0,
                                                       /*n=*/file_name_idx);
      }

      DBG_LOG << "boot_image_location parent_dir_name was " << parent_dir_name;

      if (GetInstructionSetFromString(parent_dir_name.c_str()) != InstructionSet::kNone) {
          *error_msg = "Do not specify the architecture as part of the boot image location";
          return false;
      }
    }

    return true;
  }

  void PrintUsage() { fprintf(stderr, "%s", GetUsage().c_str()); }

  std::unique_ptr<OatFileAssistantContext> GetOatFileAssistantContext(std::string* error_msg) {
    if (boot_class_path_.empty()) {
      *error_msg = "Boot classpath is empty";
      return nullptr;
    }

    CHECK(!boot_class_path_locations_.empty());

    return std::make_unique<OatFileAssistantContext>(
        std::make_unique<OatFileAssistantContext::RuntimeOptions>(
            OatFileAssistantContext::RuntimeOptions{
                .image_locations = boot_image_locations_,
                .boot_class_path = boot_class_path_,
                .boot_class_path_locations = boot_class_path_locations_,
            }));
  }

 protected:
  virtual ParseStatus ParseCustom([[maybe_unused]] const char* raw_option,
                                  [[maybe_unused]] size_t raw_option_length,
                                  [[maybe_unused]] std::string* error_msg) {
    return kParseUnknownArgument;
  }

  virtual ParseStatus ParseChecks([[maybe_unused]] std::string* error_msg) {
    ParseBootclasspath();
    if (boot_image_locations_.empty()) {
      InferBootImage();
    }
    return kParseOk;
  }

 private:
  void ParseBootclasspath() {
    std::optional<std::string_view> bcp_str = std::nullopt;
    std::optional<std::string_view> bcp_location_str = std::nullopt;
    for (const char* arg : runtime_args_) {
      if (StartsWith(arg, "-Xbootclasspath:")) {
          bcp_str = arg + strlen("-Xbootclasspath:");
      }
      if (StartsWith(arg, "-Xbootclasspath-locations:")) {
          bcp_location_str = arg + strlen("-Xbootclasspath-locations:");
      }
    }

    if (bcp_str.has_value() && bcp_location_str.has_value()) {
      Split(*bcp_str, ':', &boot_class_path_);
      Split(*bcp_location_str, ':', &boot_class_path_locations_);
    } else if (bcp_str.has_value()) {
      Split(*bcp_str, ':', &boot_class_path_);
      boot_class_path_locations_ = boot_class_path_;
    } else {
      // Try the default.
      const char* env_value = getenv("BOOTCLASSPATH");
      if (env_value != nullptr && strlen(env_value) > 0) {
          Split(env_value, ':', &boot_class_path_);
          boot_class_path_locations_ = boot_class_path_;
          is_default_boot_class_path_ = true;
      }
    }
  }

  // Infers the boot image on a best-effort basis.
  // The inference logic aligns with installd/artd + dex2oat.
  void InferBootImage() {
    // The boot image inference only makes sense on device.
    if (!kIsTargetAndroid) {
      return;
    }

    // The inferred boot image can only be used with the default bootclasspath.
    if (boot_class_path_.empty() || !is_default_boot_class_path_) {
      return;
    }

    std::string error_msg;
    std::string boot_image = GetBootImageLocationForDefaultBcpRespectingSysProps(&error_msg);
    if (boot_image.empty()) {
      LOG(WARNING) << "Failed to infer boot image: " << error_msg;
      return;
    }

    LOG(INFO) << "Inferred boot image: " << boot_image;
    Split(boot_image, ':', &boot_image_locations_);

    // Verify the inferred boot image.
    std::unique_ptr<OatFileAssistantContext> ofa_context = GetOatFileAssistantContext(&error_msg);
    CHECK_NE(ofa_context, nullptr);
    size_t verified_boot_image_count = ofa_context->GetBootImageInfoList(instruction_set_).size();
    if (verified_boot_image_count != boot_image_locations_.size()) {
      LOG(WARNING) << "Failed to verify inferred boot image";
      boot_image_locations_.resize(verified_boot_image_count);
    }
  }
};

template <typename Args = CmdlineArgs>
struct CmdlineMain {
  int Main(int argc, char** argv) {
    Locks::Init();
    InitLogging(argv, Runtime::Abort);
    std::unique_ptr<Args> args = std::unique_ptr<Args>(CreateArguments());
    args_ = args.get();

    DBG_LOG << "Try to parse";

    if (args_ == nullptr || !args_->Parse(argc, argv)) {
      return EXIT_FAILURE;
    }

    bool needs_runtime = NeedsRuntime();
    std::unique_ptr<Runtime> runtime;


    if (needs_runtime) {
      std::string error_msg;
      if (!args_->ParseCheckBootImage(&error_msg)) {
        fprintf(stderr, "%s\n", error_msg.c_str());
        args_->PrintUsage();
        return EXIT_FAILURE;
      }
      runtime.reset(CreateRuntime(args.get()));
      if (runtime == nullptr) {
        return EXIT_FAILURE;
      }
      if (!ExecuteWithRuntime(runtime.get())) {
        return EXIT_FAILURE;
      }
    } else {
      if (!ExecuteWithoutRuntime()) {
        return EXIT_FAILURE;
      }
    }

    if (!ExecuteCommon()) {
      return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
  }

  // Override this function to create your own arguments.
  // Usually will want to return a subtype of CmdlineArgs.
  virtual Args* CreateArguments() {
    return new Args();
  }

  // Override this function to do something else with the runtime.
  virtual bool ExecuteWithRuntime(Runtime* runtime) {
    CHECK(runtime != nullptr);
    // Do nothing
    return true;
  }

  // Does the code execution need a runtime? Sometimes it doesn't.
  virtual bool NeedsRuntime() {
    return true;
  }

  // Do execution without having created a runtime.
  virtual bool ExecuteWithoutRuntime() {
    return true;
  }

  // Continue execution after ExecuteWith[out]Runtime
  virtual bool ExecuteCommon() {
    return true;
  }

  virtual ~CmdlineMain() {}

 protected:
  Args* args_ = nullptr;

 private:
  Runtime* CreateRuntime(CmdlineArgs* args) {
    CHECK(args != nullptr);

    return StartRuntime(args->boot_image_locations_, args->instruction_set_, args_->runtime_args_);
  }
};
}  // namespace art

#endif  // ART_CMDLINE_CMDLINE_H_
