//===-- Statusline.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/Statusline.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Locale.h"

#define ESCAPE "\x1b"
#define ANSI_NORMAL ESCAPE "[0m"
#define ANSI_SAVE_CURSOR ESCAPE "7"
#define ANSI_RESTORE_CURSOR ESCAPE "8"
#define ANSI_CLEAR_BELOW ESCAPE "[J"
#define ANSI_CLEAR_SCREEN ESCAPE "[2J"
#define ANSI_SET_SCROLL_ROWS ESCAPE "[1;%ur"
#define ANSI_TO_START_OF_ROW ESCAPE "[%u;1f"
#define ANSI_REVERSE_VIDEO ESCAPE "[7m"
#define ANSI_UP_ROWS ESCAPE "[%dA"

using namespace lldb;
using namespace lldb_private;

Statusline::Statusline(Debugger &debugger)
    : m_debugger(debugger), m_terminal_width(m_debugger.GetTerminalWidth()),
      m_terminal_height(m_debugger.GetTerminalHeight()) {}

Statusline::~Statusline() { Disable(); }

void Statusline::TerminalSizeChanged() {
  m_terminal_width = m_debugger.GetTerminalWidth();
  m_terminal_height = m_debugger.GetTerminalHeight();

  UpdateScrollWindow(ResizeStatusline);

  // Redraw the old statusline.
  Redraw(std::nullopt);
}

void Statusline::Enable(std::optional<ExecutionContextRef> exe_ctx_ref) {
  // Reduce the scroll window to make space for the status bar below.
  UpdateScrollWindow(EnableStatusline);

  // Draw the statusline.
  Redraw(exe_ctx_ref);
}

void Statusline::Disable() {
  // Extend the scroll window to cover the status bar.
  UpdateScrollWindow(DisableStatusline);
}

void Statusline::Draw(std::string str) {
  lldb::LockableStreamFileSP stream_sp = m_debugger.GetOutputStreamSP();
  if (!stream_sp)
    return;

  str = ansi::TrimAndPad(str, m_terminal_width);

  LockedStreamFile locked_stream = stream_sp->Lock();
  locked_stream << ANSI_SAVE_CURSOR;
  locked_stream.Printf(ANSI_TO_START_OF_ROW,
                       static_cast<unsigned>(m_terminal_height));

  // Use "reverse video" to make sure the statusline has a background. Only do
  // this when colors are disabled, and rely on the statusline format otherwise.
  if (!m_debugger.GetUseColor())
    locked_stream << ANSI_REVERSE_VIDEO;

  locked_stream << str;
  locked_stream << ANSI_NORMAL;
  locked_stream << ANSI_RESTORE_CURSOR;
}

void Statusline::UpdateScrollWindow(ScrollWindowMode mode) {
  assert(m_terminal_width != 0 && m_terminal_height != 0);

  lldb::LockableStreamFileSP stream_sp = m_debugger.GetOutputStreamSP();
  if (!stream_sp)
    return;

  const unsigned reduced_scroll_rows = m_terminal_height - 1;
  { // Scope for locked_stream:
    LockedStreamFile locked_stream = stream_sp->Lock();

    switch (mode) {
    case EnableStatusline:
      // Move everything on the screen up.
      locked_stream << '\n';
      locked_stream.Printf(ANSI_UP_ROWS, 1);
      // Reduce the scroll window.
      locked_stream << ANSI_SAVE_CURSOR;
      locked_stream.Printf(ANSI_SET_SCROLL_ROWS, reduced_scroll_rows);
      locked_stream << ANSI_RESTORE_CURSOR;
      break;
    case DisableStatusline:
      // Reset the scroll window.
      locked_stream << ANSI_SAVE_CURSOR;
      locked_stream.Printf(ANSI_SET_SCROLL_ROWS,
                           static_cast<unsigned>(m_terminal_height));
      locked_stream << ANSI_RESTORE_CURSOR;
      // Clear the screen below to hide the old statusline.
      locked_stream << ANSI_CLEAR_BELOW;
      break;
    case ResizeStatusline:
      // Clear the screen and update the scroll window.
      // FIXME: Find a better solution (#146919).
      locked_stream << ANSI_CLEAR_SCREEN;
      locked_stream.Printf(ANSI_SET_SCROLL_ROWS, reduced_scroll_rows);
      break;
    }
  }
  m_debugger.RefreshIOHandler();
}

void Statusline::Redraw(std::optional<ExecutionContextRef> exe_ctx_ref) {
  // Update the cached execution context.
  if (exe_ctx_ref)
    m_exe_ctx_ref = *exe_ctx_ref;

  // Lock the execution context.
  ExecutionContext exe_ctx =
      m_exe_ctx_ref.Lock(/*thread_and_frame_only_if_stopped=*/false);

  // Compute the symbol context if we're stopped.
  SymbolContext sym_ctx;
  llvm::Expected<StoppedExecutionContext> stopped_exe_ctx =
      GetStoppedExecutionContext(&m_exe_ctx_ref);
  if (stopped_exe_ctx) {
    // The StoppedExecutionContext only ensures that we hold the run lock.
    // The process could be in an exited or unloaded state and have no frame.
    if (auto frame_sp = stopped_exe_ctx->GetFrameSP())
      sym_ctx = frame_sp->GetSymbolContext(eSymbolContextEverything);
  } else {
    // We can draw the statusline without being stopped.
    llvm::consumeError(stopped_exe_ctx.takeError());
  }

  StreamString stream;
  FormatEntity::Entry format = m_debugger.GetStatuslineFormat();
  FormatEntity::Formatter(&sym_ctx, &exe_ctx, nullptr, false, false)
      .Format(format, stream);

  Draw(stream.GetString().str());
}
