// Copyright 2019 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/lib/line_input/modal_line_input.h"

#include <lib/syslog/cpp/macros.h>

#include <locale>

namespace line_input {

namespace {

// State associated with running a modal options prompt.
class ModalOptionState {
 public:
  ModalOptionState(ModalLineInput* input, ModalPromptOptions opts,
                   ModalLineInput::ModalCompletionCallback cb)
      : input_(input), options_(std::move(opts)), on_complete_(std::move(cb)) {}

  void OnAccept(const std::string& line) { CheckAccept(line, true); }

  void OnChanged(const std::string& line) {
    if (options_.require_enter)
      return;  // Nothing to do.

    if (CheckAccept(line, false)) {
      // When the user has typed valid input and we don't require enter, synthesize an enter to
      // invoke the normal accept codepath. We could close the input now, but skipping tne
      // enter will erase the current line in normal console mode.
      //
      // This will cause OnAccept() above to be called which will then signal completion.
      input_->OnInput('\r');
    }
  }

  void OnCancel() {
    if (!options_.cancel_option.empty()) {
      input_->EndModal();
      on_complete_(options_.cancel_option);
    }
  }

 private:
  // Checks whether the current line is a valid option. On success, returns true and optionally
  // signals completion (which closes the modal prompt).
  bool CheckAccept(const std::string& line, bool signal_complete) {
    // Optionally check case-insensitively.
    std::string to_check(line);
    if (!options_.case_sensitive) {
      for (size_t i = 0; i < to_check.size(); i++)
        to_check[i] = std::tolower(to_check[i]);
    }

    for (const auto& opt : options_.options) {
      if (to_check == opt) {
        if (signal_complete) {
          input_->EndModal();
          on_complete_(to_check);
        }
        return true;
      }
    }

    return false;
  }

  ModalLineInput* input_;  // Non-owning (it owns us).
  ModalPromptOptions options_;
  ModalLineInput::ModalCompletionCallback on_complete_;
};

}  // namespace

ModalLineInput::ModalLineInput(Factory factory) : factory_(std::move(factory)) {
  if (!factory_) {
    // Make a "stdout" line input factory when not explicitly specified.
    factory_ = [](AcceptCallback accept_cb, const std::string& prompt) {
      return std::make_unique<LineInputStdout>(std::move(accept_cb), prompt);
    };
  }
}

void ModalLineInput::Init(AcceptCallback accept_cb, const std::string& prompt) {
  FX_DCHECK(!normal_input_) << "Calling Init() twice.";

  normal_input_ = MakeAndSetupLineInput(std::move(accept_cb), prompt);
  current_input_ = normal_input_.get();
}

void ModalLineInput::SetAutocompleteCallback(AutocompleteCallback cb) {
  FX_DCHECK(normal_input_) << "Need to call Init() first.";
  // Autocomplete only works for the non-modal input.
  normal_input_->SetAutocompleteCallback(std::move(cb));
}

void ModalLineInput::SetChangeCallback(ChangeCallback cb) {
  // Change callbacks only go to the non-modal input. Our model interface handles changes on the
  // modal one.
  normal_input_->SetChangeCallback(std::move(cb));
}

void ModalLineInput::SetCancelCallback(CancelCallback cb) {
  // The cancel callback goes only to the regular input. Modal prompts have special handling.
  normal_input_->SetCancelCallback(std::move(cb));
}

void ModalLineInput::SetEofCallback(EofCallback cb) { eof_callback_ = std::move(cb); }

void ModalLineInput::SetMaxCols(size_t max) {
  FX_DCHECK(normal_input_) << "Need to call Init() first.";

  max_cols_ = max;
  normal_input_->SetMaxCols(max);
  if (modal_input_)
    modal_input_->SetMaxCols(max);
}

const std::string& ModalLineInput::GetLine() const { return current_input_->GetLine(); }

const std::deque<std::string>& ModalLineInput::GetHistory() const {
  // History always comes from the regular one. The modal input has no history.
  FX_DCHECK(normal_input_) << "Need to call Init() first.";
  return normal_input_->GetHistory();
}

void ModalLineInput::OnInput(char c) {
  if (to_delete_)
    to_delete_.reset();
  current_input_->OnInput(c);
}

void ModalLineInput::AddToHistory(const std::string& line) {
  // History always goes to the normal input.
  normal_input_->AddToHistory(line);
}

void ModalLineInput::Hide(InterruptHandlingBehavior behavior) {
  hidden_ = true;
  current_input_->Hide(behavior);
}

void ModalLineInput::Show() {
  hidden_ = false;
  current_input_->Show();
}

void ModalLineInput::SetCurrentInput(const std::string& input) {
  current_input_->SetCurrentInput(input);
}

void ModalLineInput::ModalGetOption(const ModalPromptOptions& options, const std::string& prompt,
                                    ModalCompletionCallback cb, WillShowModalCallback will_show) {
  auto state = std::make_shared<ModalOptionState>(this, options, std::move(cb));

  // This will show callback registers our changed callback on the new modal input class and
  // calls the user will_show callback if provided. |this| can be captured here because this
  // owns the callback.
  auto do_will_show = [this, state, will_show = std::move(will_show)]() mutable {
    modal_input_->SetChangeCallback([state](const std::string& line) { state->OnChanged(line); });
    modal_input_->SetCancelCallback([state]() { state->OnCancel(); });
    if (will_show)
      will_show();
  };

  BeginModal(
      prompt, [state](const std::string& line) { state->OnAccept(line); }, std::move(do_will_show));
}

void ModalLineInput::BeginModal(const std::string& prompt, ModalCompletionCallback cb,
                                WillShowModalCallback will_show) {
  auto& record = modal_callbacks_.emplace_back();
  record.prompt = prompt;
  record.complete = std::move(cb);
  record.will_show = std::move(will_show);

  if (!modal_input_) {
    // Not showing a modal input already, switch to it.
    if (!hidden_)
      normal_input_->Hide();
    ShowNextModal();
  }
  // Otherwise we're already showing a modal input. This new one will be automatically shown in
  // time.
}

void ModalLineInput::EndModal() {
  FX_DCHECK(modal_input_) << "Not in a modal input.";
  FX_DCHECK(!modal_callbacks_.empty());

  modal_callbacks_.pop_front();

  if (!hidden_)
    modal_input_->Hide();

  // Schedule the modal input to be deleted in next OnInput() call to prevent reentrancy.
  FX_DCHECK(!to_delete_);
  to_delete_ = std::move(modal_input_);

  current_input_ = normal_input_.get();

  if (modal_callbacks_.empty()) {
    // Go back to normal mode.
    if (!hidden_)
      normal_input_->Show();
  } else {
    ShowNextModal();
  }
}

void ModalLineInput::ShowNextModal() {
  FX_DCHECK(!modal_callbacks_.empty());
  FX_DCHECK(!modal_input_);

  auto& record = modal_callbacks_.front();

  modal_input_ = MakeAndSetupLineInput(std::move(record.complete), record.prompt);
  current_input_ = modal_input_.get();

  if (record.will_show)
    record.will_show();

  if (!hidden_)
    current_input_->Show();
}

std::unique_ptr<LineInput> ModalLineInput::MakeAndSetupLineInput(AcceptCallback accept_cb,
                                                                 const std::string& prompt) {
  auto input = factory_(std::move(accept_cb), prompt);

  if (max_cols_)
    input->SetMaxCols(max_cols_);

  input->SetEofCallback([this]() {
    if (eof_callback_)
      eof_callback_();
  });

  return input;
}

}  // namespace line_input
