// 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

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() {
  hidden_ = true;
  current_input_->Hide();
}

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

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 = MakeLineInput(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
