// 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/developer/debug/zxdb/console/console_impl.h"

#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef __Fuchsia__
#include <signal.h>
#include <termios.h>
#endif

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

#include <filesystem>

#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/system.h"
#include "src/developer/debug/zxdb/client/target.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/console/command.h"
#include "src/developer/debug/zxdb/console/command_parser.h"
#include "src/developer/debug/zxdb/console/output_buffer.h"
#include "src/lib/files/file.h"
#include "src/lib/fxl/strings/join_strings.h"
#include "src/lib/fxl/strings/split_string.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "src/lib/fxl/strings/trim.h"

namespace zxdb {

namespace {

const char* kHistoryFilename = ".zxdb_history";

#ifndef __Fuchsia__

termios stdout_saved_termios;
struct sigaction saved_abort;
struct sigaction saved_segv;

void TerminalRestoreSignalHandler(int sig, siginfo_t* info, void* ucontext) {
  struct sigaction _ignore;

  if (sig == SIGABRT) {
    sigaction(SIGABRT, &saved_abort, &_ignore);
  } else if (sig == SIGSEGV) {
    sigaction(SIGSEGV, &saved_segv, &_ignore);
  } else {
    // Weird, but I'm not about to assert inside a signal handler.
    return;
  }

  tcsetattr(STDOUT_FILENO, TCSAFLUSH, &stdout_saved_termios);
  raise(sig);
}

void PreserveStdoutTermios() {
  if (!isatty(STDOUT_FILENO))
    return;

  if (tcgetattr(STDOUT_FILENO, &stdout_saved_termios) < 0)
    return;

  struct sigaction restore_handler;

  restore_handler.sa_sigaction = TerminalRestoreSignalHandler;
  restore_handler.sa_flags = SA_SIGINFO;

  sigaction(SIGABRT, &restore_handler, &saved_abort);
  sigaction(SIGSEGV, &restore_handler, &saved_segv);
}

#else

void PreserveStdoutTermios() {}

#endif  // !__Fuchsia__

}  // namespace

ConsoleImpl::ConsoleImpl(Session* session) : Console(session), impl_weak_factory_(this) {
  line_input_.Init([this](const std::string& s) { ProcessInputLine(s); }, "[zxdb] ");

  // Set the line input completion callback that can know about our context. OK to bind |this| since
  // we own the line_input object.
  FillCommandContextCallback fill_command_context([this](Command* cmd) {
    context_.FillOutCommand(cmd);  // Ignore errors, this is for autocomplete.
  });
  line_input_.SetAutocompleteCallback([fill_command_context = std::move(fill_command_context)](
                                          const std::string& prefix) -> std::vector<std::string> {
    return GetCommandCompletions(prefix, fill_command_context);
  });

  // EOF (ctrl-d) should exit gracefully.
  line_input_.SetEofCallback([this]() {
    line_input_.Hide();
    debug_ipc::MessageLoop::Current()->QuitNow();
  });

  // Set stdin to async mode or OnStdinReadable will block.
  fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | O_NONBLOCK);
}

ConsoleImpl::~ConsoleImpl() {
  if (!SaveHistoryFile())
    Console::Output(Err("Could not save history file to $HOME/%s.\n", kHistoryFilename));
}

fxl::WeakPtr<ConsoleImpl> ConsoleImpl::GetImplWeakPtr() { return impl_weak_factory_.GetWeakPtr(); }

void ConsoleImpl::Init() {
  PreserveStdoutTermios();

  stdio_watch_ = debug_ipc::MessageLoop::Current()->WatchFD(
      debug_ipc::MessageLoop::WatchMode::kRead, STDIN_FILENO, this);

  LoadHistoryFile();
  line_input_.Show();
}

void ConsoleImpl::LoadHistoryFile() {
  std::filesystem::path path(getenv("HOME"));
  if (path.empty())
    return;
  path /= kHistoryFilename;

  std::string data;
  if (!files::ReadFileToString(path, &data))
    return;

  auto history = fxl::SplitStringCopy(data, "\n", fxl::kTrimWhitespace, fxl::kSplitWantNonEmpty);

  for (const std::string& cmd : history)
    line_input_.AddToHistory(cmd);
}

