// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "base/memory/raw_ptr.h"

#include <string>
#include <utility>

#include "base/files/file_path.h"
#include "base/json/json_reader.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
#include "chrome/browser/extensions/browser_extension_window_controller.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "components/crx_file/id_util.h"
#include "extensions/browser/api_test_utils.h"
#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_function_dispatcher.h"
#include "extensions/common/extension.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

using content::WebContents;
using extensions::Extension;
using extensions::Manifest;
namespace keys = extensions::tabs_constants;

namespace {

class TestFunctionDispatcherDelegate
    : public extensions::ExtensionFunctionDispatcher::Delegate {
 public:
  explicit TestFunctionDispatcherDelegate(Browser* browser) :
      browser_(browser) {}
  ~TestFunctionDispatcherDelegate() override {}

 private:
  extensions::WindowController* GetExtensionWindowController() const override {
    return browser_->extension_window_controller();
  }

  WebContents* GetAssociatedWebContents() const override { return nullptr; }

  raw_ptr<Browser> browser_;
};

}  // namespace

namespace extension_function_test_utils {

absl::optional<base::Value> ParseList(const std::string& data) {
  absl::optional<base::Value> result = base::JSONReader::Read(data);
  if (!result) {
    ADD_FAILURE() << "Failed to parse: " << data;
    return absl::nullopt;
  }
  if (!result->is_list())
    return absl::nullopt;
  return result;
}

base::Value::Dict ToDictionary(std::unique_ptr<base::Value> val) {
  if (!val || !val->is_dict()) {
    ADD_FAILURE() << "val is nullptr or is not a dictonary.";
    return base::Value::Dict();
  }
  return std::move(*val).TakeDict();
}

base::Value::Dict ToDictionary(const base::Value& val) {
  EXPECT_TRUE(val.is_dict());
  if (!val.is_dict())
    return base::Value::Dict();
  return val.GetDict().Clone();
}

base::Value::List ToList(std::unique_ptr<base::Value> val) {
  if (!val || !val->is_list()) {
    ADD_FAILURE() << "val is nullptr or is not a list.";
    return base::Value::List();
  }
  return std::move(*val).TakeList();
}

bool HasAnyPrivacySensitiveFields(const base::Value::Dict& dict) {
  constexpr std::array privacySensitiveKeys{keys::kUrlKey, keys::kTitleKey,
                                            keys::kFaviconUrlKey,
                                            keys::kPendingUrlKey};
  for (auto* key : privacySensitiveKeys) {
    if (dict.contains(key))
      return true;
  }
  return false;
}

std::string RunFunctionAndReturnError(ExtensionFunction* function,
                                      const std::string& args,
                                      Browser* browser) {
  return RunFunctionAndReturnError(function, args, browser,
                                   extensions::api_test_utils::NONE);
}
std::string RunFunctionAndReturnError(
    ExtensionFunction* function,
    const std::string& args,
    Browser* browser,
    extensions::api_test_utils::RunFunctionFlags flags) {
  scoped_refptr<ExtensionFunction> function_owner(function);
  RunFunction(function, args, browser, flags);
  // When sending a response, the function will set an empty list value if there
  // is no specified result.
  const base::Value::List* results = function->GetResultList();
  CHECK(results);
  EXPECT_TRUE(results->empty()) << "Did not expect a result";
  CHECK(function->response_type());
  EXPECT_EQ(ExtensionFunction::FAILED, *function->response_type());
  return function->GetError();
}

std::unique_ptr<base::Value> RunFunctionAndReturnSingleResult(
    ExtensionFunction* function,
    const std::string& args,
    Browser* browser) {
  return RunFunctionAndReturnSingleResult(function, args, browser,
                                          extensions::api_test_utils::NONE);
}

std::unique_ptr<base::Value> RunFunctionAndReturnSingleResult(
    ExtensionFunction* function,
    const std::string& args,
    Browser* browser,
    extensions::api_test_utils::RunFunctionFlags flags) {
  scoped_refptr<ExtensionFunction> function_owner(function);
  function->preserve_results_for_testing();
  RunFunction(function, args, browser, flags);
  EXPECT_TRUE(function->GetError().empty()) << "Unexpected error: "
      << function->GetError();
  if (function->GetResultList() && !function->GetResultList()->empty()) {
    return base::Value::ToUniquePtrValue(
        (*function->GetResultList())[0].Clone());
  }
  return nullptr;
}

bool RunFunction(ExtensionFunction* function,
                 const std::string& args,
                 Browser* browser,
                 extensions::api_test_utils::RunFunctionFlags flags) {
  absl::optional<base::Value> maybe_parsed_args(ParseList(args));
  EXPECT_TRUE(maybe_parsed_args)
      << "Could not parse extension function arguments: " << args;
  std::unique_ptr<base::ListValue> parsed_args(base::ListValue::From(
      base::Value::ToUniquePtrValue(std::move(*maybe_parsed_args))));

  return RunFunction(function, std::move(parsed_args), browser, flags);
}

bool RunFunction(ExtensionFunction* function,
                 std::unique_ptr<base::ListValue> args,
                 Browser* browser,
                 extensions::api_test_utils::RunFunctionFlags flags) {
  TestFunctionDispatcherDelegate dispatcher_delegate(browser);
  std::unique_ptr<extensions::ExtensionFunctionDispatcher> dispatcher(
      new extensions::ExtensionFunctionDispatcher(browser->profile()));
  dispatcher->set_delegate(&dispatcher_delegate);
  return extensions::api_test_utils::RunFunction(function, std::move(args),
                                                 std::move(dispatcher), flags);
}

} // namespace extension_function_test_utils
