// 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_executor.h"

#include <string>
#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill_assistant/browser/batch_element_checker.h"
#include "components/autofill_assistant/browser/client_memory.h"
#include "components/autofill_assistant/browser/protocol_utils.h"
#include "components/autofill_assistant/browser/service.h"
#include "components/autofill_assistant/browser/ui_controller.h"
#include "components/autofill_assistant/browser/web_controller.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"

namespace autofill_assistant {
namespace {

// Maximum amount of time normal actions should implicitly wait for a selector
// to show up.
constexpr base::TimeDelta kWaitForSelectorDeadline =
    base::TimeDelta::FromSeconds(2);
}  // namespace

ScriptExecutor::ScriptExecutor(const std::string& script_path,
                               const std::string& server_payload,
                               ScriptExecutor::Listener* listener,
                               ScriptExecutorDelegate* delegate)
    : script_path_(script_path),
      last_server_payload_(server_payload),
      listener_(listener),
      delegate_(delegate),
      at_end_(CONTINUE),
      should_stop_script_(false),
      should_clean_contextual_ui_on_finish_(false),
      previous_action_type_(ActionProto::ACTION_INFO_NOT_SET),
      weak_ptr_factory_(this) {
  DCHECK(delegate_);
}
ScriptExecutor::~ScriptExecutor() {}

ScriptExecutor::Result::Result() = default;
ScriptExecutor::Result::Result(const Result& other) = default;
ScriptExecutor::Result::~Result() = default;

void ScriptExecutor::Run(RunScriptCallback callback) {
  callback_ = std::move(callback);
  DCHECK(delegate_->GetService());

  delegate_->GetService()->GetActions(
      script_path_, delegate_->GetWebController()->GetUrl(),
      delegate_->GetParameters(), last_server_payload_,
      base::BindOnce(&ScriptExecutor::OnGetActions,
                     weak_ptr_factory_.GetWeakPtr()));
}

std::unique_ptr<BatchElementChecker>
ScriptExecutor::CreateBatchElementChecker() {
  return delegate_->GetWebController()->CreateBatchElementChecker();
}

void ScriptExecutor::WaitForElement(const std::vector<std::string>& selectors,
                                    base::OnceCallback<void(bool)> callback) {
  std::unique_ptr<BatchElementChecker> checker = CreateBatchElementChecker();
  checker->AddElementCheck(kVisibilityCheck, selectors, base::DoNothing());
  checker->Run(kWaitForSelectorDeadline,
               /* try_done= */ base::DoNothing(),
               /* all_done= */
               base::BindOnce(
                   [](std::unique_ptr<BatchElementChecker> checker_to_delete,
                      base::OnceCallback<void(bool)> callback) {
                     std::move(callback).Run(checker_to_delete->all_found());
                   },
                   std::move(checker), std::move(callback)));
}

void ScriptExecutor::ShowStatusMessage(const std::string& message) {
  delegate_->GetUiController()->ShowStatusMessage(message);
}

void ScriptExecutor::ClickOrTapElement(
    const std::vector<std::string>& selectors,
    base::OnceCallback<void(bool)> callback) {
  delegate_->GetWebController()->ClickOrTapElement(selectors,
                                                   std::move(callback));
}

void ScriptExecutor::GetPaymentInformation(
    payments::mojom::PaymentOptionsPtr payment_options,
    base::OnceCallback<void(std::unique_ptr<PaymentInformation>)> callback,
    const std::string& title,
    const std::vector<std::string>& supported_basic_card_networks) {
  delegate_->GetUiController()->GetPaymentInformation(
      std::move(payment_options), std::move(callback), title,
      supported_basic_card_networks);
}

void ScriptExecutor::ChooseAddress(
    base::OnceCallback<void(const std::string&)> callback) {
  delegate_->GetUiController()->ChooseAddress(std::move(callback));
}

void ScriptExecutor::FillAddressForm(const autofill::AutofillProfile* profile,
                                     const std::vector<std::string>& selectors,
                                     base::OnceCallback<void(bool)> callback) {
  delegate_->GetWebController()->FillAddressForm(profile, selectors,
                                                 std::move(callback));
}

void ScriptExecutor::ChooseCard(
    base::OnceCallback<void(const std::string&)> callback) {
  delegate_->GetUiController()->ChooseCard(std::move(callback));
}

void ScriptExecutor::FillCardForm(std::unique_ptr<autofill::CreditCard> card,
                                  const base::string16& cvc,
                                  const std::vector<std::string>& selectors,
                                  base::OnceCallback<void(bool)> callback) {
  delegate_->GetWebController()->FillCardForm(std::move(card), cvc, selectors,
                                              std::move(callback));
}

void ScriptExecutor::SelectOption(const std::vector<std::string>& selectors,
                                  const std::string& selected_option,
                                  base::OnceCallback<void(bool)> callback) {
  delegate_->GetWebController()->SelectOption(selectors, selected_option,
                                              std::move(callback));
}

void ScriptExecutor::HighlightElement(const std::vector<std::string>& selectors,
                                      base::OnceCallback<void(bool)> callback) {
  delegate_->GetWebController()->HighlightElement(selectors,
                                                  std::move(callback));
}

void ScriptExecutor::FocusElement(const std::vector<std::string>& selectors,
                                  base::OnceCallback<void(bool)> callback) {
  delegate_->GetWebController()->FocusElement(selectors, std::move(callback));
}

void ScriptExecutor::SetTouchableElements(
    const std::vector<std::vector<std::string>>& element_selectors) {
  touchable_elements_ = element_selectors;
}

void ScriptExecutor::ShowProgressBar(int progress, const std::string& message) {
  delegate_->GetUiController()->ShowProgressBar(progress, message);
}

void ScriptExecutor::HideProgressBar() {
  delegate_->GetUiController()->HideProgressBar();
}

void ScriptExecutor::ShowOverlay() {
  delegate_->GetUiController()->ShowOverlay();
}

void ScriptExecutor::HideOverlay() {
  delegate_->GetUiController()->HideOverlay();
}

void ScriptExecutor::SetFieldValue(const std::vector<std::string>& selectors,
                                   const std::string& value,
                                   bool simulate_key_presses,
                                   base::OnceCallback<void(bool)> callback) {
  delegate_->GetWebController()->SetFieldValue(
      selectors, value, simulate_key_presses, std::move(callback));
}

void ScriptExecutor::SetAttribute(const std::vector<std::string>& selectors,
                                  const std::vector<std::string>& attribute,
                                  const std::string& value,
                                  base::OnceCallback<void(bool)> callback) {
  delegate_->GetWebController()->SetAttribute(selectors, attribute, value,
                                              std::move(callback));
}

void ScriptExecutor::GetOuterHtml(
    const std::vector<std::string>& selectors,
    base::OnceCallback<void(bool, const std::string&)> callback) {
  delegate_->GetWebController()->GetOuterHtml(selectors, std::move(callback));
}

void ScriptExecutor::LoadURL(const GURL& url) {
  delegate_->GetWebController()->LoadURL(url);
}

void ScriptExecutor::Shutdown() {
  // The following handles the case where scripts end with tell + stop
  // differently from just stop. TODO(b/806868): Make that difference explicit:
  // add an optional message to stop and update the scripts to use that.
  if (previous_action_type_ == ActionProto::kTell) {
    at_end_ = SHUTDOWN_GRACEFULLY;
  } else {
    at_end_ = SHUTDOWN;
  }
}

void ScriptExecutor::Restart() {
  at_end_ = RESTART;
}

void ScriptExecutor::StopCurrentScriptAndShutdown(const std::string& message) {
  // Use a default message when |message| is empty.
  delegate_->GetUiController()->ShowStatusMessage(
      message.empty() ? l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_GIVE_UP)
                      : message);
  at_end_ = SHUTDOWN_GRACEFULLY;
  should_stop_script_ = true;
}

