// Copyright 2018 The Chromium 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 "components/autofill_assistant/browser/script_precondition.h"

#include <utility>

#include "base/bind.h"
#include "base/strings/strcat.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/autofill_assistant/browser/batch_element_checker.h"
#include "components/autofill_assistant/browser/service.pb.h"
#include "third_party/re2/src/re2/re2.h"
#include "url/gurl.h"

namespace autofill_assistant {
// Static
std::unique_ptr<ScriptPrecondition> ScriptPrecondition::FromProto(
    const std::string& script_path,
    const ScriptPreconditionProto& script_precondition_proto) {
  std::vector<Selector> elements_exist;
  for (const auto& element : script_precondition_proto.elements_exist()) {
    // TODO(crbug.com/806868): Check if we shouldn't skip the script when this
    // happens.
    if (element.selectors_size() == 0) {
      DLOG(WARNING)
          << "Empty selectors in script precondition for script path: "
          << script_path << ".";
      continue;
    }

    Selector a_selector;
    for (const auto& selector : element.selectors()) {
      a_selector.selectors.emplace_back(selector);
    }
    elements_exist.emplace_back(std::move(a_selector));
  }

  std::set<std::string> domain_match;
  for (const auto& domain : script_precondition_proto.domain()) {
    domain_match.emplace(domain);
  }

  std::vector<std::unique_ptr<re2::RE2>> path_pattern;
  for (const auto& pattern : script_precondition_proto.path_pattern()) {
    auto re = std::make_unique<re2::RE2>(pattern);
    if (re->error_code() != re2::RE2::NoError) {
      DLOG(ERROR) << "Invalid regexp in script precondition '" << pattern
                  << "' for script path: " << script_path << ".";
      return nullptr;
    }
    path_pattern.emplace_back(std::move(re));
  }

  std::vector<ScriptParameterMatchProto> parameter_match;
  for (const auto& match : script_precondition_proto.script_parameter_match()) {
    parameter_match.emplace_back(match);
  }

  std::vector<FormValueMatchProto> form_value_match;
  for (const auto& match : script_precondition_proto.form_value_match()) {
    form_value_match.emplace_back(match);
  }

  std::vector<ScriptStatusMatchProto> status_matches;
  for (const auto& status_match :
       script_precondition_proto.script_status_match()) {
    status_matches.push_back(status_match);
  }

  // TODO(crbug.com/806868): Detect unknown or unsupported conditions and
  // reject them.
  return std::make_unique<ScriptPrecondition>(
      elements_exist, domain_match, std::move(path_pattern), parameter_match,
      form_value_match, status_matches);
}

ScriptPrecondition::~ScriptPrecondition() {}

void ScriptPrecondition::Check(
    const GURL& url,
    BatchElementChecker* batch_checks,
    const std::map<std::string, std::string>& parameters,
    const std::map<std::string, ScriptStatusProto>& executed_scripts,
    base::OnceCallback<void(bool)> callback) {
  if (!MatchDomain(url) || !MatchPath(url) || !MatchParameters(parameters) ||
      !MatchScriptStatus(executed_scripts)) {
    std::move(callback).Run(false);
    return;
  }

  pending_check_count_ = elements_exist_.size() + form_value_match_.size();
  if (pending_check_count_ == 0) {
    std::move(callback).Run(true);
    return;
  }

  check_preconditions_callback_ = std::move(callback);
  for (const auto& selector : elements_exist_) {
    base::OnceCallback<void(bool)> callback =
        base::BindOnce(&ScriptPrecondition::OnCheckElementExists,
                       weak_ptr_factory_.GetWeakPtr());
    batch_checks->AddElementCheck(kExistenceCheck, selector,
                                  std::move(callback));
  }
  for (const auto& value_match : form_value_match_) {
    DCHECK(!value_match.element().selectors().empty());
    Selector a_selector;
    for (const auto& selector : value_match.element().selectors()) {
      a_selector.selectors.emplace_back(selector);
    }

    batch_checks->AddFieldValueCheck(
        a_selector, base::BindOnce(&ScriptPrecondition::OnGetFieldValue,
                                   weak_ptr_factory_.GetWeakPtr()));
  }
}

ScriptPrecondition::ScriptPrecondition(
    const std::vector<Selector>& elements_exist,
    const std::set<std::string>& domain_match,
    std::vector<std::unique_ptr<re2::RE2>> path_pattern,
    const std::vector<ScriptParameterMatchProto>& parameter_match,
    const std::vector<FormValueMatchProto>& form_value_match,
    const std::vector<ScriptStatusMatchProto>& status_match)
    : elements_exist_(elements_exist),
      domain_match_(domain_match),
      path_pattern_(std::move(path_pattern)),
      parameter_match_(parameter_match),
      form_value_match_(form_value_match),
      status_match_(status_match),
      pending_check_count_(0),
      weak_ptr_factory_(this) {}

bool ScriptPrecondition::MatchDomain(const GURL& url) const {
  if (domain_match_.empty())
    return true;

  // We require the scheme and host parts to match.
  // TODO(crbug.com/806868): Consider using Origin::IsSameOriginWith here.
  std::string scheme_domain = base::StrCat({url.scheme(), "://", url.host()});
  return domain_match_.find(scheme_domain) != domain_match_.end();
}

bool ScriptPrecondition::MatchPath(const GURL& url) const {
  if (path_pattern_.empty()) {
    return true;
  }

  std::string path = url.has_ref()
                         ? base::StrCat({url.PathForRequest(), "#", url.ref()})
                         : url.PathForRequest();
  for (auto& regexp : path_pattern_) {
    if (regexp->Match(path, 0, path.size(), re2::RE2::UNANCHORED, NULL, 0)) {
      return true;
    }
  }
  return false;
}

bool ScriptPrecondition::MatchParameters(
    const std::map<std::string, std::string>& parameters) const {
  for (const auto& match : parameter_match_) {
    auto iter = parameters.find(match.name());
    if (match.exists()) {
      // parameter must exist and optionally have a specific value
      if (iter == parameters.end())
        return false;

      if (!match.value_equals().empty() && iter->second != match.value_equals())
        return false;

    } else {
      // parameter must not exist
      if (iter != parameters.end())
        return false;
    }
  }
  return true;
}

bool ScriptPrecondition::MatchScriptStatus(
    const std::map<std::string, ScriptStatusProto>& executed_scripts) const {
  for (const auto status_match : status_match_) {
    auto status = SCRIPT_STATUS_NOT_RUN;
    auto iter = executed_scripts.find(status_match.script());
    if (iter != executed_scripts.end()) {
      status = iter->second;
    }
    bool has_same_status = status_match.status() == status;
    switch (status_match.comparator()) {
      case ScriptStatusMatchProto::DIFFERENT:
        if (has_same_status)
          return false;
        break;
      case ScriptStatusMatchProto::EQUAL:
      default:
        if (!has_same_status)
          return false;
        break;
    }
  }
  return true;
}

void ScriptPrecondition::OnCheckElementExists(bool exists) {
  ReportCheckResult(exists);
}

void ScriptPrecondition::OnGetFieldValue(bool exists,
                                         const std::string& value) {
  ReportCheckResult(!value.empty());
}

void ScriptPrecondition::ReportCheckResult(bool success) {
  if (!check_preconditions_callback_)
    return;

  if (!success) {
    std::move(check_preconditions_callback_).Run(false);
    return;
  }

  --pending_check_count_;
  if (pending_check_count_ <= 0) {
    DCHECK_EQ(pending_check_count_, 0);
    std::move(check_preconditions_callback_).Run(true);
  }
}

}  // namespace autofill_assistant
