// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/sys/run_test_component/run_test_component.h"

#include <glob.h>
#include <lib/fit/defer.h>
#include <lib/fitx/result.h>
#include <lib/sys/cpp/service_directory.h>
#include <limits.h>

#include <sstream>
#include <string>

#include "src/lib/fxl/strings/string_printf.h"
#include "src/lib/fxl/strings/substitute.h"
#include "src/lib/pkg_url/fuchsia_pkg_url.h"

namespace run {

static constexpr char kLabelArgPrefix[] = "--realm-label=";
static constexpr char kTimeoutArgPrefix[] = "--timeout=";
static constexpr char kSeverityArgPrefix[] = "--min-severity-logs=";
static constexpr char kMaxSeverityArgPrefix[] = "--max-log-severity=";

bool to_bool(std::string str) {
  std::transform(str.begin(), str.end(), str.begin(), ::tolower);
  std::istringstream is(str);
  bool b;
  is >> std::boolalpha >> b;
  return b;
}

fitx::result<bool, uint32_t> ParseLogLevel(const std::string& level) {
  if (level == "TRACE") {
    return fitx::success(syslog::LOG_TRACE);
  }
  if (level == "DEBUG") {
    return fitx::success(syslog::LOG_DEBUG);
  }
  if (level == "INFO") {
    return fitx::success(syslog::LOG_INFO);
  }
  if (level == "WARN") {
    return fitx::success(syslog::LOG_WARNING);
  }
  if (level == "ERROR") {
    return fitx::success(syslog::LOG_ERROR);
  }
  if (level == "FATAL") {
    return fitx::success(syslog::LOG_FATAL);
  }
  return fitx::error(false);
}

ParseArgsResult ParseArgs(const std::shared_ptr<sys::ServiceDirectory>& services, int argc,
                          const char** argv) {
  ParseArgsResult result;
  result.error = false;
  result.timeout = -1;
  int url_or_matcher_argi = 1;

  std::string url;
  while (true) {
    if (argc < url_or_matcher_argi + 1) {
      result.error = true;
      result.error_msg = "Missing test URL, or matcher argument";
      return result;
    }

    std::string argument = argv[url_or_matcher_argi];
    const size_t kLabelArgPrefixLength = strlen(kLabelArgPrefix);
    const size_t kTimeoutArgPrefixLength = strlen(kTimeoutArgPrefix);
    const size_t kSeverityArgPrefixLength = strlen(kSeverityArgPrefix);
    const size_t kMaxSeverityArgPrefixLength = strlen(kMaxSeverityArgPrefix);

    if (argument.substr(0, kLabelArgPrefixLength) == kLabelArgPrefix) {
      result.realm_label = argument.substr(kLabelArgPrefixLength);
      url_or_matcher_argi++;
      continue;
    }

    if (argument.substr(0, kSeverityArgPrefixLength) == kSeverityArgPrefix) {
      std::string level = argument.substr(kSeverityArgPrefixLength);
      auto level_result = ParseLogLevel(level);
      if (level_result.is_error()) {
        result.error = true;
        result.error_msg = fxl::StringPrintf("Invalid --min-severity-logs %s", level.c_str());
        return result;
      }
      result.min_log_severity = level_result.value();

      url_or_matcher_argi++;
      continue;
    }

    if (argument.substr(0, kMaxSeverityArgPrefixLength) == kMaxSeverityArgPrefix) {
      std::string level = argument.substr(kMaxSeverityArgPrefixLength);
      auto level_result = ParseLogLevel(level);
      if (level_result.is_error()) {
        result.error = true;
        result.error_msg = fxl::StringPrintf("Invalid --max-log-severity %s", level.c_str());
        return result;
      }
      result.max_log_severity = level_result.value();
      url_or_matcher_argi++;
      continue;
    }

    if (argument.substr(0, kTimeoutArgPrefixLength) == kTimeoutArgPrefix) {
      std::string arg = argument.substr(kTimeoutArgPrefixLength);
      std::istringstream stream(arg);
      stream >> result.timeout;
      if (stream.fail() || result.timeout <= 0) {
        result.error = true;
        result.error_msg = fxl::StringPrintf("\"%s\" is not a valid timeout.", arg.c_str());
        return result;
      }
      url_or_matcher_argi++;
      continue;
    }

    url = argument;
    break;
  }

  result.launch_info.url = url;
  result.launch_info.arguments.emplace();
  int i = url_or_matcher_argi + 1;
  if (i < argc && std::string(argv[i]) != "--") {
    printf(
        "WARNING: Please use Option delimiter(--) before specifying test args. Current commandline "
        "will error out in future. Use\n 'run-test-component [run-test-component-args] <test_url> "
        "-- [test_args]'\n");
  } else {
    i++;
  }
  for (; i < argc; i++) {
    result.launch_info.arguments->push_back(argv[i]);
  }
  return result;
}

std::string GetSimplifiedUrl(const std::string& url) {
  component::FuchsiaPkgUrl furl;
  furl.Parse(url);
  return fxl::Substitute("fuchsia-pkg://$0/$1#$2", furl.host_name(), furl.package_name(),
                         furl.resource_path());
}

}  // namespace run