bool ConsoleImpl::SaveHistoryFile() {
  char* home = getenv("HOME");
  if (!home)
    return false;

  // We need to invert the order the deque has the entries.
  std::string history_data;
  const auto& history = line_input_.GetHistory();
  for (auto it = history.rbegin(); it != history.rend(); it++) {
    auto trimmed = fxl::TrimString(*it, " ");
    // We ignore empty entries or quit commands.
    if (trimmed.empty() || trimmed == "quit" || trimmed == "q" || trimmed == "exit") {
      continue;
    }

    history_data.append(trimmed).append("\n");
  }

  auto filepath = std::filesystem::path(home) / kHistoryFilename;
  return files::WriteFile(filepath, history_data.data(), history_data.size());
}

void ConsoleImpl::Output(const OutputBuffer& output) {
  // Since most operations are asynchronous, we have to hide the input line before printing anything
  // or it will get appended to whatever the user is typing on the screen.
  //
  // TODO(brettw) This can cause flickering. A more advanced system would do more fancy console
  // stuff to output above the input line so we'd never have to hide it.

  // Make sure stdout is in blocking mode since normal output won't expect non-blocking mode. We can
  // get in this state if stdin and stdout are the same underlying handle because the constructor
  // sets stdin to O_NONBLOCK so we can asynchronously wait for input.
  int old_bits = fcntl(STDIN_FILENO, F_GETFL, 0);
  if (old_bits & O_NONBLOCK)
    fcntl(STDOUT_FILENO, F_SETFL, old_bits & ~O_NONBLOCK);

  line_input_.Hide();
  output.WriteToStdout();
  line_input_.Show();

  if (old_bits & O_NONBLOCK)
    fcntl(STDOUT_FILENO, F_SETFL, old_bits);
}

void ConsoleImpl::ModalGetOption(const line_input::ModalPromptOptions& options,
                                 OutputBuffer message, const std::string& prompt,
                                 line_input::ModalLineInput::ModalCompletionCallback cb) {
  // Print the message from within the "will show" callback to ensure proper serialization if there
  // are multiple prompts pending.
  //
  // Okay to capture |this| because we own the line_input_.
  line_input_.ModalGetOption(options, prompt, std::move(cb),
                             [this, message = std::move(message)]() { Output(message); });
}

void ConsoleImpl::Quit() {
  line_input_.Hide();
  debug_ipc::MessageLoop::Current()->QuitNow();
}

void ConsoleImpl::Clear() {
  // We write directly instead of using Output because WriteToStdout expects to append '\n' to
  // outputs and won't flush it explicitly otherwise.
  line_input_.Hide();
  const char ff[] = "\033c";  // Form feed.
  write(STDOUT_FILENO, ff, sizeof(ff));
  line_input_.Show();
}

void ConsoleImpl::ProcessInputLine(const std::string& line, CommandCallback callback) {
  Command cmd;
  Err err;
  if (line.empty()) {
    // Repeat the previous command, don't add to history.
    err = ParseCommand(previous_line_, &cmd);
  } else {
    line_input_.AddToHistory(line);
    err = ParseCommand(line, &cmd);
    previous_line_ = line;
  }

  if (err.ok()) {
    err = context_.FillOutCommand(&cmd);
    if (!err.has_error()) {
      err = DispatchCommand(&context_, cmd, std::move(callback));

      if (cmd.thread() && cmd.verb() != Verb::kNone) {
        // Show the right source/disassembly for the next listing.
        context_.SetSourceAffinityForThread(cmd.thread(),
                                            GetVerbRecord(cmd.verb())->source_affinity);
      }
    }
  }

  if (err.has_error()) {
    OutputBuffer out;
    out.Append(err);
    Output(out);
  }
}

void ConsoleImpl::OnFDReady(int fd, bool readable, bool, bool) {
  if (!readable)
    return;

  char ch;
  while (read(STDIN_FILENO, &ch, 1) > 0)
    line_input_.OnInput(ch);
}

}  // namespace zxdb