ClientMemory* ScriptExecutor::GetClientMemory() {
  return delegate_->GetClientMemory();
}

autofill::PersonalDataManager* ScriptExecutor::GetPersonalDataManager() {
  return delegate_->GetPersonalDataManager();
}

content::WebContents* ScriptExecutor::GetWebContents() {
  return delegate_->GetWebContents();
}

void ScriptExecutor::HideDetails() {
  delegate_->GetUiController()->HideDetails();
}

bool ScriptExecutor::ShowDetails(const DetailsProto& details) {
  return delegate_->GetUiController()->ShowDetails(details);
}

void ScriptExecutor::OnGetActions(bool result, const std::string& response) {
  if (!result) {
    RunCallback(false);
    return;
  }
  processed_actions_.clear();
  actions_.clear();

  bool parse_result =
      ProtocolUtils::ParseActions(response, &last_server_payload_, &actions_);
  if (listener_) {
    listener_->OnServerPayloadChanged(last_server_payload_);
  }
  if (!parse_result) {
    RunCallback(false);
    return;
  }

  if (actions_.empty()) {
    // Finished executing the script if there are no more actions.
    RunCallback(true);
    return;
  }

  ProcessNextAction();
}

void ScriptExecutor::RunCallback(bool success) {
  DCHECK(callback_);
  if (should_clean_contextual_ui_on_finish_ || !success) {
    HideDetails();
    should_clean_contextual_ui_on_finish_ = false;
  }

  ScriptExecutor::Result result;
  result.success = success;
  result.at_end = at_end_;
  result.touchable_elements = touchable_elements_;
  std::move(callback_).Run(result);
}

