// 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 "garnet/bin/run_test_component/run_test_component.h"

#include <fuchsia/sys/index/cpp/fidl.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 <regex>
#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 {

using fuchsia::sys::index::ComponentIndex_FuzzySearch_Result;
using fuchsia::sys::index::ComponentIndexSyncPtr;

static constexpr char kComponentIndexerUrl[] =
    "fuchsia-pkg://fuchsia.com/component_index#meta/component_index.cmx";

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;
  }

  if (!component::FuchsiaPkgUrl::IsFuchsiaPkgScheme(url)) {
    fuchsia::sys::LaunchInfo index_launch_info;
    index_launch_info.url = kComponentIndexerUrl;
    auto index_provider =
        sys::ServiceDirectory::CreateWithRequest(&index_launch_info.directory_request);

    // Connect to the Launcher service through our static environment.
    fuchsia::sys::LauncherSyncPtr launcher;
    services->Connect(launcher.NewRequest());
    fuchsia::sys::ComponentControllerPtr component_index_controller;
    launcher->CreateComponent(std::move(index_launch_info),
                              component_index_controller.NewRequest());

    ComponentIndexSyncPtr index;
    index_provider->Connect(index.NewRequest());

    std::string test_name = url;
    ComponentIndex_FuzzySearch_Result fuzzy_search_result;
    zx_status_t status = index->FuzzySearch(test_name, &fuzzy_search_result);
    if (status != ZX_OK) {
      result.error = true;
      result.error_msg = fxl::StringPrintf(
          "\"%s\" is not a valid URL. Attempted to match to a URL with "
          "fuchsia.sys.index.FuzzySearch, but the service is not available.",
          test_name.c_str());
      return result;
    }

    if (fuzzy_search_result.is_err()) {
      result.error = true;
      result.error_msg = fxl::StringPrintf(
          "\"%s\" contains unsupported characters for fuzzy "
          "matching. Valid characters are [A-Z a-z 0-9 / _ - .].\n",
          test_name.c_str());
      return result;
    }
    std::vector<std::string> uris = fuzzy_search_result.response().uris;
    if (uris.empty()) {
      result.error = true;
      result.error_msg =
          fxl::StringPrintf("\"%s\" did not match any components.\n", test_name.c_str());
      return result;
    }
    for (auto& uri : uris) {
      result.matching_urls.push_back(uri);
    }
    if (uris.size() > 1) {
      return result;
    }
    url = uris[0];
  }

  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
