// 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 <sys/ioctl.h>
#include <termios.h>
#endif

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

  // 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));
}

void ConsoleImpl::Init() {
  PreserveStdoutTermios();
  line_input_.BeginReadLine();

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

  LoadHistoryFile();
}

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_.history();
  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.ToString()).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::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();
}

Console::Result ConsoleImpl::DispatchInputLine(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()) {
    if (cmd.verb() == Verb::kQuit) {
      return Result::kQuit;
    } else {
      err = context_.FillOutCommand(&cmd);
      if (!err.has_error()) {
        err = DispatchCommand(&context_, cmd, 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);
  }
  return Result::kContinue;
}

Console::Result ConsoleImpl::ProcessInputLine(const std::string& line, CommandCallback callback) {
  Result result = DispatchInputLine(line, callback);
  if (result == Result::kQuit)
    debug_ipc::MessageLoop::Current()->QuitNow();
  return result;
}

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

  char ch;
  while (read(STDIN_FILENO, &ch, 1) > 0) {
    if (line_input_.OnInput(ch)) {
      // EOF (ctrl-d) should exit gracefully.
      if (line_input_.eof()) {
        line_input_.EnsureNoRawMode();
        Console::Output("\n");
        debug_ipc::MessageLoop::Current()->QuitNow();
        return;
      }

      std::string line = line_input_.line();
      Result result = ProcessInputLine(line);
      if (result == Result::kQuit)
        return;
      line_input_.BeginReadLine();
    }
  }
}

}  // namespace zxdb