void ScriptExecutor::ProcessNextAction() {
  // We could get into a strange situation if ProcessNextAction is called before
  // the action was reported as processed, which should not happen. In that case
  // we could have more |processed_actions| than |actions_|.
  if (actions_.size() <= processed_actions_.size()) {
    DCHECK_EQ(actions_.size(), processed_actions_.size());
    // Request more actions to execute.
    GetNextActions();
    return;
  }

  Action* action = actions_[processed_actions_.size()].get();
  should_clean_contextual_ui_on_finish_ = action->proto().clean_contextual_ui();
  int delay_ms = action->proto().action_delay_ms();
  if (delay_ms > 0) {
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&ScriptExecutor::ProcessAction,
                       weak_ptr_factory_.GetWeakPtr(), action),
        base::TimeDelta::FromMilliseconds(delay_ms));
  } else {
    ProcessAction(action);
  }
}

void ScriptExecutor::ProcessAction(Action* action) {
  action->ProcessAction(this, base::BindOnce(&ScriptExecutor::OnProcessedAction,
                                             weak_ptr_factory_.GetWeakPtr()));
}

void ScriptExecutor::GetNextActions() {
  delegate_->GetService()->GetNextActions(
      last_server_payload_, processed_actions_,
      base::BindOnce(&ScriptExecutor::OnGetActions,
                     weak_ptr_factory_.GetWeakPtr()));
}

void ScriptExecutor::OnProcessedAction(
    std::unique_ptr<ProcessedActionProto> processed_action_proto) {
  previous_action_type_ = processed_action_proto->action().action_info_case();
  processed_actions_.emplace_back(*processed_action_proto);
  if (processed_actions_.back().status() !=
      ProcessedActionStatusProto::ACTION_APPLIED) {
    // Report error immediately, interrupting action processing.
    GetNextActions();
    return;
  }

  if (should_stop_script_) {
    // Last action called StopCurrentScript(). We simulate a successful end of
    // script to make sure we don't display any errors.
    RunCallback(true);
    return;
  }

  ProcessNextAction();
}

}  // namespace autofill_assistant
