//===-- IOHandlerCursesGUI.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/IOHandlerCursesGUI.h"
#include "lldb/Host/Config.h"

#if LLDB_ENABLE_CURSES
#if CURSES_HAVE_NCURSES_CURSES_H
#include <ncurses/curses.h>
#include <ncurses/panel.h>
#else
#include <curses.h>
#include <panel.h>
#endif
#endif

#if defined(__APPLE__)
#include <deque>
#endif
#include <string>

#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObjectUpdater.h"
#include "lldb/Host/File.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringList.h"
#include "lldb/lldb-forward.h"

#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"

#if LLDB_ENABLE_CURSES
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/State.h"
#endif

#include "llvm/ADT/StringRef.h"

#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
#endif

#include <memory>
#include <mutex>

#include <cassert>
#include <cctype>
#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <functional>
#include <optional>
#include <type_traits>

using namespace lldb;
using namespace lldb_private;
using llvm::StringRef;

// we may want curses to be disabled for some builds for instance, windows
#if LLDB_ENABLE_CURSES

#define KEY_CTRL_A 1
#define KEY_CTRL_E 5
#define KEY_CTRL_K 11
#define KEY_RETURN 10
#define KEY_ESCAPE 27
#define KEY_DELETE 127

#define KEY_SHIFT_TAB (KEY_MAX + 1)
#define KEY_ALT_ENTER (KEY_MAX + 2)

namespace curses {
class Menu;
class MenuDelegate;
class Window;
class WindowDelegate;
typedef std::shared_ptr<Menu> MenuSP;
typedef std::shared_ptr<MenuDelegate> MenuDelegateSP;
typedef std::shared_ptr<Window> WindowSP;
typedef std::shared_ptr<WindowDelegate> WindowDelegateSP;
typedef std::vector<MenuSP> Menus;
typedef std::vector<WindowSP> Windows;
typedef std::vector<WindowDelegateSP> WindowDelegates;

#if 0
type summary add -s "x=${var.x}, y=${var.y}" curses::Point
type summary add -s "w=${var.width}, h=${var.height}" curses::Size
type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
#endif

struct Point {
  int x;
  int y;

  Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}

  void Clear() {
    x = 0;
    y = 0;
  }

  Point &operator+=(const Point &rhs) {
    x += rhs.x;
    y += rhs.y;
    return *this;
  }

  void Dump() { printf("(x=%i, y=%i)\n", x, y); }
};

bool operator==(const Point &lhs, const Point &rhs) {
  return lhs.x == rhs.x && lhs.y == rhs.y;
}

bool operator!=(const Point &lhs, const Point &rhs) {
  return lhs.x != rhs.x || lhs.y != rhs.y;
}

struct Size {
  int width;
  int height;
  Size(int w = 0, int h = 0) : width(w), height(h) {}

  void Clear() {
    width = 0;
    height = 0;
  }

  void Dump() { printf("(w=%i, h=%i)\n", width, height); }
};

bool operator==(const Size &lhs, const Size &rhs) {
  return lhs.width == rhs.width && lhs.height == rhs.height;
}

bool operator!=(const Size &lhs, const Size &rhs) {
  return lhs.width != rhs.width || lhs.height != rhs.height;
}

struct Rect {
  Point origin;
  Size size;

  Rect() : origin(), size() {}

  Rect(const Point &p, const Size &s) : origin(p), size(s) {}

  void Clear() {
    origin.Clear();
    size.Clear();
  }

  void Dump() {
    printf("(x=%i, y=%i), w=%i, h=%i)\n", origin.x, origin.y, size.width,
           size.height);
  }

  void Inset(int w, int h) {
    if (size.width > w * 2)
      size.width -= w * 2;
    origin.x += w;

    if (size.height > h * 2)
      size.height -= h * 2;
    origin.y += h;
  }

  // Return a status bar rectangle which is the last line of this rectangle.
  // This rectangle will be modified to not include the status bar area.
  Rect MakeStatusBar() {
    Rect status_bar;
    if (size.height > 1) {
      status_bar.origin.x = origin.x;
      status_bar.origin.y = size.height;
      status_bar.size.width = size.width;
      status_bar.size.height = 1;
      --size.height;
    }
    return status_bar;
  }

  // Return a menubar rectangle which is the first line of this rectangle. This
  // rectangle will be modified to not include the menubar area.
  Rect MakeMenuBar() {
    Rect menubar;
    if (size.height > 1) {
      menubar.origin.x = origin.x;
      menubar.origin.y = origin.y;
      menubar.size.width = size.width;
      menubar.size.height = 1;
      ++origin.y;
      --size.height;
    }
    return menubar;
  }

  void HorizontalSplitPercentage(float top_percentage, Rect &top,
                                 Rect &bottom) const {
    float top_height = top_percentage * size.height;
    HorizontalSplit(top_height, top, bottom);
  }

  void HorizontalSplit(int top_height, Rect &top, Rect &bottom) const {
    top = *this;
    if (top_height < size.height) {
      top.size.height = top_height;
      bottom.origin.x = origin.x;
      bottom.origin.y = origin.y + top.size.height;
      bottom.size.width = size.width;
      bottom.size.height = size.height - top.size.height;
    } else {
      bottom.Clear();
    }
  }

  void VerticalSplitPercentage(float left_percentage, Rect &left,
                               Rect &right) const {
    float left_width = left_percentage * size.width;
    VerticalSplit(left_width, left, right);
  }

  void VerticalSplit(int left_width, Rect &left, Rect &right) const {
    left = *this;
    if (left_width < size.width) {
      left.size.width = left_width;
      right.origin.x = origin.x + left.size.width;
      right.origin.y = origin.y;
      right.size.width = size.width - left.size.width;
      right.size.height = size.height;
    } else {
      right.Clear();
    }
  }
};

bool operator==(const Rect &lhs, const Rect &rhs) {
  return lhs.origin == rhs.origin && lhs.size == rhs.size;
}

bool operator!=(const Rect &lhs, const Rect &rhs) {
  return lhs.origin != rhs.origin || lhs.size != rhs.size;
}

enum HandleCharResult {
  eKeyNotHandled = 0,
  eKeyHandled = 1,
  eQuitApplication = 2
};

enum class MenuActionResult {
  Handled,
  NotHandled,
  Quit // Exit all menus and quit
};

struct KeyHelp {
  int ch;
  const char *description;
};

// COLOR_PAIR index names
enum {
  // First 16 colors are 8 black background and 8 blue background colors,
  // needed by OutputColoredStringTruncated().
  BlackOnBlack = 1,
  RedOnBlack,
  GreenOnBlack,
  YellowOnBlack,
  BlueOnBlack,
  MagentaOnBlack,
  CyanOnBlack,
  WhiteOnBlack,
  BlackOnBlue,
  RedOnBlue,
  GreenOnBlue,
  YellowOnBlue,
  BlueOnBlue,
  MagentaOnBlue,
  CyanOnBlue,
  WhiteOnBlue,
  // Other colors, as needed.
  BlackOnWhite,
  MagentaOnWhite,
  LastColorPairIndex = MagentaOnWhite
};

class WindowDelegate {
public:
  virtual ~WindowDelegate() = default;

  virtual bool WindowDelegateDraw(Window &window, bool force) {
    return false; // Drawing not handled
  }

  virtual HandleCharResult WindowDelegateHandleChar(Window &window, int key) {
    return eKeyNotHandled;
  }

  virtual const char *WindowDelegateGetHelpText() { return nullptr; }

  virtual KeyHelp *WindowDelegateGetKeyHelp() { return nullptr; }
};

class HelpDialogDelegate : public WindowDelegate {
public:
  HelpDialogDelegate(const char *text, KeyHelp *key_help_array);

  ~HelpDialogDelegate() override;

  bool WindowDelegateDraw(Window &window, bool force) override;

  HandleCharResult WindowDelegateHandleChar(Window &window, int key) override;

  size_t GetNumLines() const { return m_text.GetSize(); }

  size_t GetMaxLineLength() const { return m_text.GetMaxStringLength(); }

protected:
  StringList m_text;
  int m_first_visible_line = 0;
};

// A surface is an abstraction for something than can be drawn on. The surface
// have a width, a height, a cursor position, and a multitude of drawing
// operations. This type should be sub-classed to get an actually useful ncurses
// object, such as a Window or a Pad.
class Surface {
public:
  enum class Type { Window, Pad };

  Surface(Surface::Type type) : m_type(type) {}

  WINDOW *get() { return m_window; }

  operator WINDOW *() { return m_window; }

  Surface SubSurface(Rect bounds) {
    Surface subSurface(m_type);
    if (m_type == Type::Pad)
      subSurface.m_window =
          ::subpad(m_window, bounds.size.height, bounds.size.width,
                   bounds.origin.y, bounds.origin.x);
    else
      subSurface.m_window =
          ::derwin(m_window, bounds.size.height, bounds.size.width,
                   bounds.origin.y, bounds.origin.x);
    return subSurface;
  }

  // Copy a region of the surface to another surface.
  void CopyToSurface(Surface &target, Point source_origin, Point target_origin,
                     Size size) {
    ::copywin(m_window, target.get(), source_origin.y, source_origin.x,
              target_origin.y, target_origin.x,
              target_origin.y + size.height - 1,
              target_origin.x + size.width - 1, false);
  }

  int GetCursorX() const { return getcurx(m_window); }
  int GetCursorY() const { return getcury(m_window); }
  void MoveCursor(int x, int y) { ::wmove(m_window, y, x); }

  void AttributeOn(attr_t attr) { ::wattron(m_window, attr); }
  void AttributeOff(attr_t attr) { ::wattroff(m_window, attr); }

  int GetMaxX() const { return getmaxx(m_window); }
  int GetMaxY() const { return getmaxy(m_window); }
  int GetWidth() const { return GetMaxX(); }
  int GetHeight() const { return GetMaxY(); }
  Size GetSize() const { return Size(GetWidth(), GetHeight()); }
  // Get a zero origin rectangle width the surface size.
  Rect GetFrame() const { return Rect(Point(), GetSize()); }

  void Clear() { ::wclear(m_window); }
  void Erase() { ::werase(m_window); }

  void SetBackground(int color_pair_idx) {
    ::wbkgd(m_window, COLOR_PAIR(color_pair_idx));
  }

  void PutChar(int ch) { ::waddch(m_window, ch); }
  void PutCString(const char *s, int len = -1) { ::waddnstr(m_window, s, len); }

  void PutCStringTruncated(int right_pad, const char *s, int len = -1) {
    int bytes_left = GetWidth() - GetCursorX();
    if (bytes_left > right_pad) {
      bytes_left -= right_pad;
      ::waddnstr(m_window, s, len < 0 ? bytes_left : std::min(bytes_left, len));
    }
  }

  void Printf(const char *format, ...) __attribute__((format(printf, 2, 3))) {
    va_list args;
    va_start(args, format);
    vw_printw(m_window, format, args);
    va_end(args);
  }

  void PrintfTruncated(int right_pad, const char *format, ...)
      __attribute__((format(printf, 3, 4))) {
    va_list args;
    va_start(args, format);
    StreamString strm;
    strm.PrintfVarArg(format, args);
    va_end(args);
    PutCStringTruncated(right_pad, strm.GetData());
  }

  void VerticalLine(int n, chtype v_char = ACS_VLINE) {
    ::wvline(m_window, v_char, n);
  }
  void HorizontalLine(int n, chtype h_char = ACS_HLINE) {
    ::whline(m_window, h_char, n);
  }
  void Box(chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) {
    ::box(m_window, v_char, h_char);
  }

  void TitledBox(const char *title, chtype v_char = ACS_VLINE,
                 chtype h_char = ACS_HLINE) {
    Box(v_char, h_char);
    int title_offset = 2;
    MoveCursor(title_offset, 0);
    PutChar('[');
    PutCString(title, GetWidth() - title_offset);
    PutChar(']');
  }

  void Box(const Rect &bounds, chtype v_char = ACS_VLINE,
           chtype h_char = ACS_HLINE) {
    MoveCursor(bounds.origin.x, bounds.origin.y);
    VerticalLine(bounds.size.height);
    HorizontalLine(bounds.size.width);
    PutChar(ACS_ULCORNER);

    MoveCursor(bounds.origin.x + bounds.size.width - 1, bounds.origin.y);
    VerticalLine(bounds.size.height);
    PutChar(ACS_URCORNER);

    MoveCursor(bounds.origin.x, bounds.origin.y + bounds.size.height - 1);
    HorizontalLine(bounds.size.width);
    PutChar(ACS_LLCORNER);

    MoveCursor(bounds.origin.x + bounds.size.width - 1,
               bounds.origin.y + bounds.size.height - 1);
    PutChar(ACS_LRCORNER);
  }

  void TitledBox(const Rect &bounds, const char *title,
                 chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) {
    Box(bounds, v_char, h_char);
    int title_offset = 2;
    MoveCursor(bounds.origin.x + title_offset, bounds.origin.y);
    PutChar('[');
    PutCString(title, bounds.size.width - title_offset);
    PutChar(']');
  }

  // Curses doesn't allow direct output of color escape sequences, but that's
  // how we get source lines from the Highligher class. Read the line and
  // convert color escape sequences to curses color attributes. Use
  // first_skip_count to skip leading visible characters. Returns false if all
  // visible characters were skipped due to first_skip_count.
  bool OutputColoredStringTruncated(int right_pad, StringRef string,
                                    size_t skip_first_count,
                                    bool use_blue_background) {
    attr_t saved_attr;
    short saved_pair;
    bool result = false;
    wattr_get(m_window, &saved_attr, &saved_pair, nullptr);
    if (use_blue_background)
      ::wattron(m_window, COLOR_PAIR(WhiteOnBlue));
    while (!string.empty()) {
      size_t esc_pos = string.find(ANSI_ESC_START);
      if (esc_pos == StringRef::npos) {
        string = string.substr(skip_first_count);
        if (!string.empty()) {
          PutCStringTruncated(right_pad, string.data(), string.size());
          result = true;
        }
        break;
      }
      if (esc_pos > 0) {
        if (skip_first_count > 0) {
          int skip = std::min(esc_pos, skip_first_count);
          string = string.substr(skip);
          skip_first_count -= skip;
          esc_pos -= skip;
        }
        if (esc_pos > 0) {
          PutCStringTruncated(right_pad, string.data(), esc_pos);
          result = true;
          string = string.drop_front(esc_pos);
        }
      }
      bool consumed = string.consume_front(ANSI_ESC_START);
      assert(consumed);
      UNUSED_IF_ASSERT_DISABLED(consumed);
      // This is written to match our Highlighter classes, which seem to
      // generate only foreground color escape sequences. If necessary, this
      // will need to be extended.
      // Only 8 basic foreground colors, underline and reset, our Highlighter
      // doesn't use anything else.
      int value;
      if (!!string.consumeInteger(10, value) || // Returns false on success.
          !(value == 0 || value == ANSI_CTRL_UNDERLINE ||
            (value >= ANSI_FG_COLOR_BLACK && value <= ANSI_FG_COLOR_WHITE))) {
        llvm::errs() << "No valid color code in color escape sequence.\n";
        continue;
      }
      if (!string.consume_front(ANSI_ESC_END)) {
        llvm::errs() << "Missing '" << ANSI_ESC_END
                     << "' in color escape sequence.\n";
        continue;
      }
      if (value == 0) { // Reset.
        wattr_set(m_window, saved_attr, saved_pair, nullptr);
        if (use_blue_background)
          ::wattron(m_window, COLOR_PAIR(WhiteOnBlue));
      } else if (value == ANSI_CTRL_UNDERLINE) {
        ::wattron(m_window, A_UNDERLINE);
      } else {
        // Mapped directly to first 16 color pairs (black/blue background).
        ::wattron(m_window, COLOR_PAIR(value - ANSI_FG_COLOR_BLACK + 1 +
                                       (use_blue_background ? 8 : 0)));
      }
    }
    wattr_set(m_window, saved_attr, saved_pair, nullptr);
    return result;
  }

protected:
  Type m_type;
  WINDOW *m_window = nullptr;
};

class Pad : public Surface {
public:
  Pad(Size size) : Surface(Surface::Type::Pad) {
    m_window = ::newpad(size.height, size.width);
  }

  ~Pad() { ::delwin(m_window); }
};

class Window : public Surface {
public:
  Window(const char *name)
      : Surface(Surface::Type::Window), m_name(name), m_panel(nullptr),
        m_parent(nullptr), m_subwindows(), m_delegate_sp(),
        m_curr_active_window_idx(UINT32_MAX),
        m_prev_active_window_idx(UINT32_MAX), m_delete(false),
        m_needs_update(true), m_can_activate(true), m_is_subwin(false) {}

  Window(const char *name, WINDOW *w, bool del = true)
      : Surface(Surface::Type::Window), m_name(name), m_panel(nullptr),
        m_parent(nullptr), m_subwindows(), m_delegate_sp(),
        m_curr_active_window_idx(UINT32_MAX),
        m_prev_active_window_idx(UINT32_MAX), m_delete(del),
        m_needs_update(true), m_can_activate(true), m_is_subwin(false) {
    if (w)
      Reset(w);
  }

  Window(const char *name, const Rect &bounds)
      : Surface(Surface::Type::Window), m_name(name), m_panel(nullptr),
        m_parent(nullptr), m_subwindows(), m_delegate_sp(),
        m_curr_active_window_idx(UINT32_MAX),
        m_prev_active_window_idx(UINT32_MAX), m_delete(false),
        m_needs_update(true), m_can_activate(true), m_is_subwin(false) {
    Reset(::newwin(bounds.size.height, bounds.size.width, bounds.origin.y,
                   bounds.origin.y));
  }

  virtual ~Window() {
    RemoveSubWindows();
    Reset();
  }

  void Reset(WINDOW *w = nullptr, bool del = true) {
    if (m_window == w)
      return;

    if (m_panel) {
      ::del_panel(m_panel);
      m_panel = nullptr;
    }
    if (m_window && m_delete) {
      ::delwin(m_window);
      m_window = nullptr;
      m_delete = false;
    }
    if (w) {
      m_window = w;
      m_panel = ::new_panel(m_window);
      m_delete = del;
    }
  }

  // Get the rectangle in our parent window
  Rect GetBounds() const { return Rect(GetParentOrigin(), GetSize()); }

  Rect GetCenteredRect(int width, int height) {
    Size size = GetSize();
    width = std::min(size.width, width);
    height = std::min(size.height, height);
    int x = (size.width - width) / 2;
    int y = (size.height - height) / 2;
    return Rect(Point(x, y), Size(width, height));
  }

  int GetChar() { return ::wgetch(m_window); }
  Point GetParentOrigin() const { return Point(GetParentX(), GetParentY()); }
  int GetParentX() const { return getparx(m_window); }
  int GetParentY() const { return getpary(m_window); }
  void MoveWindow(int x, int y) { MoveWindow(Point(x, y)); }
  void Resize(int w, int h) { ::wresize(m_window, h, w); }
  void Resize(const Size &size) {
    ::wresize(m_window, size.height, size.width);
  }
  void MoveWindow(const Point &origin) {
    const bool moving_window = origin != GetParentOrigin();
    if (m_is_subwin && moving_window) {
      // Can't move subwindows, must delete and re-create
      Size size = GetSize();
      Reset(::subwin(m_parent->m_window, size.height, size.width, origin.y,
                     origin.x),
            true);
    } else {
      ::mvwin(m_window, origin.y, origin.x);
    }
  }

  void SetBounds(const Rect &bounds) {
    const bool moving_window = bounds.origin != GetParentOrigin();
    if (m_is_subwin && moving_window) {
      // Can't move subwindows, must delete and re-create
      Reset(::subwin(m_parent->m_window, bounds.size.height, bounds.size.width,
                     bounds.origin.y, bounds.origin.x),
            true);
    } else {
      if (moving_window)
        MoveWindow(bounds.origin);
      Resize(bounds.size);
    }
  }

  void Touch() {
    ::touchwin(m_window);
    if (m_parent)
      m_parent->Touch();
  }

  WindowSP CreateSubWindow(const char *name, const Rect &bounds,
                           bool make_active) {
    auto get_window = [this, &bounds]() {
      return m_window
                 ? ::subwin(m_window, bounds.size.height, bounds.size.width,
                            bounds.origin.y, bounds.origin.x)
                 : ::newwin(bounds.size.height, bounds.size.width,
                            bounds.origin.y, bounds.origin.x);
    };
    WindowSP subwindow_sp = std::make_shared<Window>(name, get_window(), true);
    subwindow_sp->m_is_subwin = subwindow_sp.operator bool();
    subwindow_sp->m_parent = this;
    if (make_active) {
      m_prev_active_window_idx = m_curr_active_window_idx;
      m_curr_active_window_idx = m_subwindows.size();
    }
    m_subwindows.push_back(subwindow_sp);
    ::top_panel(subwindow_sp->m_panel);
    m_needs_update = true;
    return subwindow_sp;
  }

  bool RemoveSubWindow(Window *window) {
    Windows::iterator pos, end = m_subwindows.end();
    size_t i = 0;
    for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) {
      if ((*pos).get() == window) {
        if (m_prev_active_window_idx == i)
          m_prev_active_window_idx = UINT32_MAX;
        else if (m_prev_active_window_idx != UINT32_MAX &&
                 m_prev_active_window_idx > i)
          --m_prev_active_window_idx;

        if (m_curr_active_window_idx == i)
          m_curr_active_window_idx = UINT32_MAX;
        else if (m_curr_active_window_idx != UINT32_MAX &&
                 m_curr_active_window_idx > i)
          --m_curr_active_window_idx;
        window->Erase();
        m_subwindows.erase(pos);
        m_needs_update = true;
        if (m_parent)
          m_parent->Touch();
        else
          ::touchwin(stdscr);
        return true;
      }
    }
    return false;
  }

  WindowSP FindSubWindow(const char *name) {
    Windows::iterator pos, end = m_subwindows.end();
    size_t i = 0;
    for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) {
      if ((*pos)->m_name == name)
        return *pos;
    }
    return WindowSP();
  }

  void RemoveSubWindows() {
    m_curr_active_window_idx = UINT32_MAX;
    m_prev_active_window_idx = UINT32_MAX;
    for (Windows::iterator pos = m_subwindows.begin();
         pos != m_subwindows.end(); pos = m_subwindows.erase(pos)) {
      (*pos)->Erase();
    }
    if (m_parent)
      m_parent->Touch();
    else
      ::touchwin(stdscr);
  }

  // Window drawing utilities
  void DrawTitleBox(const char *title, const char *bottom_message = nullptr) {
    attr_t attr = 0;
    if (IsActive())
      attr = A_BOLD | COLOR_PAIR(BlackOnWhite);
    else
      attr = 0;
    if (attr)
      AttributeOn(attr);

    Box();
    MoveCursor(3, 0);

    if (title && title[0]) {
      PutChar('<');
      PutCString(title);
      PutChar('>');
    }

    if (bottom_message && bottom_message[0]) {
      int bottom_message_length = strlen(bottom_message);
      int x = GetWidth() - 3 - (bottom_message_length + 2);

      if (x > 0) {
        MoveCursor(x, GetHeight() - 1);
        PutChar('[');
        PutCString(bottom_message);
        PutChar(']');
      } else {
        MoveCursor(1, GetHeight() - 1);
        PutChar('[');
        PutCStringTruncated(1, bottom_message);
      }
    }
    if (attr)
      AttributeOff(attr);
  }

  virtual void Draw(bool force) {
    if (m_delegate_sp && m_delegate_sp->WindowDelegateDraw(*this, force))
      return;

    for (auto &subwindow_sp : m_subwindows)
      subwindow_sp->Draw(force);
  }

  bool CreateHelpSubwindow() {
    if (m_delegate_sp) {
      const char *text = m_delegate_sp->WindowDelegateGetHelpText();
      KeyHelp *key_help = m_delegate_sp->WindowDelegateGetKeyHelp();
      if ((text && text[0]) || key_help) {
        std::unique_ptr<HelpDialogDelegate> help_delegate_up(
            new HelpDialogDelegate(text, key_help));
        const size_t num_lines = help_delegate_up->GetNumLines();
        const size_t max_length = help_delegate_up->GetMaxLineLength();
        Rect bounds = GetBounds();
        bounds.Inset(1, 1);
        if (max_length + 4 < static_cast<size_t>(bounds.size.width)) {
          bounds.origin.x += (bounds.size.width - max_length + 4) / 2;
          bounds.size.width = max_length + 4;
        } else {
          if (bounds.size.width > 100) {
            const int inset_w = bounds.size.width / 4;
            bounds.origin.x += inset_w;
            bounds.size.width -= 2 * inset_w;
          }
        }

        if (num_lines + 2 < static_cast<size_t>(bounds.size.height)) {
          bounds.origin.y += (bounds.size.height - num_lines + 2) / 2;
          bounds.size.height = num_lines + 2;
        } else {
          if (bounds.size.height > 100) {
            const int inset_h = bounds.size.height / 4;
            bounds.origin.y += inset_h;
            bounds.size.height -= 2 * inset_h;
          }
        }
        WindowSP help_window_sp;
        Window *parent_window = GetParent();
        if (parent_window)
          help_window_sp = parent_window->CreateSubWindow("Help", bounds, true);
        else
          help_window_sp = CreateSubWindow("Help", bounds, true);
        help_window_sp->SetDelegate(
            WindowDelegateSP(help_delegate_up.release()));
        return true;
      }
    }
    return false;
  }

  virtual HandleCharResult HandleChar(int key) {
    // Always check the active window first
    HandleCharResult result = eKeyNotHandled;
    WindowSP active_window_sp = GetActiveWindow();
    if (active_window_sp) {
      result = active_window_sp->HandleChar(key);
      if (result != eKeyNotHandled)
        return result;
    }

    if (m_delegate_sp) {
      result = m_delegate_sp->WindowDelegateHandleChar(*this, key);
      if (result != eKeyNotHandled)
        return result;
    }

    // Then check for any windows that want any keys that weren't handled. This
    // is typically only for a menubar. Make a copy of the subwindows in case
    // any HandleChar() functions muck with the subwindows. If we don't do
    // this, we can crash when iterating over the subwindows.
    Windows subwindows(m_subwindows);
    for (auto subwindow_sp : subwindows) {
      if (!subwindow_sp->m_can_activate) {
        HandleCharResult result = subwindow_sp->HandleChar(key);
        if (result != eKeyNotHandled)
          return result;
      }
    }

    return eKeyNotHandled;
  }

  WindowSP GetActiveWindow() {
    if (!m_subwindows.empty()) {
      if (m_curr_active_window_idx >= m_subwindows.size()) {
        if (m_prev_active_window_idx < m_subwindows.size()) {
          m_curr_active_window_idx = m_prev_active_window_idx;
          m_prev_active_window_idx = UINT32_MAX;
        } else if (IsActive()) {
          m_prev_active_window_idx = UINT32_MAX;
          m_curr_active_window_idx = UINT32_MAX;

          // Find first window that wants to be active if this window is active
          const size_t num_subwindows = m_subwindows.size();
          for (size_t i = 0; i < num_subwindows; ++i) {
            if (m_subwindows[i]->GetCanBeActive()) {
              m_curr_active_window_idx = i;
              break;
            }
          }
        }
      }

      if (m_curr_active_window_idx < m_subwindows.size())
        return m_subwindows[m_curr_active_window_idx];
    }
    return WindowSP();
  }

  bool GetCanBeActive() const { return m_can_activate; }

  void SetCanBeActive(bool b) { m_can_activate = b; }

  void SetDelegate(const WindowDelegateSP &delegate_sp) {
    m_delegate_sp = delegate_sp;
  }

  Window *GetParent() const { return m_parent; }

  bool IsActive() const {
    if (m_parent)
      return m_parent->GetActiveWindow().get() == this;
    else
      return true; // Top level window is always active
  }

  void SelectNextWindowAsActive() {
    // Move active focus to next window
    const int num_subwindows = m_subwindows.size();
    int start_idx = 0;
    if (m_curr_active_window_idx != UINT32_MAX) {
      m_prev_active_window_idx = m_curr_active_window_idx;
      start_idx = m_curr_active_window_idx + 1;
    }
    for (int idx = start_idx; idx < num_subwindows; ++idx) {
      if (m_subwindows[idx]->GetCanBeActive()) {
        m_curr_active_window_idx = idx;
        return;
      }
    }
    for (int idx = 0; idx < start_idx; ++idx) {
      if (m_subwindows[idx]->GetCanBeActive()) {
        m_curr_active_window_idx = idx;
        break;
      }
    }
  }

  void SelectPreviousWindowAsActive() {
    // Move active focus to previous window
    const int num_subwindows = m_subwindows.size();
    int start_idx = num_subwindows - 1;
    if (m_curr_active_window_idx != UINT32_MAX) {
      m_prev_active_window_idx = m_curr_active_window_idx;
      start_idx = m_curr_active_window_idx - 1;
    }
    for (int idx = start_idx; idx >= 0; --idx) {
      if (m_subwindows[idx]->GetCanBeActive()) {
        m_curr_active_window_idx = idx;
        return;
      }
    }
    for (int idx = num_subwindows - 1; idx > start_idx; --idx) {
      if (m_subwindows[idx]->GetCanBeActive()) {
        m_curr_active_window_idx = idx;
        break;
      }
    }
  }

  const char *GetName() const { return m_name.c_str(); }

protected:
  std::string m_name;
  PANEL *m_panel;
  Window *m_parent;
  Windows m_subwindows;
  WindowDelegateSP m_delegate_sp;
  uint32_t m_curr_active_window_idx;
  uint32_t m_prev_active_window_idx;
  bool m_delete;
  bool m_needs_update;
  bool m_can_activate;
  bool m_is_subwin;

private:
  Window(const Window &) = delete;
  const Window &operator=(const Window &) = delete;
};

/////////
// Forms
/////////

// A scroll context defines a vertical region that needs to be visible in a
// scrolling area. The region is defined by the index of the start and end lines
// of the region. The start and end lines may be equal, in which case, the
// region is a single line.
struct ScrollContext {
  int start;
  int end;

  ScrollContext(int line) : start(line), end(line) {}
  ScrollContext(int _start, int _end) : start(_start), end(_end) {}

  void Offset(int offset) {
    start += offset;
    end += offset;
  }
};

class FieldDelegate {
public:
  virtual ~FieldDelegate() = default;

  // Returns the number of lines needed to draw the field. The draw method will
  // be given a surface that have exactly this number of lines.
  virtual int FieldDelegateGetHeight() = 0;

  // Returns the scroll context in the local coordinates of the field. By
  // default, the scroll context spans the whole field. Bigger fields with
  // internal navigation should override this method to provide a finer context.
  // Typical override methods would first get the scroll context of the internal
  // element then add the offset of the element in the field.
  virtual ScrollContext FieldDelegateGetScrollContext() {
    return ScrollContext(0, FieldDelegateGetHeight() - 1);
  }

  // Draw the field in the given subpad surface. The surface have a height that
  // is equal to the height returned by FieldDelegateGetHeight(). If the field
  // is selected in the form window, then is_selected will be true.
  virtual void FieldDelegateDraw(Surface &surface, bool is_selected) = 0;

  // Handle the key that wasn't handled by the form window or a container field.
  virtual HandleCharResult FieldDelegateHandleChar(int key) {
    return eKeyNotHandled;
  }

  // This is executed once the user exists the field, that is, once the user
  // navigates to the next or the previous field. This is particularly useful to
  // do in-field validation and error setting. Fields with internal navigation
  // should call this method on their fields.
  virtual void FieldDelegateExitCallback() {}

  // Fields may have internal navigation, for instance, a List Field have
  // multiple internal elements, which needs to be navigated. To allow for this
  // mechanism, the window shouldn't handle the navigation keys all the time,
  // and instead call the key handing method of the selected field. It should
  // only handle the navigation keys when the field contains a single element or
  // have the last or first element selected depending on if the user is
  // navigating forward or backward. Additionally, once a field is selected in
  // the forward or backward direction, its first or last internal element
  // should be selected. The following methods implements those mechanisms.

  // Returns true if the first element in the field is selected or if the field
  // contains a single element.
  virtual bool FieldDelegateOnFirstOrOnlyElement() { return true; }

  // Returns true if the last element in the field is selected or if the field
  // contains a single element.
  virtual bool FieldDelegateOnLastOrOnlyElement() { return true; }

  // Select the first element in the field if multiple elements exists.
  virtual void FieldDelegateSelectFirstElement() {}

  // Select the last element in the field if multiple elements exists.
  virtual void FieldDelegateSelectLastElement() {}

  // Returns true if the field has an error, false otherwise.
  virtual bool FieldDelegateHasError() { return false; }

  bool FieldDelegateIsVisible() { return m_is_visible; }

  void FieldDelegateHide() { m_is_visible = false; }

  void FieldDelegateShow() { m_is_visible = true; }

protected:
  bool m_is_visible = true;
};

typedef std::unique_ptr<FieldDelegate> FieldDelegateUP;

class TextFieldDelegate : public FieldDelegate {
public:
  TextFieldDelegate(const char *label, const char *content, bool required)
      : m_label(label), m_required(required) {
    if (content)
      m_content = content;
  }

  // Text fields are drawn as titled boxes of a single line, with a possible
  // error messages at the end.
  //
  // __[Label]___________
  // |                  |
  // |__________________|
  // - Error message if it exists.

  // The text field has a height of 3 lines. 2 lines for borders and 1 line for
  // the content.
  int GetFieldHeight() { return 3; }

  // The text field has a full height of 3 or 4 lines. 3 lines for the actual
  // field and an optional line for an error if it exists.
  int FieldDelegateGetHeight() override {
    int height = GetFieldHeight();
    if (FieldDelegateHasError())
      height++;
    return height;
  }

  // Get the cursor X position in the surface coordinate.
  int GetCursorXPosition() { return m_cursor_position - m_first_visibile_char; }

  int GetContentLength() { return m_content.length(); }

  void DrawContent(Surface &surface, bool is_selected) {
    UpdateScrolling(surface.GetWidth());

    surface.MoveCursor(0, 0);
    const char *text = m_content.c_str() + m_first_visibile_char;
    surface.PutCString(text, surface.GetWidth());

    // Highlight the cursor.
    surface.MoveCursor(GetCursorXPosition(), 0);
    if (is_selected)
      surface.AttributeOn(A_REVERSE);
    if (m_cursor_position == GetContentLength())
      // Cursor is past the last character. Highlight an empty space.
      surface.PutChar(' ');
    else
      surface.PutChar(m_content[m_cursor_position]);
    if (is_selected)
      surface.AttributeOff(A_REVERSE);
  }

  void DrawField(Surface &surface, bool is_selected) {
    surface.TitledBox(m_label.c_str());

    Rect content_bounds = surface.GetFrame();
    content_bounds.Inset(1, 1);
    Surface content_surface = surface.SubSurface(content_bounds);

    DrawContent(content_surface, is_selected);
  }

  void DrawError(Surface &surface) {
    if (!FieldDelegateHasError())
      return;
    surface.MoveCursor(0, 0);
    surface.AttributeOn(COLOR_PAIR(RedOnBlack));
    surface.PutChar(ACS_DIAMOND);
    surface.PutChar(' ');
    surface.PutCStringTruncated(1, GetError().c_str());
    surface.AttributeOff(COLOR_PAIR(RedOnBlack));
  }

  void FieldDelegateDraw(Surface &surface, bool is_selected) override {
    Rect frame = surface.GetFrame();
    Rect field_bounds, error_bounds;
    frame.HorizontalSplit(GetFieldHeight(), field_bounds, error_bounds);
    Surface field_surface = surface.SubSurface(field_bounds);
    Surface error_surface = surface.SubSurface(error_bounds);

    DrawField(field_surface, is_selected);
    DrawError(error_surface);
  }

  // Get the position of the last visible character.
  int GetLastVisibleCharPosition(int width) {
    int position = m_first_visibile_char + width - 1;
    return std::min(position, GetContentLength());
  }

  void UpdateScrolling(int width) {
    if (m_cursor_position < m_first_visibile_char) {
      m_first_visibile_char = m_cursor_position;
      return;
    }

    if (m_cursor_position > GetLastVisibleCharPosition(width))
      m_first_visibile_char = m_cursor_position - (width - 1);
  }

  // The cursor is allowed to move one character past the string.
  // m_cursor_position is in range [0, GetContentLength()].
  void MoveCursorRight() {
    if (m_cursor_position < GetContentLength())
      m_cursor_position++;
  }

  void MoveCursorLeft() {
    if (m_cursor_position > 0)
      m_cursor_position--;
  }

  void MoveCursorToStart() { m_cursor_position = 0; }

  void MoveCursorToEnd() { m_cursor_position = GetContentLength(); }

  void ScrollLeft() {
    if (m_first_visibile_char > 0)
      m_first_visibile_char--;
  }

  // Insert a character at the current cursor position and advance the cursor
  // position.
  void InsertChar(char character) {
    m_content.insert(m_cursor_position, 1, character);
    m_cursor_position++;
    ClearError();
  }

  // Remove the character before the cursor position, retreat the cursor
  // position, and scroll left.
  void RemovePreviousChar() {
    if (m_cursor_position == 0)
      return;

    m_content.erase(m_cursor_position - 1, 1);
    m_cursor_position--;
    ScrollLeft();
    ClearError();
  }

  // Remove the character after the cursor position.
  void RemoveNextChar() {
    if (m_cursor_position == GetContentLength())
      return;

    m_content.erase(m_cursor_position, 1);
    ClearError();
  }

  // Clear characters from the current cursor position to the end.
  void ClearToEnd() {
    m_content.erase(m_cursor_position);
    ClearError();
  }

  void Clear() {
    m_content.clear();
    m_cursor_position = 0;
    ClearError();
  }

  // True if the key represents a char that can be inserted in the field
  // content, false otherwise.
  virtual bool IsAcceptableChar(int key) {
    // The behavior of isprint is undefined when the value is not representable
    // as an unsigned char. So explicitly check for non-ascii key codes.
    if (key > 127)
      return false;
    return isprint(key);
  }

  HandleCharResult FieldDelegateHandleChar(int key) override {
    if (IsAcceptableChar(key)) {
      ClearError();
      InsertChar((char)key);
      return eKeyHandled;
    }

    switch (key) {
    case KEY_HOME:
    case KEY_CTRL_A:
      MoveCursorToStart();
      return eKeyHandled;
    case KEY_END:
    case KEY_CTRL_E:
      MoveCursorToEnd();
      return eKeyHandled;
    case KEY_RIGHT:
    case KEY_SF:
      MoveCursorRight();
      return eKeyHandled;
    case KEY_LEFT:
    case KEY_SR:
      MoveCursorLeft();
      return eKeyHandled;
    case KEY_BACKSPACE:
    case KEY_DELETE:
      RemovePreviousChar();
      return eKeyHandled;
    case KEY_DC:
      RemoveNextChar();
      return eKeyHandled;
    case KEY_EOL:
    case KEY_CTRL_K:
      ClearToEnd();
      return eKeyHandled;
    case KEY_DL:
    case KEY_CLEAR:
      Clear();
      return eKeyHandled;
    default:
      break;
    }
    return eKeyNotHandled;
  }

  bool FieldDelegateHasError() override { return !m_error.empty(); }

  void FieldDelegateExitCallback() override {
    if (!IsSpecified() && m_required)
      SetError("This field is required!");
  }

  bool IsSpecified() { return !m_content.empty(); }

  void ClearError() { m_error.clear(); }

  const std::string &GetError() { return m_error; }

  void SetError(const char *error) { m_error = error; }

  const std::string &GetText() { return m_content; }

  void SetText(const char *text) {
    if (text == nullptr) {
      m_content.clear();
      return;
    }
    m_content = text;
  }

protected:
  std::string m_label;
  bool m_required;
  // The position of the top left corner character of the border.
  std::string m_content;
  // The cursor position in the content string itself. Can be in the range
  // [0, GetContentLength()].
  int m_cursor_position = 0;
  // The index of the first visible character in the content.
  int m_first_visibile_char = 0;
  // Optional error message. If empty, field is considered to have no error.
  std::string m_error;
};

class IntegerFieldDelegate : public TextFieldDelegate {
public:
  IntegerFieldDelegate(const char *label, int content, bool required)
      : TextFieldDelegate(label, std::to_string(content).c_str(), required) {}

  // Only accept digits.
  bool IsAcceptableChar(int key) override { return isdigit(key); }

  // Returns the integer content of the field.
  int GetInteger() { return std::stoi(m_content); }
};

class FileFieldDelegate : public TextFieldDelegate {
public:
  FileFieldDelegate(const char *label, const char *content, bool need_to_exist,
                    bool required)
      : TextFieldDelegate(label, content, required),
        m_need_to_exist(need_to_exist) {}

  void FieldDelegateExitCallback() override {
    TextFieldDelegate::FieldDelegateExitCallback();
    if (!IsSpecified())
      return;

    if (!m_need_to_exist)
      return;

    FileSpec file = GetResolvedFileSpec();
    if (!FileSystem::Instance().Exists(file)) {
      SetError("File doesn't exist!");
      return;
    }
    if (FileSystem::Instance().IsDirectory(file)) {
      SetError("Not a file!");
      return;
    }
  }

  FileSpec GetFileSpec() {
    FileSpec file_spec(GetPath());
    return file_spec;
  }

  FileSpec GetResolvedFileSpec() {
    FileSpec file_spec(GetPath());
    FileSystem::Instance().Resolve(file_spec);
    return file_spec;
  }

  const std::string &GetPath() { return m_content; }

protected:
  bool m_need_to_exist;
};

class DirectoryFieldDelegate : public TextFieldDelegate {
public:
  DirectoryFieldDelegate(const char *label, const char *content,
                         bool need_to_exist, bool required)
      : TextFieldDelegate(label, content, required),
        m_need_to_exist(need_to_exist) {}

  void FieldDelegateExitCallback() override {
    TextFieldDelegate::FieldDelegateExitCallback();
    if (!IsSpecified())
      return;

    if (!m_need_to_exist)
      return;

    FileSpec file = GetResolvedFileSpec();
    if (!FileSystem::Instance().Exists(file)) {
      SetError("Directory doesn't exist!");
      return;
    }
    if (!FileSystem::Instance().IsDirectory(file)) {
      SetError("Not a directory!");
      return;
    }
  }

  FileSpec GetFileSpec() {
    FileSpec file_spec(GetPath());
    return file_spec;
  }

  FileSpec GetResolvedFileSpec() {
    FileSpec file_spec(GetPath());
    FileSystem::Instance().Resolve(file_spec);
    return file_spec;
  }

  const std::string &GetPath() { return m_content; }

protected:
  bool m_need_to_exist;
};

class ArchFieldDelegate : public TextFieldDelegate {
public:
  ArchFieldDelegate(const char *label, const char *content, bool required)
      : TextFieldDelegate(label, content, required) {}

  void FieldDelegateExitCallback() override {
    TextFieldDelegate::FieldDelegateExitCallback();
    if (!IsSpecified())
      return;

    if (!GetArchSpec().IsValid())
      SetError("Not a valid arch!");
  }

  const std::string &GetArchString() { return m_content; }

  ArchSpec GetArchSpec() { return ArchSpec(GetArchString()); }
};

class BooleanFieldDelegate : public FieldDelegate {
public:
  BooleanFieldDelegate(const char *label, bool content)
      : m_label(label), m_content(content) {}

  // Boolean fields are drawn as checkboxes.
  //
  // [X] Label  or [ ] Label

  // Boolean fields are have a single line.
  int FieldDelegateGetHeight() override { return 1; }

  void FieldDelegateDraw(Surface &surface, bool is_selected) override {
    surface.MoveCursor(0, 0);
    surface.PutChar('[');
    if (is_selected)
      surface.AttributeOn(A_REVERSE);
    surface.PutChar(m_content ? ACS_DIAMOND : ' ');
    if (is_selected)
      surface.AttributeOff(A_REVERSE);
    surface.PutChar(']');
    surface.PutChar(' ');
    surface.PutCString(m_label.c_str());
  }

  void ToggleContent() { m_content = !m_content; }

  void SetContentToTrue() { m_content = true; }

  void SetContentToFalse() { m_content = false; }

  HandleCharResult FieldDelegateHandleChar(int key) override {
    switch (key) {
    case 't':
    case '1':
      SetContentToTrue();
      return eKeyHandled;
    case 'f':
    case '0':
      SetContentToFalse();
      return eKeyHandled;
    case ' ':
    case '\r':
    case '\n':
    case KEY_ENTER:
      ToggleContent();
      return eKeyHandled;
    default:
      break;
    }
    return eKeyNotHandled;
  }

  // Returns the boolean content of the field.
  bool GetBoolean() { return m_content; }

protected:
  std::string m_label;
  bool m_content;
};

class ChoicesFieldDelegate : public FieldDelegate {
public:
  ChoicesFieldDelegate(const char *label, int number_of_visible_choices,
                       std::vector<std::string> choices)
      : m_label(label), m_number_of_visible_choices(number_of_visible_choices),
        m_choices(choices) {}

  // Choices fields are drawn as titles boxses of a number of visible choices.
  // The rest of the choices become visible as the user scroll. The selected
  // choice is denoted by a diamond as the first character.
  //
  // __[Label]___________
  // |-Choice 1         |
  // | Choice 2         |
  // | Choice 3         |
  // |__________________|

  // Choices field have two border characters plus the number of visible
  // choices.
  int FieldDelegateGetHeight() override {
    return m_number_of_visible_choices + 2;
  }

  int GetNumberOfChoices() { return m_choices.size(); }

  // Get the index of the last visible choice.
  int GetLastVisibleChoice() {
    int index = m_first_visibile_choice + m_number_of_visible_choices;
    return std::min(index, GetNumberOfChoices()) - 1;
  }

  void DrawContent(Surface &surface, bool is_selected) {
    int choices_to_draw = GetLastVisibleChoice() - m_first_visibile_choice + 1;
    for (int i = 0; i < choices_to_draw; i++) {
      surface.MoveCursor(0, i);
      int current_choice = m_first_visibile_choice + i;
      const char *text = m_choices[current_choice].c_str();
      bool highlight = is_selected && current_choice == m_choice;
      if (highlight)
        surface.AttributeOn(A_REVERSE);
      surface.PutChar(current_choice == m_choice ? ACS_DIAMOND : ' ');
      surface.PutCString(text);
      if (highlight)
        surface.AttributeOff(A_REVERSE);
    }
  }

  void FieldDelegateDraw(Surface &surface, bool is_selected) override {
    UpdateScrolling();

    surface.TitledBox(m_label.c_str());

    Rect content_bounds = surface.GetFrame();
    content_bounds.Inset(1, 1);
    Surface content_surface = surface.SubSurface(content_bounds);

    DrawContent(content_surface, is_selected);
  }

  void SelectPrevious() {
    if (m_choice > 0)
      m_choice--;
  }

  void SelectNext() {
    if (m_choice < GetNumberOfChoices() - 1)
      m_choice++;
  }

  void UpdateScrolling() {
    if (m_choice > GetLastVisibleChoice()) {
      m_first_visibile_choice = m_choice - (m_number_of_visible_choices - 1);
      return;
    }

    if (m_choice < m_first_visibile_choice)
      m_first_visibile_choice = m_choice;
  }

  HandleCharResult FieldDelegateHandleChar(int key) override {
    switch (key) {
    case KEY_UP:
      SelectPrevious();
      return eKeyHandled;
    case KEY_DOWN:
      SelectNext();
      return eKeyHandled;
    default:
      break;
    }
    return eKeyNotHandled;
  }

  // Returns the content of the choice as a string.
  std::string GetChoiceContent() { return m_choices[m_choice]; }

  // Returns the index of the choice.
  int GetChoice() { return m_choice; }

  void SetChoice(llvm::StringRef choice) {
    for (int i = 0; i < GetNumberOfChoices(); i++) {
      if (choice == m_choices[i]) {
        m_choice = i;
        return;
      }
    }
  }

protected:
  std::string m_label;
  int m_number_of_visible_choices;
  std::vector<std::string> m_choices;
  // The index of the selected choice.
  int m_choice = 0;
  // The index of the first visible choice in the field.
  int m_first_visibile_choice = 0;
};

class PlatformPluginFieldDelegate : public ChoicesFieldDelegate {
public:
  PlatformPluginFieldDelegate(Debugger &debugger)
      : ChoicesFieldDelegate("Platform Plugin", 3, GetPossiblePluginNames()) {
    PlatformSP platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
    if (platform_sp)
      SetChoice(platform_sp->GetPluginName());
  }

  std::vector<std::string> GetPossiblePluginNames() {
    std::vector<std::string> names;
    size_t i = 0;
    for (llvm::StringRef name =
             PluginManager::GetPlatformPluginNameAtIndex(i++);
         !name.empty(); name = PluginManager::GetProcessPluginNameAtIndex(i++))
      names.push_back(name.str());
    return names;
  }

  std::string GetPluginName() {
    std::string plugin_name = GetChoiceContent();
    return plugin_name;
  }
};

class ProcessPluginFieldDelegate : public ChoicesFieldDelegate {
public:
  ProcessPluginFieldDelegate()
      : ChoicesFieldDelegate("Process Plugin", 3, GetPossiblePluginNames()) {}

  std::vector<std::string> GetPossiblePluginNames() {
    std::vector<std::string> names;
    names.push_back("<default>");

    size_t i = 0;
    for (llvm::StringRef name = PluginManager::GetProcessPluginNameAtIndex(i++);
         !name.empty(); name = PluginManager::GetProcessPluginNameAtIndex(i++))
      names.push_back(name.str());
    return names;
  }

  std::string GetPluginName() {
    std::string plugin_name = GetChoiceContent();
    if (plugin_name == "<default>")
      return "";
    return plugin_name;
  }
};

class LazyBooleanFieldDelegate : public ChoicesFieldDelegate {
public:
  LazyBooleanFieldDelegate(const char *label, const char *calculate_label)
      : ChoicesFieldDelegate(label, 3, GetPossibleOptions(calculate_label)) {}

  static constexpr const char *kNo = "No";
  static constexpr const char *kYes = "Yes";

  std::vector<std::string> GetPossibleOptions(const char *calculate_label) {
    std::vector<std::string> options;
    options.push_back(calculate_label);
    options.push_back(kYes);
    options.push_back(kNo);
    return options;
  }

  LazyBool GetLazyBoolean() {
    std::string choice = GetChoiceContent();
    if (choice == kNo)
      return eLazyBoolNo;
    else if (choice == kYes)
      return eLazyBoolYes;
    else
      return eLazyBoolCalculate;
  }
};

template <class T> class ListFieldDelegate : public FieldDelegate {
public:
  ListFieldDelegate(const char *label, T default_field)
      : m_label(label), m_default_field(default_field),
        m_selection_type(SelectionType::NewButton) {}

  // Signify which element is selected. If a field or a remove button is
  // selected, then m_selection_index signifies the particular field that
  // is selected or the field that the remove button belongs to.
  enum class SelectionType { Field, RemoveButton, NewButton };

  // A List field is drawn as a titled box of a number of other fields of the
  // same type. Each field has a Remove button next to it that removes the
  // corresponding field. Finally, the last line contains a New button to add a
  // new field.
  //
  // __[Label]___________
  // | Field 0 [Remove] |
  // | Field 1 [Remove] |
  // | Field 2 [Remove] |
  // |      [New]       |
  // |__________________|

  // List fields have two lines for border characters, 1 line for the New
  // button, and the total height of the available fields.
  int FieldDelegateGetHeight() override {
    // 2 border characters.
    int height = 2;
    // Total height of the fields.
    for (int i = 0; i < GetNumberOfFields(); i++) {
      height += m_fields[i].FieldDelegateGetHeight();
    }
    // A line for the New button.
    height++;
    return height;
  }

  ScrollContext FieldDelegateGetScrollContext() override {
    int height = FieldDelegateGetHeight();
    if (m_selection_type == SelectionType::NewButton)
      return ScrollContext(height - 2, height - 1);

    FieldDelegate &field = m_fields[m_selection_index];
    ScrollContext context = field.FieldDelegateGetScrollContext();

    // Start at 1 because of the top border.
    int offset = 1;
    for (int i = 0; i < m_selection_index; i++) {
      offset += m_fields[i].FieldDelegateGetHeight();
    }
    context.Offset(offset);

    // If the scroll context is touching the top border, include it in the
    // context to show the label.
    if (context.start == 1)
      context.start--;

    // If the scroll context is touching the new button, include it as well as
    // the bottom border in the context.
    if (context.end == height - 3)
      context.end += 2;

    return context;
  }

  void DrawRemoveButton(Surface &surface, int highlight) {
    surface.MoveCursor(1, surface.GetHeight() / 2);
    if (highlight)
      surface.AttributeOn(A_REVERSE);
    surface.PutCString("[Remove]");
    if (highlight)
      surface.AttributeOff(A_REVERSE);
  }

  void DrawFields(Surface &surface, bool is_selected) {
    int line = 0;
    int width = surface.GetWidth();
    for (int i = 0; i < GetNumberOfFields(); i++) {
      int height = m_fields[i].FieldDelegateGetHeight();
      Rect bounds = Rect(Point(0, line), Size(width, height));
      Rect field_bounds, remove_button_bounds;
      bounds.VerticalSplit(bounds.size.width - sizeof(" [Remove]"),
                           field_bounds, remove_button_bounds);
      Surface field_surface = surface.SubSurface(field_bounds);
      Surface remove_button_surface = surface.SubSurface(remove_button_bounds);

      bool is_element_selected = m_selection_index == i && is_selected;
      bool is_field_selected =
          is_element_selected && m_selection_type == SelectionType::Field;
      bool is_remove_button_selected =
          is_element_selected &&
          m_selection_type == SelectionType::RemoveButton;
      m_fields[i].FieldDelegateDraw(field_surface, is_field_selected);
      DrawRemoveButton(remove_button_surface, is_remove_button_selected);

      line += height;
    }
  }

  void DrawNewButton(Surface &surface, bool is_selected) {
    const char *button_text = "[New]";
    int x = (surface.GetWidth() - sizeof(button_text) - 1) / 2;
    surface.MoveCursor(x, 0);
    bool highlight =
        is_selected && m_selection_type == SelectionType::NewButton;
    if (highlight)
      surface.AttributeOn(A_REVERSE);
    surface.PutCString(button_text);
    if (highlight)
      surface.AttributeOff(A_REVERSE);
  }

  void FieldDelegateDraw(Surface &surface, bool is_selected) override {
    surface.TitledBox(m_label.c_str());

    Rect content_bounds = surface.GetFrame();
    content_bounds.Inset(1, 1);
    Rect fields_bounds, new_button_bounds;
    content_bounds.HorizontalSplit(content_bounds.size.height - 1,
                                   fields_bounds, new_button_bounds);
    Surface fields_surface = surface.SubSurface(fields_bounds);
    Surface new_button_surface = surface.SubSurface(new_button_bounds);

    DrawFields(fields_surface, is_selected);
    DrawNewButton(new_button_surface, is_selected);
  }

  void AddNewField() {
    m_fields.push_back(m_default_field);
    m_selection_index = GetNumberOfFields() - 1;
    m_selection_type = SelectionType::Field;
    FieldDelegate &field = m_fields[m_selection_index];
    field.FieldDelegateSelectFirstElement();
  }

  void RemoveField() {
    m_fields.erase(m_fields.begin() + m_selection_index);
    if (m_selection_index != 0)
      m_selection_index--;

    if (GetNumberOfFields() > 0) {
      m_selection_type = SelectionType::Field;
      FieldDelegate &field = m_fields[m_selection_index];
      field.FieldDelegateSelectFirstElement();
    } else
      m_selection_type = SelectionType::NewButton;
  }

  HandleCharResult SelectNext(int key) {
    if (m_selection_type == SelectionType::NewButton)
      return eKeyNotHandled;

    if (m_selection_type == SelectionType::RemoveButton) {
      if (m_selection_index == GetNumberOfFields() - 1) {
        m_selection_type = SelectionType::NewButton;
        return eKeyHandled;
      }
      m_selection_index++;
      m_selection_type = SelectionType::Field;
      FieldDelegate &next_field = m_fields[m_selection_index];
      next_field.FieldDelegateSelectFirstElement();
      return eKeyHandled;
    }

    FieldDelegate &field = m_fields[m_selection_index];
    if (!field.FieldDelegateOnLastOrOnlyElement()) {
      return field.FieldDelegateHandleChar(key);
    }

    field.FieldDelegateExitCallback();

    m_selection_type = SelectionType::RemoveButton;
    return eKeyHandled;
  }

  HandleCharResult SelectPrevious(int key) {
    if (FieldDelegateOnFirstOrOnlyElement())
      return eKeyNotHandled;

    if (m_selection_type == SelectionType::RemoveButton) {
      m_selection_type = SelectionType::Field;
      FieldDelegate &field = m_fields[m_selection_index];
      field.FieldDelegateSelectLastElement();
      return eKeyHandled;
    }

    if (m_selection_type == SelectionType::NewButton) {
      m_selection_type = SelectionType::RemoveButton;
      m_selection_index = GetNumberOfFields() - 1;
      return eKeyHandled;
    }

    FieldDelegate &field = m_fields[m_selection_index];
    if (!field.FieldDelegateOnFirstOrOnlyElement()) {
      return field.FieldDelegateHandleChar(key);
    }

    field.FieldDelegateExitCallback();

    m_selection_type = SelectionType::RemoveButton;
    m_selection_index--;
    return eKeyHandled;
  }

  // If the last element of the field is selected and it didn't handle the key.
  // Select the next field or new button if the selected field is the last one.
  HandleCharResult SelectNextInList(int key) {
    assert(m_selection_type == SelectionType::Field);

    FieldDelegate &field = m_fields[m_selection_index];
    if (field.FieldDelegateHandleChar(key) == eKeyHandled)
      return eKeyHandled;

    if (!field.FieldDelegateOnLastOrOnlyElement())
      return eKeyNotHandled;

    field.FieldDelegateExitCallback();

    if (m_selection_index == GetNumberOfFields() - 1) {
      m_selection_type = SelectionType::NewButton;
      return eKeyHandled;
    }

    m_selection_index++;
    FieldDelegate &next_field = m_fields[m_selection_index];
    next_field.FieldDelegateSelectFirstElement();
    return eKeyHandled;
  }

  HandleCharResult FieldDelegateHandleChar(int key) override {
    switch (key) {
    case '\r':
    case '\n':
    case KEY_ENTER:
      switch (m_selection_type) {
      case SelectionType::NewButton:
        AddNewField();
        return eKeyHandled;
      case SelectionType::RemoveButton:
        RemoveField();
        return eKeyHandled;
      case SelectionType::Field:
        return SelectNextInList(key);
      }
      break;
    case '\t':
      return SelectNext(key);
    case KEY_SHIFT_TAB:
      return SelectPrevious(key);
    default:
      break;
    }

    // If the key wasn't handled and one of the fields is selected, pass the key
    // to that field.
    if (m_selection_type == SelectionType::Field) {
      return m_fields[m_selection_index].FieldDelegateHandleChar(key);
    }

    return eKeyNotHandled;
  }

  bool FieldDelegateOnLastOrOnlyElement() override {
    if (m_selection_type == SelectionType::NewButton) {
      return true;
    }
    return false;
  }

  bool FieldDelegateOnFirstOrOnlyElement() override {
    if (m_selection_type == SelectionType::NewButton &&
        GetNumberOfFields() == 0)
      return true;

    if (m_selection_type == SelectionType::Field && m_selection_index == 0) {
      FieldDelegate &field = m_fields[m_selection_index];
      return field.FieldDelegateOnFirstOrOnlyElement();
    }

    return false;
  }

  void FieldDelegateSelectFirstElement() override {
    if (GetNumberOfFields() == 0) {
      m_selection_type = SelectionType::NewButton;
      return;
    }

    m_selection_type = SelectionType::Field;
    m_selection_index = 0;
  }

  void FieldDelegateSelectLastElement() override {
    m_selection_type = SelectionType::NewButton;
  }

  int GetNumberOfFields() { return m_fields.size(); }

  // Returns the form delegate at the current index.
  T &GetField(int index) { return m_fields[index]; }

protected:
  std::string m_label;
  // The default field delegate instance from which new field delegates will be
  // created though a copy.
  T m_default_field;
  std::vector<T> m_fields;
  int m_selection_index = 0;
  // See SelectionType class enum.
  SelectionType m_selection_type;
};

class ArgumentsFieldDelegate : public ListFieldDelegate<TextFieldDelegate> {
public:
  ArgumentsFieldDelegate()
      : ListFieldDelegate("Arguments",
                          TextFieldDelegate("Argument", "", false)) {}

  Args GetArguments() {
    Args arguments;
    for (int i = 0; i < GetNumberOfFields(); i++) {
      arguments.AppendArgument(GetField(i).GetText());
    }
    return arguments;
  }

  void AddArguments(const Args &arguments) {
    for (size_t i = 0; i < arguments.GetArgumentCount(); i++) {
      AddNewField();
      TextFieldDelegate &field = GetField(GetNumberOfFields() - 1);
      field.SetText(arguments.GetArgumentAtIndex(i));
    }
  }
};

template <class KeyFieldDelegateType, class ValueFieldDelegateType>
class MappingFieldDelegate : public FieldDelegate {
public:
  MappingFieldDelegate(KeyFieldDelegateType key_field,
                       ValueFieldDelegateType value_field)
      : m_key_field(key_field), m_value_field(value_field),
        m_selection_type(SelectionType::Key) {}

  // Signify which element is selected. The key field or its value field.
  enum class SelectionType { Key, Value };

  // A mapping field is drawn as two text fields with a right arrow in between.
  // The first field stores the key of the mapping and the second stores the
  // value if the mapping.
  //
  // __[Key]_____________   __[Value]___________
  // |                  | > |                  |
  // |__________________|   |__________________|
  // - Error message if it exists.

  // The mapping field has a height that is equal to the maximum height between
  // the key and value fields.
  int FieldDelegateGetHeight() override {
    return std::max(m_key_field.FieldDelegateGetHeight(),
                    m_value_field.FieldDelegateGetHeight());
  }

  void DrawArrow(Surface &surface) {
    surface.MoveCursor(0, 1);
    surface.PutChar(ACS_RARROW);
  }

  void FieldDelegateDraw(Surface &surface, bool is_selected) override {
    Rect bounds = surface.GetFrame();
    Rect key_field_bounds, arrow_and_value_field_bounds;
    bounds.VerticalSplit(bounds.size.width / 2, key_field_bounds,
                         arrow_and_value_field_bounds);
    Rect arrow_bounds, value_field_bounds;
    arrow_and_value_field_bounds.VerticalSplit(1, arrow_bounds,
                                               value_field_bounds);

    Surface key_field_surface = surface.SubSurface(key_field_bounds);
    Surface arrow_surface = surface.SubSurface(arrow_bounds);
    Surface value_field_surface = surface.SubSurface(value_field_bounds);

    bool key_is_selected =
        m_selection_type == SelectionType::Key && is_selected;
    m_key_field.FieldDelegateDraw(key_field_surface, key_is_selected);
    DrawArrow(arrow_surface);
    bool value_is_selected =
        m_selection_type == SelectionType::Value && is_selected;
    m_value_field.FieldDelegateDraw(value_field_surface, value_is_selected);
  }

  HandleCharResult SelectNext(int key) {
    if (FieldDelegateOnLastOrOnlyElement())
      return eKeyNotHandled;

    if (!m_key_field.FieldDelegateOnLastOrOnlyElement()) {
      return m_key_field.FieldDelegateHandleChar(key);
    }

    m_key_field.FieldDelegateExitCallback();
    m_selection_type = SelectionType::Value;
    m_value_field.FieldDelegateSelectFirstElement();
    return eKeyHandled;
  }

  HandleCharResult SelectPrevious(int key) {
    if (FieldDelegateOnFirstOrOnlyElement())
      return eKeyNotHandled;

    if (!m_value_field.FieldDelegateOnFirstOrOnlyElement()) {
      return m_value_field.FieldDelegateHandleChar(key);
    }

    m_value_field.FieldDelegateExitCallback();
    m_selection_type = SelectionType::Key;
    m_key_field.FieldDelegateSelectLastElement();
    return eKeyHandled;
  }

  // If the value field is selected, pass the key to it. If the key field is
  // selected, its last element is selected, and it didn't handle the key, then
  // select its corresponding value field.
  HandleCharResult SelectNextField(int key) {
    if (m_selection_type == SelectionType::Value) {
      return m_value_field.FieldDelegateHandleChar(key);
    }

    if (m_key_field.FieldDelegateHandleChar(key) == eKeyHandled)
      return eKeyHandled;

    if (!m_key_field.FieldDelegateOnLastOrOnlyElement())
      return eKeyNotHandled;

    m_key_field.FieldDelegateExitCallback();
    m_selection_type = SelectionType::Value;
    m_value_field.FieldDelegateSelectFirstElement();
    return eKeyHandled;
  }

  HandleCharResult FieldDelegateHandleChar(int key) override {
    switch (key) {
    case KEY_RETURN:
      return SelectNextField(key);
    case '\t':
      return SelectNext(key);
    case KEY_SHIFT_TAB:
      return SelectPrevious(key);
    default:
      break;
    }

    // If the key wasn't handled, pass the key to the selected field.
    if (m_selection_type == SelectionType::Key)
      return m_key_field.FieldDelegateHandleChar(key);
    else
      return m_value_field.FieldDelegateHandleChar(key);

    return eKeyNotHandled;
  }

  bool FieldDelegateOnFirstOrOnlyElement() override {
    return m_selection_type == SelectionType::Key;
  }

  bool FieldDelegateOnLastOrOnlyElement() override {
    return m_selection_type == SelectionType::Value;
  }

  void FieldDelegateSelectFirstElement() override {
    m_selection_type = SelectionType::Key;
  }

  void FieldDelegateSelectLastElement() override {
    m_selection_type = SelectionType::Value;
  }

  bool FieldDelegateHasError() override {
    return m_key_field.FieldDelegateHasError() ||
           m_value_field.FieldDelegateHasError();
  }

  KeyFieldDelegateType &GetKeyField() { return m_key_field; }

  ValueFieldDelegateType &GetValueField() { return m_value_field; }

protected:
  KeyFieldDelegateType m_key_field;
  ValueFieldDelegateType m_value_field;
  // See SelectionType class enum.
  SelectionType m_selection_type;
};

class EnvironmentVariableNameFieldDelegate : public TextFieldDelegate {
public:
  EnvironmentVariableNameFieldDelegate(const char *content)
      : TextFieldDelegate("Name", content, true) {}

  // Environment variable names can't contain an equal sign.
  bool IsAcceptableChar(int key) override {
    return TextFieldDelegate::IsAcceptableChar(key) && key != '=';
  }

  const std::string &GetName() { return m_content; }
};

class EnvironmentVariableFieldDelegate
    : public MappingFieldDelegate<EnvironmentVariableNameFieldDelegate,
                                  TextFieldDelegate> {
public:
  EnvironmentVariableFieldDelegate()
      : MappingFieldDelegate(
            EnvironmentVariableNameFieldDelegate(""),
            TextFieldDelegate("Value", "", /*required=*/false)) {}

  const std::string &GetName() { return GetKeyField().GetName(); }

  const std::string &GetValue() { return GetValueField().GetText(); }

  void SetName(const char *name) { return GetKeyField().SetText(name); }

  void SetValue(const char *value) { return GetValueField().SetText(value); }
};

class EnvironmentVariableListFieldDelegate
    : public ListFieldDelegate<EnvironmentVariableFieldDelegate> {
public:
  EnvironmentVariableListFieldDelegate(const char *label)
      : ListFieldDelegate(label, EnvironmentVariableFieldDelegate()) {}

  Environment GetEnvironment() {
    Environment environment;
    for (int i = 0; i < GetNumberOfFields(); i++) {
      environment.insert(
          std::make_pair(GetField(i).GetName(), GetField(i).GetValue()));
    }
    return environment;
  }

  void AddEnvironmentVariables(const Environment &environment) {
    for (auto &variable : environment) {
      AddNewField();
      EnvironmentVariableFieldDelegate &field =
          GetField(GetNumberOfFields() - 1);
      field.SetName(variable.getKey().str().c_str());
      field.SetValue(variable.getValue().c_str());
    }
  }
};

class FormAction {
public:
  FormAction(const char *label, std::function<void(Window &)> action)
      : m_action(action) {
    if (label)
      m_label = label;
  }

  // Draw a centered [Label].
  void Draw(Surface &surface, bool is_selected) {
    int x = (surface.GetWidth() - m_label.length()) / 2;
    surface.MoveCursor(x, 0);
    if (is_selected)
      surface.AttributeOn(A_REVERSE);
    surface.PutChar('[');
    surface.PutCString(m_label.c_str());
    surface.PutChar(']');
    if (is_selected)
      surface.AttributeOff(A_REVERSE);
  }

  void Execute(Window &window) { m_action(window); }

  const std::string &GetLabel() { return m_label; }

protected:
  std::string m_label;
  std::function<void(Window &)> m_action;
};

class FormDelegate {
public:
  FormDelegate() = default;

  virtual ~FormDelegate() = default;

  virtual std::string GetName() = 0;

  virtual void UpdateFieldsVisibility() {}

  FieldDelegate *GetField(uint32_t field_index) {
    if (field_index < m_fields.size())
      return m_fields[field_index].get();
    return nullptr;
  }

  FormAction &GetAction(int action_index) { return m_actions[action_index]; }

  int GetNumberOfFields() { return m_fields.size(); }

  int GetNumberOfActions() { return m_actions.size(); }

  bool HasError() { return !m_error.empty(); }

  void ClearError() { m_error.clear(); }

  const std::string &GetError() { return m_error; }

  void SetError(const char *error) { m_error = error; }

  // If all fields are valid, true is returned. Otherwise, an error message is
  // set and false is returned. This method is usually called at the start of an
  // action that requires valid fields.
  bool CheckFieldsValidity() {
    for (int i = 0; i < GetNumberOfFields(); i++) {
      GetField(i)->FieldDelegateExitCallback();
      if (GetField(i)->FieldDelegateHasError()) {
        SetError("Some fields are invalid!");
        return false;
      }
    }
    return true;
  }

  // Factory methods to create and add fields of specific types.

  TextFieldDelegate *AddTextField(const char *label, const char *content,
                                  bool required) {
    TextFieldDelegate *delegate =
        new TextFieldDelegate(label, content, required);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  FileFieldDelegate *AddFileField(const char *label, const char *content,
                                  bool need_to_exist, bool required) {
    FileFieldDelegate *delegate =
        new FileFieldDelegate(label, content, need_to_exist, required);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  DirectoryFieldDelegate *AddDirectoryField(const char *label,
                                            const char *content,
                                            bool need_to_exist, bool required) {
    DirectoryFieldDelegate *delegate =
        new DirectoryFieldDelegate(label, content, need_to_exist, required);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  ArchFieldDelegate *AddArchField(const char *label, const char *content,
                                  bool required) {
    ArchFieldDelegate *delegate =
        new ArchFieldDelegate(label, content, required);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  IntegerFieldDelegate *AddIntegerField(const char *label, int content,
                                        bool required) {
    IntegerFieldDelegate *delegate =
        new IntegerFieldDelegate(label, content, required);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  BooleanFieldDelegate *AddBooleanField(const char *label, bool content) {
    BooleanFieldDelegate *delegate = new BooleanFieldDelegate(label, content);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  LazyBooleanFieldDelegate *AddLazyBooleanField(const char *label,
                                                const char *calculate_label) {
    LazyBooleanFieldDelegate *delegate =
        new LazyBooleanFieldDelegate(label, calculate_label);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  ChoicesFieldDelegate *AddChoicesField(const char *label, int height,
                                        std::vector<std::string> choices) {
    ChoicesFieldDelegate *delegate =
        new ChoicesFieldDelegate(label, height, choices);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  PlatformPluginFieldDelegate *AddPlatformPluginField(Debugger &debugger) {
    PlatformPluginFieldDelegate *delegate =
        new PlatformPluginFieldDelegate(debugger);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  ProcessPluginFieldDelegate *AddProcessPluginField() {
    ProcessPluginFieldDelegate *delegate = new ProcessPluginFieldDelegate();
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  template <class T>
  ListFieldDelegate<T> *AddListField(const char *label, T default_field) {
    ListFieldDelegate<T> *delegate =
        new ListFieldDelegate<T>(label, default_field);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  ArgumentsFieldDelegate *AddArgumentsField() {
    ArgumentsFieldDelegate *delegate = new ArgumentsFieldDelegate();
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  template <class K, class V>
  MappingFieldDelegate<K, V> *AddMappingField(K key_field, V value_field) {
    MappingFieldDelegate<K, V> *delegate =
        new MappingFieldDelegate<K, V>(key_field, value_field);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  EnvironmentVariableNameFieldDelegate *
  AddEnvironmentVariableNameField(const char *content) {
    EnvironmentVariableNameFieldDelegate *delegate =
        new EnvironmentVariableNameFieldDelegate(content);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  EnvironmentVariableFieldDelegate *AddEnvironmentVariableField() {
    EnvironmentVariableFieldDelegate *delegate =
        new EnvironmentVariableFieldDelegate();
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  EnvironmentVariableListFieldDelegate *
  AddEnvironmentVariableListField(const char *label) {
    EnvironmentVariableListFieldDelegate *delegate =
        new EnvironmentVariableListFieldDelegate(label);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  // Factory methods for adding actions.

  void AddAction(const char *label, std::function<void(Window &)> action) {
    m_actions.push_back(FormAction(label, action));
  }

protected:
  std::vector<FieldDelegateUP> m_fields;
  std::vector<FormAction> m_actions;
  // Optional error message. If empty, form is considered to have no error.
  std::string m_error;
};

typedef std::shared_ptr<FormDelegate> FormDelegateSP;

class FormWindowDelegate : public WindowDelegate {
public:
  FormWindowDelegate(FormDelegateSP &delegate_sp) : m_delegate_sp(delegate_sp) {
    assert(m_delegate_sp->GetNumberOfActions() > 0);
    if (m_delegate_sp->GetNumberOfFields() > 0)
      m_selection_type = SelectionType::Field;
    else
      m_selection_type = SelectionType::Action;
  }

  // Signify which element is selected. If a field or an action is selected,
  // then m_selection_index signifies the particular field or action that is
  // selected.
  enum class SelectionType { Field, Action };

  // A form window is padded by one character from all sides. First, if an error
  // message exists, it is drawn followed by a separator. Then one or more
  // fields are drawn. Finally, all available actions are drawn on a single
  // line.
  //
  // ___<Form Name>_________________________________________________
  // |                                                             |
  // | - Error message if it exists.                               |
  // |-------------------------------------------------------------|
  // | Form elements here.                                         |
  // |                       Form actions here.                    |
  // |                                                             |
  // |______________________________________[Press Esc to cancel]__|
  //

  // One line for the error and another for the horizontal line.
  int GetErrorHeight() {
    if (m_delegate_sp->HasError())
      return 2;
    return 0;
  }

  // Actions span a single line.
  int GetActionsHeight() {
    if (m_delegate_sp->GetNumberOfActions() > 0)
      return 1;
    return 0;
  }

  // Get the total number of needed lines to draw the contents.
  int GetContentHeight() {
    int height = 0;
    height += GetErrorHeight();
    for (int i = 0; i < m_delegate_sp->GetNumberOfFields(); i++) {
      if (!m_delegate_sp->GetField(i)->FieldDelegateIsVisible())
        continue;
      height += m_delegate_sp->GetField(i)->FieldDelegateGetHeight();
    }
    height += GetActionsHeight();
    return height;
  }

  ScrollContext GetScrollContext() {
    if (m_selection_type == SelectionType::Action)
      return ScrollContext(GetContentHeight() - 1);

    FieldDelegate *field = m_delegate_sp->GetField(m_selection_index);
    ScrollContext context = field->FieldDelegateGetScrollContext();

    int offset = GetErrorHeight();
    for (int i = 0; i < m_selection_index; i++) {
      if (!m_delegate_sp->GetField(i)->FieldDelegateIsVisible())
        continue;
      offset += m_delegate_sp->GetField(i)->FieldDelegateGetHeight();
    }
    context.Offset(offset);

    // If the context is touching the error, include the error in the context as
    // well.
    if (context.start == GetErrorHeight())
      context.start = 0;

    return context;
  }

  void UpdateScrolling(Surface &surface) {
    ScrollContext context = GetScrollContext();
    int content_height = GetContentHeight();
    int surface_height = surface.GetHeight();
    int visible_height = std::min(content_height, surface_height);
    int last_visible_line = m_first_visible_line + visible_height - 1;

    // If the last visible line is bigger than the content, then it is invalid
    // and needs to be set to the last line in the content. This can happen when
    // a field has shrunk in height.
    if (last_visible_line > content_height - 1) {
      m_first_visible_line = content_height - visible_height;
    }

    if (context.start < m_first_visible_line) {
      m_first_visible_line = context.start;
      return;
    }

    if (context.end > last_visible_line) {
      m_first_visible_line = context.end - visible_height + 1;
    }
  }

  void DrawError(Surface &surface) {
    if (!m_delegate_sp->HasError())
      return;
    surface.MoveCursor(0, 0);
    surface.AttributeOn(COLOR_PAIR(RedOnBlack));
    surface.PutChar(ACS_DIAMOND);
    surface.PutChar(' ');
    surface.PutCStringTruncated(1, m_delegate_sp->GetError().c_str());
    surface.AttributeOff(COLOR_PAIR(RedOnBlack));

    surface.MoveCursor(0, 1);
    surface.HorizontalLine(surface.GetWidth());
  }

  void DrawFields(Surface &surface) {
    int line = 0;
    int width = surface.GetWidth();
    bool a_field_is_selected = m_selection_type == SelectionType::Field;
    for (int i = 0; i < m_delegate_sp->GetNumberOfFields(); i++) {
      FieldDelegate *field = m_delegate_sp->GetField(i);
      if (!field->FieldDelegateIsVisible())
        continue;
      bool is_field_selected = a_field_is_selected && m_selection_index == i;
      int height = field->FieldDelegateGetHeight();
      Rect bounds = Rect(Point(0, line), Size(width, height));
      Surface field_surface = surface.SubSurface(bounds);
      field->FieldDelegateDraw(field_surface, is_field_selected);
      line += height;
    }
  }

  void DrawActions(Surface &surface) {
    int number_of_actions = m_delegate_sp->GetNumberOfActions();
    int width = surface.GetWidth() / number_of_actions;
    bool an_action_is_selected = m_selection_type == SelectionType::Action;
    int x = 0;
    for (int i = 0; i < number_of_actions; i++) {
      bool is_action_selected = an_action_is_selected && m_selection_index == i;
      FormAction &action = m_delegate_sp->GetAction(i);
      Rect bounds = Rect(Point(x, 0), Size(width, 1));
      Surface action_surface = surface.SubSurface(bounds);
      action.Draw(action_surface, is_action_selected);
      x += width;
    }
  }

  void DrawElements(Surface &surface) {
    Rect frame = surface.GetFrame();
    Rect fields_bounds, actions_bounds;
    frame.HorizontalSplit(surface.GetHeight() - GetActionsHeight(),
                          fields_bounds, actions_bounds);
    Surface fields_surface = surface.SubSurface(fields_bounds);
    Surface actions_surface = surface.SubSurface(actions_bounds);

    DrawFields(fields_surface);
    DrawActions(actions_surface);
  }

  // Contents are first drawn on a pad. Then a subset of that pad is copied to
  // the derived window starting at the first visible line. This essentially
  // provides scrolling functionality.
  void DrawContent(Surface &surface) {
    UpdateScrolling(surface);

    int width = surface.GetWidth();
    int height = GetContentHeight();
    Pad pad = Pad(Size(width, height));

    Rect frame = pad.GetFrame();
    Rect error_bounds, elements_bounds;
    frame.HorizontalSplit(GetErrorHeight(), error_bounds, elements_bounds);
    Surface error_surface = pad.SubSurface(error_bounds);
    Surface elements_surface = pad.SubSurface(elements_bounds);

    DrawError(error_surface);
    DrawElements(elements_surface);

    int copy_height = std::min(surface.GetHeight(), pad.GetHeight());
    pad.CopyToSurface(surface, Point(0, m_first_visible_line), Point(),
                      Size(width, copy_height));
  }

  void DrawSubmitHint(Surface &surface, bool is_active) {
    surface.MoveCursor(2, surface.GetHeight() - 1);
    if (is_active)
      surface.AttributeOn(A_BOLD | COLOR_PAIR(BlackOnWhite));
    surface.Printf("[Press Alt+Enter to %s]",
                   m_delegate_sp->GetAction(0).GetLabel().c_str());
    if (is_active)
      surface.AttributeOff(A_BOLD | COLOR_PAIR(BlackOnWhite));
  }

  bool WindowDelegateDraw(Window &window, bool force) override {
    m_delegate_sp->UpdateFieldsVisibility();

    window.Erase();

    window.DrawTitleBox(m_delegate_sp->GetName().c_str(),
                        "Press Esc to Cancel");
    DrawSubmitHint(window, window.IsActive());

    Rect content_bounds = window.GetFrame();
    content_bounds.Inset(2, 2);
    Surface content_surface = window.SubSurface(content_bounds);

    DrawContent(content_surface);
    return true;
  }

  void SkipNextHiddenFields() {
    while (true) {
      if (m_delegate_sp->GetField(m_selection_index)->FieldDelegateIsVisible())
        return;

      if (m_selection_index == m_delegate_sp->GetNumberOfFields() - 1) {
        m_selection_type = SelectionType::Action;
        m_selection_index = 0;
        return;
      }

      m_selection_index++;
    }
  }

  HandleCharResult SelectNext(int key) {
    if (m_selection_type == SelectionType::Action) {
      if (m_selection_index < m_delegate_sp->GetNumberOfActions() - 1) {
        m_selection_index++;
        return eKeyHandled;
      }

      m_selection_index = 0;
      m_selection_type = SelectionType::Field;
      SkipNextHiddenFields();
      if (m_selection_type == SelectionType::Field) {
        FieldDelegate *next_field = m_delegate_sp->GetField(m_selection_index);
        next_field->FieldDelegateSelectFirstElement();
      }
      return eKeyHandled;
    }

    FieldDelegate *field = m_delegate_sp->GetField(m_selection_index);
    if (!field->FieldDelegateOnLastOrOnlyElement()) {
      return field->FieldDelegateHandleChar(key);
    }

    field->FieldDelegateExitCallback();

    if (m_selection_index == m_delegate_sp->GetNumberOfFields() - 1) {
      m_selection_type = SelectionType::Action;
      m_selection_index = 0;
      return eKeyHandled;
    }

    m_selection_index++;
    SkipNextHiddenFields();

    if (m_selection_type == SelectionType::Field) {
      FieldDelegate *next_field = m_delegate_sp->GetField(m_selection_index);
      next_field->FieldDelegateSelectFirstElement();
    }

    return eKeyHandled;
  }

  void SkipPreviousHiddenFields() {
    while (true) {
      if (m_delegate_sp->GetField(m_selection_index)->FieldDelegateIsVisible())
        return;

      if (m_selection_index == 0) {
        m_selection_type = SelectionType::Action;
        m_selection_index = 0;
        return;
      }

      m_selection_index--;
    }
  }

  HandleCharResult SelectPrevious(int key) {
    if (m_selection_type == SelectionType::Action) {
      if (m_selection_index > 0) {
        m_selection_index--;
        return eKeyHandled;
      }
      m_selection_index = m_delegate_sp->GetNumberOfFields() - 1;
      m_selection_type = SelectionType::Field;
      SkipPreviousHiddenFields();
      if (m_selection_type == SelectionType::Field) {
        FieldDelegate *previous_field =
            m_delegate_sp->GetField(m_selection_index);
        previous_field->FieldDelegateSelectLastElement();
      }
      return eKeyHandled;
    }

    FieldDelegate *field = m_delegate_sp->GetField(m_selection_index);
    if (!field->FieldDelegateOnFirstOrOnlyElement()) {
      return field->FieldDelegateHandleChar(key);
    }

    field->FieldDelegateExitCallback();

    if (m_selection_index == 0) {
      m_selection_type = SelectionType::Action;
      m_selection_index = m_delegate_sp->GetNumberOfActions() - 1;
      return eKeyHandled;
    }

    m_selection_index--;
    SkipPreviousHiddenFields();

    if (m_selection_type == SelectionType::Field) {
      FieldDelegate *previous_field =
          m_delegate_sp->GetField(m_selection_index);
      previous_field->FieldDelegateSelectLastElement();
    }

    return eKeyHandled;
  }

  void ExecuteAction(Window &window, int index) {
    FormAction &action = m_delegate_sp->GetAction(index);
    action.Execute(window);
    if (m_delegate_sp->HasError()) {
      m_first_visible_line = 0;
      m_selection_index = 0;
      m_selection_type = SelectionType::Field;
    }
  }

  // Always return eKeyHandled to absorb all events since forms are always
  // added as pop-ups that should take full control until canceled or submitted.
  HandleCharResult WindowDelegateHandleChar(Window &window, int key) override {
    switch (key) {
    case '\r':
    case '\n':
    case KEY_ENTER:
      if (m_selection_type == SelectionType::Action) {
        ExecuteAction(window, m_selection_index);
        return eKeyHandled;
      }
      break;
    case KEY_ALT_ENTER:
      ExecuteAction(window, 0);
      return eKeyHandled;
    case '\t':
      SelectNext(key);
      return eKeyHandled;
    case KEY_SHIFT_TAB:
      SelectPrevious(key);
      return eKeyHandled;
    case KEY_ESCAPE:
      window.GetParent()->RemoveSubWindow(&window);
      return eKeyHandled;
    default:
      break;
    }

    // If the key wasn't handled and one of the fields is selected, pass the key
    // to that field.
    if (m_selection_type == SelectionType::Field) {
      FieldDelegate *field = m_delegate_sp->GetField(m_selection_index);
      if (field->FieldDelegateHandleChar(key) == eKeyHandled)
        return eKeyHandled;
    }

    // If the key wasn't handled by the possibly selected field, handle some
    // extra keys for navigation.
    switch (key) {
    case KEY_DOWN:
      SelectNext(key);
      return eKeyHandled;
    case KEY_UP:
      SelectPrevious(key);
      return eKeyHandled;
    default:
      break;
    }

    return eKeyHandled;
  }

protected:
  FormDelegateSP m_delegate_sp;
  // The index of the currently selected SelectionType.
  int m_selection_index = 0;
  // See SelectionType class enum.
  SelectionType m_selection_type;
  // The first visible line from the pad.
  int m_first_visible_line = 0;
};

///////////////////////////
// Form Delegate Instances
///////////////////////////

class DetachOrKillProcessFormDelegate : public FormDelegate {
public:
  DetachOrKillProcessFormDelegate(Process *process) : m_process(process) {
    SetError("There is a running process, either detach or kill it.");

    m_keep_stopped_field =
        AddBooleanField("Keep process stopped when detaching.", false);

    AddAction("Detach", [this](Window &window) { Detach(window); });
    AddAction("Kill", [this](Window &window) { Kill(window); });
  }

  std::string GetName() override { return "Detach/Kill Process"; }

  void Kill(Window &window) {
    Status destroy_status(m_process->Destroy(false));
    if (destroy_status.Fail()) {
      SetError("Failed to kill process.");
      return;
    }
    window.GetParent()->RemoveSubWindow(&window);
  }

  void Detach(Window &window) {
    Status detach_status(m_process->Detach(m_keep_stopped_field->GetBoolean()));
    if (detach_status.Fail()) {
      SetError("Failed to detach from process.");
      return;
    }
    window.GetParent()->RemoveSubWindow(&window);
  }

protected:
  Process *m_process;
  BooleanFieldDelegate *m_keep_stopped_field;
};

class ProcessAttachFormDelegate : public FormDelegate {
public:
  ProcessAttachFormDelegate(Debugger &debugger, WindowSP main_window_sp)
      : m_debugger(debugger), m_main_window_sp(main_window_sp) {
    std::vector<std::string> types;
    types.push_back(std::string("Name"));
    types.push_back(std::string("PID"));
    m_type_field = AddChoicesField("Attach By", 2, types);
    m_pid_field = AddIntegerField("PID", 0, true);
    m_name_field =
        AddTextField("Process Name", GetDefaultProcessName().c_str(), true);
    m_continue_field = AddBooleanField("Continue once attached.", false);
    m_wait_for_field = AddBooleanField("Wait for process to launch.", false);
    m_include_existing_field =
        AddBooleanField("Include existing processes.", false);
    m_show_advanced_field = AddBooleanField("Show advanced settings.", false);
    m_plugin_field = AddProcessPluginField();

    AddAction("Attach", [this](Window &window) { Attach(window); });
  }

  std::string GetName() override { return "Attach Process"; }

  void UpdateFieldsVisibility() override {
    if (m_type_field->GetChoiceContent() == "Name") {
      m_pid_field->FieldDelegateHide();
      m_name_field->FieldDelegateShow();
      m_wait_for_field->FieldDelegateShow();
      if (m_wait_for_field->GetBoolean())
        m_include_existing_field->FieldDelegateShow();
      else
        m_include_existing_field->FieldDelegateHide();
    } else {
      m_pid_field->FieldDelegateShow();
      m_name_field->FieldDelegateHide();
      m_wait_for_field->FieldDelegateHide();
      m_include_existing_field->FieldDelegateHide();
    }
    if (m_show_advanced_field->GetBoolean())
      m_plugin_field->FieldDelegateShow();
    else
      m_plugin_field->FieldDelegateHide();
  }

  // Get the basename of the target's main executable if available, empty string
  // otherwise.
  std::string GetDefaultProcessName() {
    Target *target = m_debugger.GetSelectedTarget().get();
    if (target == nullptr)
      return "";

    ModuleSP module_sp = target->GetExecutableModule();
    if (!module_sp->IsExecutable())
      return "";

    return module_sp->GetFileSpec().GetFilename().AsCString();
  }

  bool StopRunningProcess() {
    ExecutionContext exe_ctx =
        m_debugger.GetCommandInterpreter().GetExecutionContext();

    if (!exe_ctx.HasProcessScope())
      return false;

    Process *process = exe_ctx.GetProcessPtr();
    if (!(process && process->IsAlive()))
      return false;

    FormDelegateSP form_delegate_sp =
        FormDelegateSP(new DetachOrKillProcessFormDelegate(process));
    Rect bounds = m_main_window_sp->GetCenteredRect(85, 8);
    WindowSP form_window_sp = m_main_window_sp->CreateSubWindow(
        form_delegate_sp->GetName().c_str(), bounds, true);
    WindowDelegateSP window_delegate_sp =
        WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
    form_window_sp->SetDelegate(window_delegate_sp);

    return true;
  }

  Target *GetTarget() {
    Target *target = m_debugger.GetSelectedTarget().get();

    if (target != nullptr)
      return target;

    TargetSP new_target_sp;
    m_debugger.GetTargetList().CreateTarget(
        m_debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);

    target = new_target_sp.get();

    if (target == nullptr)
      SetError("Failed to create target.");

    m_debugger.GetTargetList().SetSelectedTarget(new_target_sp);

    return target;
  }

  ProcessAttachInfo GetAttachInfo() {
    ProcessAttachInfo attach_info;
    attach_info.SetContinueOnceAttached(m_continue_field->GetBoolean());
    if (m_type_field->GetChoiceContent() == "Name") {
      attach_info.GetExecutableFile().SetFile(m_name_field->GetText(),
                                              FileSpec::Style::native);
      attach_info.SetWaitForLaunch(m_wait_for_field->GetBoolean());
      if (m_wait_for_field->GetBoolean())
        attach_info.SetIgnoreExisting(!m_include_existing_field->GetBoolean());
    } else {
      attach_info.SetProcessID(m_pid_field->GetInteger());
    }
    attach_info.SetProcessPluginName(m_plugin_field->GetPluginName());

    return attach_info;
  }

  void Attach(Window &window) {
    ClearError();

    bool all_fields_are_valid = CheckFieldsValidity();
    if (!all_fields_are_valid)
      return;

    bool process_is_running = StopRunningProcess();
    if (process_is_running)
      return;

    Target *target = GetTarget();
    if (HasError())
      return;

    StreamString stream;
    ProcessAttachInfo attach_info = GetAttachInfo();
    Status status = target->Attach(attach_info, &stream);

    if (status.Fail()) {
      SetError(status.AsCString());
      return;
    }

    ProcessSP process_sp(target->GetProcessSP());
    if (!process_sp) {
      SetError("Attached sucessfully but target has no process.");
      return;
    }

    if (attach_info.GetContinueOnceAttached())
      process_sp->Resume();

    window.GetParent()->RemoveSubWindow(&window);
  }

protected:
  Debugger &m_debugger;
  WindowSP m_main_window_sp;

  ChoicesFieldDelegate *m_type_field;
  IntegerFieldDelegate *m_pid_field;
  TextFieldDelegate *m_name_field;
  BooleanFieldDelegate *m_continue_field;
  BooleanFieldDelegate *m_wait_for_field;
  BooleanFieldDelegate *m_include_existing_field;
  BooleanFieldDelegate *m_show_advanced_field;
  ProcessPluginFieldDelegate *m_plugin_field;
};

class TargetCreateFormDelegate : public FormDelegate {
public:
  TargetCreateFormDelegate(Debugger &debugger) : m_debugger(debugger) {
    m_executable_field = AddFileField("Executable", "", /*need_to_exist=*/true,
                                      /*required=*/true);
    m_core_file_field = AddFileField("Core File", "", /*need_to_exist=*/true,
                                     /*required=*/false);
    m_symbol_file_field = AddFileField(
        "Symbol File", "", /*need_to_exist=*/true, /*required=*/false);
    m_show_advanced_field = AddBooleanField("Show advanced settings.", false);
    m_remote_file_field = AddFileField(
        "Remote File", "", /*need_to_exist=*/false, /*required=*/false);
    m_arch_field = AddArchField("Architecture", "", /*required=*/false);
    m_platform_field = AddPlatformPluginField(debugger);
    m_load_dependent_files_field =
        AddChoicesField("Load Dependents", 3, GetLoadDependentFilesChoices());

    AddAction("Create", [this](Window &window) { CreateTarget(window); });
  }

  std::string GetName() override { return "Create Target"; }

  void UpdateFieldsVisibility() override {
    if (m_show_advanced_field->GetBoolean()) {
      m_remote_file_field->FieldDelegateShow();
      m_arch_field->FieldDelegateShow();
      m_platform_field->FieldDelegateShow();
      m_load_dependent_files_field->FieldDelegateShow();
    } else {
      m_remote_file_field->FieldDelegateHide();
      m_arch_field->FieldDelegateHide();
      m_platform_field->FieldDelegateHide();
      m_load_dependent_files_field->FieldDelegateHide();
    }
  }

  static constexpr const char *kLoadDependentFilesNo = "No";
  static constexpr const char *kLoadDependentFilesYes = "Yes";
  static constexpr const char *kLoadDependentFilesExecOnly = "Executable only";

  std::vector<std::string> GetLoadDependentFilesChoices() {
    std::vector<std::string> load_dependents_options;
    load_dependents_options.push_back(kLoadDependentFilesExecOnly);
    load_dependents_options.push_back(kLoadDependentFilesYes);
    load_dependents_options.push_back(kLoadDependentFilesNo);
    return load_dependents_options;
  }

  LoadDependentFiles GetLoadDependentFiles() {
    std::string choice = m_load_dependent_files_field->GetChoiceContent();
    if (choice == kLoadDependentFilesNo)
      return eLoadDependentsNo;
    if (choice == kLoadDependentFilesYes)
      return eLoadDependentsYes;
    return eLoadDependentsDefault;
  }

  OptionGroupPlatform GetPlatformOptions() {
    OptionGroupPlatform platform_options(false);
    platform_options.SetPlatformName(m_platform_field->GetPluginName().c_str());
    return platform_options;
  }

  TargetSP GetTarget() {
    OptionGroupPlatform platform_options = GetPlatformOptions();
    TargetSP target_sp;
    Status status = m_debugger.GetTargetList().CreateTarget(
        m_debugger, m_executable_field->GetPath(),
        m_arch_field->GetArchString(), GetLoadDependentFiles(),
        &platform_options, target_sp);

    if (status.Fail()) {
      SetError(status.AsCString());
      return nullptr;
    }

    m_debugger.GetTargetList().SetSelectedTarget(target_sp);

    return target_sp;
  }

  void SetSymbolFile(TargetSP target_sp) {
    if (!m_symbol_file_field->IsSpecified())
      return;

    ModuleSP module_sp(target_sp->GetExecutableModule());
    if (!module_sp)
      return;

    module_sp->SetSymbolFileFileSpec(
        m_symbol_file_field->GetResolvedFileSpec());
  }

  void SetCoreFile(TargetSP target_sp) {
    if (!m_core_file_field->IsSpecified())
      return;

    FileSpec core_file_spec = m_core_file_field->GetResolvedFileSpec();

    FileSpec core_file_directory_spec;
    core_file_directory_spec.SetDirectory(core_file_spec.GetDirectory());
    target_sp->AppendExecutableSearchPaths(core_file_directory_spec);

    ProcessSP process_sp(target_sp->CreateProcess(
        m_debugger.GetListener(), llvm::StringRef(), &core_file_spec, false));

    if (!process_sp) {
      SetError("Unable to find process plug-in for core file!");
      return;
    }

    Status status = process_sp->LoadCore();
    if (status.Fail()) {
      SetError("Can't find plug-in for core file!");
      return;
    }
  }

  void SetRemoteFile(TargetSP target_sp) {
    if (!m_remote_file_field->IsSpecified())
      return;

    ModuleSP module_sp(target_sp->GetExecutableModule());
    if (!module_sp)
      return;

    FileSpec remote_file_spec = m_remote_file_field->GetFileSpec();
    module_sp->SetPlatformFileSpec(remote_file_spec);
  }

  void RemoveTarget(TargetSP target_sp) {
    m_debugger.GetTargetList().DeleteTarget(target_sp);
  }

  void CreateTarget(Window &window) {
    ClearError();

    bool all_fields_are_valid = CheckFieldsValidity();
    if (!all_fields_are_valid)
      return;

    TargetSP target_sp = GetTarget();
    if (HasError())
      return;

    SetSymbolFile(target_sp);
    if (HasError()) {
      RemoveTarget(target_sp);
      return;
    }

    SetCoreFile(target_sp);
    if (HasError()) {
      RemoveTarget(target_sp);
      return;
    }

    SetRemoteFile(target_sp);
    if (HasError()) {
      RemoveTarget(target_sp);
      return;
    }

    window.GetParent()->RemoveSubWindow(&window);
  }

protected:
  Debugger &m_debugger;

  FileFieldDelegate *m_executable_field;
  FileFieldDelegate *m_core_file_field;
  FileFieldDelegate *m_symbol_file_field;
  BooleanFieldDelegate *m_show_advanced_field;
  FileFieldDelegate *m_remote_file_field;
  ArchFieldDelegate *m_arch_field;
  PlatformPluginFieldDelegate *m_platform_field;
  ChoicesFieldDelegate *m_load_dependent_files_field;
};

class ProcessLaunchFormDelegate : public FormDelegate {
public:
  ProcessLaunchFormDelegate(Debugger &debugger, WindowSP main_window_sp)
      : m_debugger(debugger), m_main_window_sp(main_window_sp) {

    m_arguments_field = AddArgumentsField();
    SetArgumentsFieldDefaultValue();
    m_target_environment_field =
        AddEnvironmentVariableListField("Target Environment Variables");
    SetTargetEnvironmentFieldDefaultValue();
    m_working_directory_field = AddDirectoryField(
        "Working Directory", GetDefaultWorkingDirectory().c_str(), true, false);

    m_show_advanced_field = AddBooleanField("Show advanced settings.", false);

    m_stop_at_entry_field = AddBooleanField("Stop at entry point.", false);
    m_detach_on_error_field =
        AddBooleanField("Detach on error.", GetDefaultDetachOnError());
    m_disable_aslr_field =
        AddBooleanField("Disable ASLR", GetDefaultDisableASLR());
    m_plugin_field = AddProcessPluginField();
    m_arch_field = AddArchField("Architecture", "", false);
    m_shell_field = AddFileField("Shell", "", true, false);
    m_expand_shell_arguments_field =
        AddBooleanField("Expand shell arguments.", false);

    m_disable_standard_io_field =
        AddBooleanField("Disable Standard IO", GetDefaultDisableStandardIO());
    m_standard_output_field =
        AddFileField("Standard Output File", "", /*need_to_exist=*/false,
                     /*required=*/false);
    m_standard_error_field =
        AddFileField("Standard Error File", "", /*need_to_exist=*/false,
                     /*required=*/false);
    m_standard_input_field =
        AddFileField("Standard Input File", "", /*need_to_exist=*/false,
                     /*required=*/false);

    m_show_inherited_environment_field =
        AddBooleanField("Show inherited environment variables.", false);
    m_inherited_environment_field =
        AddEnvironmentVariableListField("Inherited Environment Variables");
    SetInheritedEnvironmentFieldDefaultValue();

    AddAction("Launch", [this](Window &window) { Launch(window); });
  }

  std::string GetName() override { return "Launch Process"; }

  void UpdateFieldsVisibility() override {
    if (m_show_advanced_field->GetBoolean()) {
      m_stop_at_entry_field->FieldDelegateShow();
      m_detach_on_error_field->FieldDelegateShow();
      m_disable_aslr_field->FieldDelegateShow();
      m_plugin_field->FieldDelegateShow();
      m_arch_field->FieldDelegateShow();
      m_shell_field->FieldDelegateShow();
      m_expand_shell_arguments_field->FieldDelegateShow();
      m_disable_standard_io_field->FieldDelegateShow();
      if (m_disable_standard_io_field->GetBoolean()) {
        m_standard_input_field->FieldDelegateHide();
        m_standard_output_field->FieldDelegateHide();
        m_standard_error_field->FieldDelegateHide();
      } else {
        m_standard_input_field->FieldDelegateShow();
        m_standard_output_field->FieldDelegateShow();
        m_standard_error_field->FieldDelegateShow();
      }
      m_show_inherited_environment_field->FieldDelegateShow();
      if (m_show_inherited_environment_field->GetBoolean())
        m_inherited_environment_field->FieldDelegateShow();
      else
        m_inherited_environment_field->FieldDelegateHide();
    } else {
      m_stop_at_entry_field->FieldDelegateHide();
      m_detach_on_error_field->FieldDelegateHide();
      m_disable_aslr_field->FieldDelegateHide();
      m_plugin_field->FieldDelegateHide();
      m_arch_field->FieldDelegateHide();
      m_shell_field->FieldDelegateHide();
      m_expand_shell_arguments_field->FieldDelegateHide();
      m_disable_standard_io_field->FieldDelegateHide();
      m_standard_input_field->FieldDelegateHide();
      m_standard_output_field->FieldDelegateHide();
      m_standard_error_field->FieldDelegateHide();
      m_show_inherited_environment_field->FieldDelegateHide();
      m_inherited_environment_field->FieldDelegateHide();
    }
  }

  // Methods for setting the default value of the fields.

  void SetArgumentsFieldDefaultValue() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return;

    const Args &target_arguments =
        target->GetProcessLaunchInfo().GetArguments();
    m_arguments_field->AddArguments(target_arguments);
  }

  void SetTargetEnvironmentFieldDefaultValue() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return;

    const Environment &target_environment = target->GetTargetEnvironment();
    m_target_environment_field->AddEnvironmentVariables(target_environment);
  }

  void SetInheritedEnvironmentFieldDefaultValue() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return;

    const Environment &inherited_environment =
        target->GetInheritedEnvironment();
    m_inherited_environment_field->AddEnvironmentVariables(
        inherited_environment);
  }

  std::string GetDefaultWorkingDirectory() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return "";

    PlatformSP platform = target->GetPlatform();
    return platform->GetWorkingDirectory().GetPath();
  }

  bool GetDefaultDisableASLR() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return false;

    return target->GetDisableASLR();
  }

  bool GetDefaultDisableStandardIO() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return true;

    return target->GetDisableSTDIO();
  }

  bool GetDefaultDetachOnError() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return true;

    return target->GetDetachOnError();
  }

  // Methods for getting the necessary information and setting them to the
  // ProcessLaunchInfo.

  void GetExecutableSettings(ProcessLaunchInfo &launch_info) {
    TargetSP target = m_debugger.GetSelectedTarget();
    ModuleSP executable_module = target->GetExecutableModule();
    llvm::StringRef target_settings_argv0 = target->GetArg0();

    if (!target_settings_argv0.empty()) {
      launch_info.GetArguments().AppendArgument(target_settings_argv0);
      launch_info.SetExecutableFile(executable_module->GetPlatformFileSpec(),
                                    false);
      return;
    }

    launch_info.SetExecutableFile(executable_module->GetPlatformFileSpec(),
                                  true);
  }

  void GetArguments(ProcessLaunchInfo &launch_info) {
    TargetSP target = m_debugger.GetSelectedTarget();
    Args arguments = m_arguments_field->GetArguments();
    launch_info.GetArguments().AppendArguments(arguments);
  }

  void GetEnvironment(ProcessLaunchInfo &launch_info) {
    Environment target_environment =
        m_target_environment_field->GetEnvironment();
    Environment inherited_environment =
        m_inherited_environment_field->GetEnvironment();
    launch_info.GetEnvironment().insert(target_environment.begin(),
                                        target_environment.end());
    launch_info.GetEnvironment().insert(inherited_environment.begin(),
                                        inherited_environment.end());
  }

  void GetWorkingDirectory(ProcessLaunchInfo &launch_info) {
    if (m_working_directory_field->IsSpecified())
      launch_info.SetWorkingDirectory(
          m_working_directory_field->GetResolvedFileSpec());
  }

  void GetStopAtEntry(ProcessLaunchInfo &launch_info) {
    if (m_stop_at_entry_field->GetBoolean())
      launch_info.GetFlags().Set(eLaunchFlagStopAtEntry);
    else
      launch_info.GetFlags().Clear(eLaunchFlagStopAtEntry);
  }

  void GetDetachOnError(ProcessLaunchInfo &launch_info) {
    if (m_detach_on_error_field->GetBoolean())
      launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
    else
      launch_info.GetFlags().Clear(eLaunchFlagDetachOnError);
  }

  void GetDisableASLR(ProcessLaunchInfo &launch_info) {
    if (m_disable_aslr_field->GetBoolean())
      launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
    else
      launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
  }

  void GetPlugin(ProcessLaunchInfo &launch_info) {
    launch_info.SetProcessPluginName(m_plugin_field->GetPluginName());
  }

  void GetArch(ProcessLaunchInfo &launch_info) {
    if (!m_arch_field->IsSpecified())
      return;

    TargetSP target_sp = m_debugger.GetSelectedTarget();
    PlatformSP platform_sp =
        target_sp ? target_sp->GetPlatform() : PlatformSP();
    launch_info.GetArchitecture() = Platform::GetAugmentedArchSpec(
        platform_sp.get(), m_arch_field->GetArchString());
  }

  void GetShell(ProcessLaunchInfo &launch_info) {
    if (!m_shell_field->IsSpecified())
      return;

    launch_info.SetShell(m_shell_field->GetResolvedFileSpec());
    launch_info.SetShellExpandArguments(
        m_expand_shell_arguments_field->GetBoolean());
  }

  void GetStandardIO(ProcessLaunchInfo &launch_info) {
    if (m_disable_standard_io_field->GetBoolean()) {
      launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
      return;
    }

    FileAction action;
    if (m_standard_input_field->IsSpecified()) {
      if (action.Open(STDIN_FILENO, m_standard_input_field->GetFileSpec(), true,
                      false))
        launch_info.AppendFileAction(action);
    }
    if (m_standard_output_field->IsSpecified()) {
      if (action.Open(STDOUT_FILENO, m_standard_output_field->GetFileSpec(),
                      false, true))
        launch_info.AppendFileAction(action);
    }
    if (m_standard_error_field->IsSpecified()) {
      if (action.Open(STDERR_FILENO, m_standard_error_field->GetFileSpec(),
                      false, true))
        launch_info.AppendFileAction(action);
    }
  }

  void GetInheritTCC(ProcessLaunchInfo &launch_info) {
    if (m_debugger.GetSelectedTarget()->GetInheritTCC())
      launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent);
  }

  ProcessLaunchInfo GetLaunchInfo() {
    ProcessLaunchInfo launch_info;

    GetExecutableSettings(launch_info);
    GetArguments(launch_info);
    GetEnvironment(launch_info);
    GetWorkingDirectory(launch_info);
    GetStopAtEntry(launch_info);
    GetDetachOnError(launch_info);
    GetDisableASLR(launch_info);
    GetPlugin(launch_info);
    GetArch(launch_info);
    GetShell(launch_info);
    GetStandardIO(launch_info);
    GetInheritTCC(launch_info);

    return launch_info;
  }

  bool StopRunningProcess() {
    ExecutionContext exe_ctx =
        m_debugger.GetCommandInterpreter().GetExecutionContext();

    if (!exe_ctx.HasProcessScope())
      return false;

    Process *process = exe_ctx.GetProcessPtr();
    if (!(process && process->IsAlive()))
      return false;

    FormDelegateSP form_delegate_sp =
        FormDelegateSP(new DetachOrKillProcessFormDelegate(process));
    Rect bounds = m_main_window_sp->GetCenteredRect(85, 8);
    WindowSP form_window_sp = m_main_window_sp->CreateSubWindow(
        form_delegate_sp->GetName().c_str(), bounds, true);
    WindowDelegateSP window_delegate_sp =
        WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
    form_window_sp->SetDelegate(window_delegate_sp);

    return true;
  }

  Target *GetTarget() {
    Target *target = m_debugger.GetSelectedTarget().get();

    if (target == nullptr) {
      SetError("No target exists!");
      return nullptr;
    }

    ModuleSP exe_module_sp = target->GetExecutableModule();

    if (exe_module_sp == nullptr) {
      SetError("No executable in target!");
      return nullptr;
    }

    return target;
  }

  void Launch(Window &window) {
    ClearError();

    bool all_fields_are_valid = CheckFieldsValidity();
    if (!all_fields_are_valid)
      return;

    bool process_is_running = StopRunningProcess();
    if (process_is_running)
      return;

    Target *target = GetTarget();
    if (HasError())
      return;

    StreamString stream;
    ProcessLaunchInfo launch_info = GetLaunchInfo();
    Status status = target->Launch(launch_info, &stream);

    if (status.Fail()) {
      SetError(status.AsCString());
      return;
    }

    ProcessSP process_sp(target->GetProcessSP());
    if (!process_sp) {
      SetError("Launched successfully but target has no process!");
      return;
    }

    window.GetParent()->RemoveSubWindow(&window);
  }

protected:
  Debugger &m_debugger;
  WindowSP m_main_window_sp;

  ArgumentsFieldDelegate *m_arguments_field;
  EnvironmentVariableListFieldDelegate *m_target_environment_field;
  DirectoryFieldDelegate *m_working_directory_field;

  BooleanFieldDelegate *m_show_advanced_field;

  BooleanFieldDelegate *m_stop_at_entry_field;
  BooleanFieldDelegate *m_detach_on_error_field;
  BooleanFieldDelegate *m_disable_aslr_field;
  ProcessPluginFieldDelegate *m_plugin_field;
  ArchFieldDelegate *m_arch_field;
  FileFieldDelegate *m_shell_field;
  BooleanFieldDelegate *m_expand_shell_arguments_field;
  BooleanFieldDelegate *m_disable_standard_io_field;
  FileFieldDelegate *m_standard_input_field;
  FileFieldDelegate *m_standard_output_field;
  FileFieldDelegate *m_standard_error_field;

  BooleanFieldDelegate *m_show_inherited_environment_field;
  EnvironmentVariableListFieldDelegate *m_inherited_environment_field;
};

////////////
// Searchers
////////////

class SearcherDelegate {
public:
  SearcherDelegate() = default;

  virtual ~SearcherDelegate() = default;

  virtual int GetNumberOfMatches() = 0;

  // Get the string that will be displayed for the match at the input index.
  virtual const std::string &GetMatchTextAtIndex(int index) = 0;

  // Update the matches of the search. This is executed every time the text
  // field handles an event.
  virtual void UpdateMatches(const std::string &text) = 0;

  // Execute the user callback given the index of some match. This is executed
  // once the user selects a match.
  virtual void ExecuteCallback(int match_index) = 0;
};

typedef std::shared_ptr<SearcherDelegate> SearcherDelegateSP;

class SearcherWindowDelegate : public WindowDelegate {
public:
  SearcherWindowDelegate(SearcherDelegateSP &delegate_sp)
      : m_delegate_sp(delegate_sp), m_text_field("Search", "", false) {
    ;
  }

  // A completion window is padded by one character from all sides. A text field
  // is first drawn for inputting the searcher request, then a list of matches
  // are displayed in a scrollable list.
  //
  // ___<Searcher Window Name>____________________________
  // |                                                   |
  // | __[Search]_______________________________________ |
  // | |                                               | |
  // | |_______________________________________________| |
  // | - Match 1.                                        |
  // | - Match 2.                                        |
  // | - ...                                             |
  // |                                                   |
  // |____________________________[Press Esc to Cancel]__|
  //

  // Get the index of the last visible match. Assuming at least one match
  // exists.
  int GetLastVisibleMatch(int height) {
    int index = m_first_visible_match + height;
    return std::min(index, m_delegate_sp->GetNumberOfMatches()) - 1;
  }

  int GetNumberOfVisibleMatches(int height) {
    return GetLastVisibleMatch(height) - m_first_visible_match + 1;
  }

  void UpdateScrolling(Surface &surface) {
    if (m_selected_match < m_first_visible_match) {
      m_first_visible_match = m_selected_match;
      return;
    }

    int height = surface.GetHeight();
    int last_visible_match = GetLastVisibleMatch(height);
    if (m_selected_match > last_visible_match) {
      m_first_visible_match = m_selected_match - height + 1;
    }
  }

  void DrawMatches(Surface &surface) {
    if (m_delegate_sp->GetNumberOfMatches() == 0)
      return;

    UpdateScrolling(surface);

    int count = GetNumberOfVisibleMatches(surface.GetHeight());
    for (int i = 0; i < count; i++) {
      surface.MoveCursor(1, i);
      int current_match = m_first_visible_match + i;
      if (current_match == m_selected_match)
        surface.AttributeOn(A_REVERSE);
      surface.PutCString(
          m_delegate_sp->GetMatchTextAtIndex(current_match).c_str());
      if (current_match == m_selected_match)
        surface.AttributeOff(A_REVERSE);
    }
  }

  void DrawContent(Surface &surface) {
    Rect content_bounds = surface.GetFrame();
    Rect text_field_bounds, matchs_bounds;
    content_bounds.HorizontalSplit(m_text_field.FieldDelegateGetHeight(),
                                   text_field_bounds, matchs_bounds);
    Surface text_field_surface = surface.SubSurface(text_field_bounds);
    Surface matches_surface = surface.SubSurface(matchs_bounds);

    m_text_field.FieldDelegateDraw(text_field_surface, true);
    DrawMatches(matches_surface);
  }

  bool WindowDelegateDraw(Window &window, bool force) override {
    window.Erase();

    window.DrawTitleBox(window.GetName(), "Press Esc to Cancel");

    Rect content_bounds = window.GetFrame();
    content_bounds.Inset(2, 2);
    Surface content_surface = window.SubSurface(content_bounds);

    DrawContent(content_surface);
    return true;
  }

  void SelectNext() {
    if (m_selected_match != m_delegate_sp->GetNumberOfMatches() - 1)
      m_selected_match++;
  }

  void SelectPrevious() {
    if (m_selected_match != 0)
      m_selected_match--;
  }

  void ExecuteCallback(Window &window) {
    m_delegate_sp->ExecuteCallback(m_selected_match);
    window.GetParent()->RemoveSubWindow(&window);
  }

  void UpdateMatches() {
    m_delegate_sp->UpdateMatches(m_text_field.GetText());
    m_selected_match = 0;
  }

  HandleCharResult WindowDelegateHandleChar(Window &window, int key) override {
    switch (key) {
    case '\r':
    case '\n':
    case KEY_ENTER:
      ExecuteCallback(window);
      return eKeyHandled;
    case '\t':
    case KEY_DOWN:
      SelectNext();
      return eKeyHandled;
    case KEY_SHIFT_TAB:
    case KEY_UP:
      SelectPrevious();
      return eKeyHandled;
    case KEY_ESCAPE:
      window.GetParent()->RemoveSubWindow(&window);
      return eKeyHandled;
    default:
      break;
    }

    if (m_text_field.FieldDelegateHandleChar(key) == eKeyHandled)
      UpdateMatches();

    return eKeyHandled;
  }

protected:
  SearcherDelegateSP m_delegate_sp;
  TextFieldDelegate m_text_field;
  // The index of the currently selected match.
  int m_selected_match = 0;
  // The index of the first visible match.
  int m_first_visible_match = 0;
};

//////////////////////////////
// Searcher Delegate Instances
//////////////////////////////

// This is a searcher delegate wrapper around CommandCompletions common
// callbacks. The callbacks are only given the match string. The completion_mask
// can be a combination of CommonCompletionTypes.
class CommonCompletionSearcherDelegate : public SearcherDelegate {
public:
  typedef std::function<void(const std::string &)> CallbackType;

  CommonCompletionSearcherDelegate(Debugger &debugger, uint32_t completion_mask,
                                   CallbackType callback)
      : m_debugger(debugger), m_completion_mask(completion_mask),
        m_callback(callback) {}

  int GetNumberOfMatches() override { return m_matches.GetSize(); }

  const std::string &GetMatchTextAtIndex(int index) override {
    return m_matches[index];
  }

  void UpdateMatches(const std::string &text) override {
    CompletionResult result;
    CompletionRequest request(text.c_str(), text.size(), result);
    CommandCompletions::InvokeCommonCompletionCallbacks(
        m_debugger.GetCommandInterpreter(), m_completion_mask, request,
        nullptr);
    result.GetMatches(m_matches);
  }

  void ExecuteCallback(int match_index) override {
    m_callback(m_matches[match_index]);
  }

protected:
  Debugger &m_debugger;
  // A compound mask from CommonCompletionTypes.
  uint32_t m_completion_mask;
  // A callback to execute once the user selects a match. The match is passed to
  // the callback as a string.
  CallbackType m_callback;
  StringList m_matches;
};

////////
// Menus
////////

class MenuDelegate {
public:
  virtual ~MenuDelegate() = default;

  virtual MenuActionResult MenuDelegateAction(Menu &menu) = 0;
};

class Menu : public WindowDelegate {
public:
  enum class Type { Invalid, Bar, Item, Separator };

  // Menubar or separator constructor
  Menu(Type type);

  // Menuitem constructor
  Menu(const char *name, const char *key_name, int key_value,
       uint64_t identifier);

  ~Menu() override = default;

  const MenuDelegateSP &GetDelegate() const { return m_delegate_sp; }

  void SetDelegate(const MenuDelegateSP &delegate_sp) {
    m_delegate_sp = delegate_sp;
  }

  void RecalculateNameLengths();

  void AddSubmenu(const MenuSP &menu_sp);

  int DrawAndRunMenu(Window &window);

  void DrawMenuTitle(Window &window, bool highlight);

  bool WindowDelegateDraw(Window &window, bool force) override;

  HandleCharResult WindowDelegateHandleChar(Window &window, int key) override;

  MenuActionResult ActionPrivate(Menu &menu) {
    MenuActionResult result = MenuActionResult::NotHandled;
    if (m_delegate_sp) {
      result = m_delegate_sp->MenuDelegateAction(menu);
      if (result != MenuActionResult::NotHandled)
        return result;
    } else if (m_parent) {
      result = m_parent->ActionPrivate(menu);
      if (result != MenuActionResult::NotHandled)
        return result;
    }
    return m_canned_result;
  }

  MenuActionResult Action() {
    // Call the recursive action so it can try to handle it with the menu
    // delegate, and if not, try our parent menu
    return ActionPrivate(*this);
  }

  void SetCannedResult(MenuActionResult result) { m_canned_result = result; }

  Menus &GetSubmenus() { return m_submenus; }

  const Menus &GetSubmenus() const { return m_submenus; }

  int GetSelectedSubmenuIndex() const { return m_selected; }

  void SetSelectedSubmenuIndex(int idx) { m_selected = idx; }

  Type GetType() const { return m_type; }

  int GetStartingColumn() const { return m_start_col; }

  void SetStartingColumn(int col) { m_start_col = col; }

  int GetKeyValue() const { return m_key_value; }

  std::string &GetName() { return m_name; }

  int GetDrawWidth() const {
    return m_max_submenu_name_length + m_max_submenu_key_name_length + 8;
  }

  uint64_t GetIdentifier() const { return m_identifier; }

  void SetIdentifier(uint64_t identifier) { m_identifier = identifier; }

protected:
  std::string m_name;
  std::string m_key_name;
  uint64_t m_identifier;
  Type m_type;
  int m_key_value;
  int m_start_col;
  int m_max_submenu_name_length;
  int m_max_submenu_key_name_length;
  int m_selected;
  Menu *m_parent;
  Menus m_submenus;
  WindowSP m_menu_window_sp;
  MenuActionResult m_canned_result;
  MenuDelegateSP m_delegate_sp;
};

// Menubar or separator constructor
Menu::Menu(Type type)
    : m_name(), m_key_name(), m_identifier(0), m_type(type), m_key_value(0),
      m_start_col(0), m_max_submenu_name_length(0),
      m_max_submenu_key_name_length(0), m_selected(0), m_parent(nullptr),
      m_submenus(), m_canned_result(MenuActionResult::NotHandled),
      m_delegate_sp() {}

// Menuitem constructor
Menu::Menu(const char *name, const char *key_name, int key_value,
           uint64_t identifier)
    : m_name(), m_key_name(), m_identifier(identifier), m_type(Type::Invalid),
      m_key_value(key_value), m_start_col(0), m_max_submenu_name_length(0),
      m_max_submenu_key_name_length(0), m_selected(0), m_parent(nullptr),
      m_submenus(), m_canned_result(MenuActionResult::NotHandled),
      m_delegate_sp() {
  if (name && name[0]) {
    m_name = name;
    m_type = Type::Item;
    if (key_name && key_name[0])
      m_key_name = key_name;
  } else {
    m_type = Type::Separator;
  }
}

void Menu::RecalculateNameLengths() {
  m_max_submenu_name_length = 0;
  m_max_submenu_key_name_length = 0;
  Menus &submenus = GetSubmenus();
  const size_t num_submenus = submenus.size();
  for (size_t i = 0; i < num_submenus; ++i) {
    Menu *submenu = submenus[i].get();
    if (static_cast<size_t>(m_max_submenu_name_length) < submenu->m_name.size())
      m_max_submenu_name_length = submenu->m_name.size();
    if (static_cast<size_t>(m_max_submenu_key_name_length) <
        submenu->m_key_name.size())
      m_max_submenu_key_name_length = submenu->m_key_name.size();
  }
}

void Menu::AddSubmenu(const MenuSP &menu_sp) {
  menu_sp->m_parent = this;
  if (static_cast<size_t>(m_max_submenu_name_length) < menu_sp->m_name.size())
    m_max_submenu_name_length = menu_sp->m_name.size();
  if (static_cast<size_t>(m_max_submenu_key_name_length) <
      menu_sp->m_key_name.size())
    m_max_submenu_key_name_length = menu_sp->m_key_name.size();
  m_submenus.push_back(menu_sp);
}

void Menu::DrawMenuTitle(Window &window, bool highlight) {
  if (m_type == Type::Separator) {
    window.MoveCursor(0, window.GetCursorY());
    window.PutChar(ACS_LTEE);
    int width = window.GetWidth();
    if (width > 2) {
      width -= 2;
      for (int i = 0; i < width; ++i)
        window.PutChar(ACS_HLINE);
    }
    window.PutChar(ACS_RTEE);
  } else {
    const int shortcut_key = m_key_value;
    bool underlined_shortcut = false;
    const attr_t highlight_attr = A_REVERSE;
    if (highlight)
      window.AttributeOn(highlight_attr);
    if (llvm::isPrint(shortcut_key)) {
      size_t lower_pos = m_name.find(tolower(shortcut_key));
      size_t upper_pos = m_name.find(toupper(shortcut_key));
      const char *name = m_name.c_str();
      size_t pos = std::min<size_t>(lower_pos, upper_pos);
      if (pos != std::string::npos) {
        underlined_shortcut = true;
        if (pos > 0) {
          window.PutCString(name, pos);
          name += pos;
        }
        const attr_t shortcut_attr = A_UNDERLINE | A_BOLD;
        window.AttributeOn(shortcut_attr);
        window.PutChar(name[0]);
        window.AttributeOff(shortcut_attr);
        name++;
        if (name[0])
          window.PutCString(name);
      }
    }

    if (!underlined_shortcut) {
      window.PutCString(m_name.c_str());
    }

    if (highlight)
      window.AttributeOff(highlight_attr);

    if (m_key_name.empty()) {
      if (!underlined_shortcut && llvm::isPrint(m_key_value)) {
        window.AttributeOn(COLOR_PAIR(MagentaOnWhite));
        window.Printf(" (%c)", m_key_value);
        window.AttributeOff(COLOR_PAIR(MagentaOnWhite));
      }
    } else {
      window.AttributeOn(COLOR_PAIR(MagentaOnWhite));
      window.Printf(" (%s)", m_key_name.c_str());
      window.AttributeOff(COLOR_PAIR(MagentaOnWhite));
    }
  }
}

bool Menu::WindowDelegateDraw(Window &window, bool force) {
  Menus &submenus = GetSubmenus();
  const size_t num_submenus = submenus.size();
  const int selected_idx = GetSelectedSubmenuIndex();
  Menu::Type menu_type = GetType();
  switch (menu_type) {
  case Menu::Type::Bar: {
    window.SetBackground(BlackOnWhite);
    window.MoveCursor(0, 0);
    for (size_t i = 0; i < num_submenus; ++i) {
      Menu *menu = submenus[i].get();
      if (i > 0)
        window.PutChar(' ');
      menu->SetStartingColumn(window.GetCursorX());
      window.PutCString("| ");
      menu->DrawMenuTitle(window, false);
    }
    window.PutCString(" |");
  } break;

  case Menu::Type::Item: {
    int y = 1;
    int x = 3;
    // Draw the menu
    int cursor_x = 0;
    int cursor_y = 0;
    window.Erase();
    window.SetBackground(BlackOnWhite);
    window.Box();
    for (size_t i = 0; i < num_submenus; ++i) {
      const bool is_selected = (i == static_cast<size_t>(selected_idx));
      window.MoveCursor(x, y + i);
      if (is_selected) {
        // Remember where we want the cursor to be
        cursor_x = x - 1;
        cursor_y = y + i;
      }
      submenus[i]->DrawMenuTitle(window, is_selected);
    }
    window.MoveCursor(cursor_x, cursor_y);
  } break;

  default:
  case Menu::Type::Separator:
    break;
  }
  return true; // Drawing handled...
}

HandleCharResult Menu::WindowDelegateHandleChar(Window &window, int key) {
  HandleCharResult result = eKeyNotHandled;

  Menus &submenus = GetSubmenus();
  const size_t num_submenus = submenus.size();
  const int selected_idx = GetSelectedSubmenuIndex();
  Menu::Type menu_type = GetType();
  if (menu_type == Menu::Type::Bar) {
    MenuSP run_menu_sp;
    switch (key) {
    case KEY_DOWN:
    case KEY_UP:
      // Show last menu or first menu
      if (selected_idx < static_cast<int>(num_submenus))
        run_menu_sp = submenus[selected_idx];
      else if (!submenus.empty())
        run_menu_sp = submenus.front();
      result = eKeyHandled;
      break;

    case KEY_RIGHT:
      ++m_selected;
      if (m_selected >= static_cast<int>(num_submenus))
        m_selected = 0;
      if (m_selected < static_cast<int>(num_submenus))
        run_menu_sp = submenus[m_selected];
      else if (!submenus.empty())
        run_menu_sp = submenus.front();
      result = eKeyHandled;
      break;

    case KEY_LEFT:
      --m_selected;
      if (m_selected < 0)
        m_selected = num_submenus - 1;
      if (m_selected < static_cast<int>(num_submenus))
        run_menu_sp = submenus[m_selected];
      else if (!submenus.empty())
        run_menu_sp = submenus.front();
      result = eKeyHandled;
      break;

    default:
      for (size_t i = 0; i < num_submenus; ++i) {
        if (submenus[i]->GetKeyValue() == key) {
          SetSelectedSubmenuIndex(i);
          run_menu_sp = submenus[i];
          result = eKeyHandled;
          break;
        }
      }
      break;
    }

    if (run_menu_sp) {
      // Run the action on this menu in case we need to populate the menu with
      // dynamic content and also in case check marks, and any other menu
      // decorations need to be calculated
      if (run_menu_sp->Action() == MenuActionResult::Quit)
        return eQuitApplication;

      Rect menu_bounds;
      menu_bounds.origin.x = run_menu_sp->GetStartingColumn();
      menu_bounds.origin.y = 1;
      menu_bounds.size.width = run_menu_sp->GetDrawWidth();
      menu_bounds.size.height = run_menu_sp->GetSubmenus().size() + 2;
      if (m_menu_window_sp)
        window.GetParent()->RemoveSubWindow(m_menu_window_sp.get());

      m_menu_window_sp = window.GetParent()->CreateSubWindow(
          run_menu_sp->GetName().c_str(), menu_bounds, true);
      m_menu_window_sp->SetDelegate(run_menu_sp);
    }
  } else if (menu_type == Menu::Type::Item) {
    switch (key) {
    case KEY_DOWN:
      if (m_submenus.size() > 1) {
        const int start_select = m_selected;
        while (++m_selected != start_select) {
          if (static_cast<size_t>(m_selected) >= num_submenus)
            m_selected = 0;
          if (m_submenus[m_selected]->GetType() == Type::Separator)
            continue;
          else
            break;
        }
        return eKeyHandled;
      }
      break;

    case KEY_UP:
      if (m_submenus.size() > 1) {
        const int start_select = m_selected;
        while (--m_selected != start_select) {
          if (m_selected < static_cast<int>(0))
            m_selected = num_submenus - 1;
          if (m_submenus[m_selected]->GetType() == Type::Separator)
            continue;
          else
            break;
        }
        return eKeyHandled;
      }
      break;

    case KEY_RETURN:
      if (static_cast<size_t>(selected_idx) < num_submenus) {
        if (submenus[selected_idx]->Action() == MenuActionResult::Quit)
          return eQuitApplication;
        window.GetParent()->RemoveSubWindow(&window);
        return eKeyHandled;
      }
      break;

    case KEY_ESCAPE: // Beware: pressing escape key has 1 to 2 second delay in
                     // case other chars are entered for escaped sequences
      window.GetParent()->RemoveSubWindow(&window);
      return eKeyHandled;

    default:
      for (size_t i = 0; i < num_submenus; ++i) {
        Menu *menu = submenus[i].get();
        if (menu->GetKeyValue() == key) {
          SetSelectedSubmenuIndex(i);
          window.GetParent()->RemoveSubWindow(&window);
          if (menu->Action() == MenuActionResult::Quit)
            return eQuitApplication;
          return eKeyHandled;
        }
      }
      break;
    }
  } else if (menu_type == Menu::Type::Separator) {
  }
  return result;
}

class Application {
public:
  Application(FILE *in, FILE *out) : m_window_sp(), m_in(in), m_out(out) {}

  ~Application() {
    m_window_delegates.clear();
    m_window_sp.reset();
    if (m_screen) {
      ::delscreen(m_screen);
      m_screen = nullptr;
    }
  }

  void Initialize() {
    m_screen = ::newterm(nullptr, m_out, m_in);
    ::start_color();
    ::curs_set(0);
    ::noecho();
    ::keypad(stdscr, TRUE);
  }

  void Terminate() { ::endwin(); }

  void Run(Debugger &debugger) {
    bool done = false;
    int delay_in_tenths_of_a_second = 1;

    // Alas the threading model in curses is a bit lame so we need to resort
    // to polling every 0.5 seconds. We could poll for stdin ourselves and
    // then pass the keys down but then we need to translate all of the escape
    // sequences ourselves. So we resort to polling for input because we need
    // to receive async process events while in this loop.

    halfdelay(delay_in_tenths_of_a_second); // Poll using some number of
                                            // tenths of seconds seconds when
                                            // calling Window::GetChar()

    ListenerSP listener_sp(
        Listener::MakeListener("lldb.IOHandler.curses.Application"));
    ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
    debugger.EnableForwardEvents(listener_sp);

    m_update_screen = true;
#if defined(__APPLE__)
    std::deque<int> escape_chars;
#endif

    while (!done) {
      if (m_update_screen) {
        m_window_sp->Draw(false);
        // All windows should be calling Window::DeferredRefresh() instead of
        // Window::Refresh() so we can do a single update and avoid any screen
        // blinking
        update_panels();

        // Cursor hiding isn't working on MacOSX, so hide it in the top left
        // corner
        m_window_sp->MoveCursor(0, 0);

        doupdate();
        m_update_screen = false;
      }

#if defined(__APPLE__)
      // Terminal.app doesn't map its function keys correctly, F1-F4 default
      // to: \033OP, \033OQ, \033OR, \033OS, so lets take care of this here if
      // possible
      int ch;
      if (escape_chars.empty())
        ch = m_window_sp->GetChar();
      else {
        ch = escape_chars.front();
        escape_chars.pop_front();
      }
      if (ch == KEY_ESCAPE) {
        int ch2 = m_window_sp->GetChar();
        if (ch2 == 'O') {
          int ch3 = m_window_sp->GetChar();
          switch (ch3) {
          case 'P':
            ch = KEY_F(1);
            break;
          case 'Q':
            ch = KEY_F(2);
            break;
          case 'R':
            ch = KEY_F(3);
            break;
          case 'S':
            ch = KEY_F(4);
            break;
          default:
            escape_chars.push_back(ch2);
            if (ch3 != -1)
              escape_chars.push_back(ch3);
            break;
          }
        } else if (ch2 != -1)
          escape_chars.push_back(ch2);
      }
#else
      int ch = m_window_sp->GetChar();

#endif
      if (ch == -1) {
        if (feof(m_in) || ferror(m_in)) {
          done = true;
        } else {
          // Just a timeout from using halfdelay(), check for events
          EventSP event_sp;
          while (listener_sp->PeekAtNextEvent()) {
            listener_sp->GetEvent(event_sp, std::chrono::seconds(0));

            if (event_sp) {
              Broadcaster *broadcaster = event_sp->GetBroadcaster();
              if (broadcaster) {
                // uint32_t event_type = event_sp->GetType();
                ConstString broadcaster_class(
                    broadcaster->GetBroadcasterClass());
                if (broadcaster_class == broadcaster_class_process) {
                  m_update_screen = true;
                  continue; // Don't get any key, just update our view
                }
              }
            }
          }
        }
      } else {
        HandleCharResult key_result = m_window_sp->HandleChar(ch);
        switch (key_result) {
        case eKeyHandled:
          m_update_screen = true;
          break;
        case eKeyNotHandled:
          if (ch == 12) { // Ctrl+L, force full redraw
            redrawwin(m_window_sp->get());
            m_update_screen = true;
          }
          break;
        case eQuitApplication:
          done = true;
          break;
        }
      }
    }

    debugger.CancelForwardEvents(listener_sp);
  }

  WindowSP &GetMainWindow() {
    if (!m_window_sp)
      m_window_sp = std::make_shared<Window>("main", stdscr, false);
    return m_window_sp;
  }

  void TerminalSizeChanged() {
    ::endwin();
    ::refresh();
    Rect content_bounds = m_window_sp->GetFrame();
    m_window_sp->SetBounds(content_bounds);
    if (WindowSP menubar_window_sp = m_window_sp->FindSubWindow("Menubar"))
      menubar_window_sp->SetBounds(content_bounds.MakeMenuBar());
    if (WindowSP status_window_sp = m_window_sp->FindSubWindow("Status"))
      status_window_sp->SetBounds(content_bounds.MakeStatusBar());

    WindowSP source_window_sp = m_window_sp->FindSubWindow("Source");
    WindowSP variables_window_sp = m_window_sp->FindSubWindow("Variables");
    WindowSP registers_window_sp = m_window_sp->FindSubWindow("Registers");
    WindowSP threads_window_sp = m_window_sp->FindSubWindow("Threads");

    Rect threads_bounds;
    Rect source_variables_bounds;
    content_bounds.VerticalSplitPercentage(0.80, source_variables_bounds,
                                           threads_bounds);
    if (threads_window_sp)
      threads_window_sp->SetBounds(threads_bounds);
    else
      source_variables_bounds = content_bounds;

    Rect source_bounds;
    Rect variables_registers_bounds;
    source_variables_bounds.HorizontalSplitPercentage(
        0.70, source_bounds, variables_registers_bounds);
    if (variables_window_sp || registers_window_sp) {
      if (variables_window_sp && registers_window_sp) {
        Rect variables_bounds;
        Rect registers_bounds;
        variables_registers_bounds.VerticalSplitPercentage(
            0.50, variables_bounds, registers_bounds);
        variables_window_sp->SetBounds(variables_bounds);
        registers_window_sp->SetBounds(registers_bounds);
      } else if (variables_window_sp) {
        variables_window_sp->SetBounds(variables_registers_bounds);
      } else {
        registers_window_sp->SetBounds(variables_registers_bounds);
      }
    } else {
      source_bounds = source_variables_bounds;
    }

    source_window_sp->SetBounds(source_bounds);

    touchwin(stdscr);
    redrawwin(m_window_sp->get());
    m_update_screen = true;
  }

protected:
  WindowSP m_window_sp;
  WindowDelegates m_window_delegates;
  SCREEN *m_screen = nullptr;
  FILE *m_in;
  FILE *m_out;
  bool m_update_screen = false;
};

} // namespace curses

using namespace curses;

struct Row {
  ValueObjectUpdater value;
  Row *parent;
  // The process stop ID when the children were calculated.
  uint32_t children_stop_id = 0;
  int row_idx = 0;
  int x = 1;
  int y = 1;
  bool might_have_children;
  bool expanded = false;
  bool calculated_children = false;
  std::vector<Row> children;

  Row(const ValueObjectSP &v, Row *p)
      : value(v), parent(p),
        might_have_children(v ? v->MightHaveChildren() : false) {}

  size_t GetDepth() const {
    if (parent)
      return 1 + parent->GetDepth();
    return 0;
  }

  void Expand() { expanded = true; }

  std::vector<Row> &GetChildren() {
    ProcessSP process_sp = value.GetProcessSP();
    auto stop_id = process_sp->GetStopID();
    if (process_sp && stop_id != children_stop_id) {
      children_stop_id = stop_id;
      calculated_children = false;
    }
    if (!calculated_children) {
      children.clear();
      calculated_children = true;
      ValueObjectSP valobj = value.GetSP();
      if (valobj) {
        const size_t num_children = valobj->GetNumChildren();
        for (size_t i = 0; i < num_children; ++i) {
          children.push_back(Row(valobj->GetChildAtIndex(i, true), this));
        }
      }
    }
    return children;
  }

  void Unexpand() {
    expanded = false;
    calculated_children = false;
    children.clear();
  }

  void DrawTree(Window &window) {
    if (parent)
      parent->DrawTreeForChild(window, this, 0);

    if (might_have_children &&
        (!calculated_children || !GetChildren().empty())) {
      // It we can get UTF8 characters to work we should try to use the
      // "symbol" UTF8 string below
      //            const char *symbol = "";
      //            if (row.expanded)
      //                symbol = "\xe2\x96\xbd ";
      //            else
      //                symbol = "\xe2\x96\xb7 ";
      //            window.PutCString (symbol);

      // The ACS_DARROW and ACS_RARROW don't look very nice they are just a 'v'
      // or '>' character...
      //            if (expanded)
      //                window.PutChar (ACS_DARROW);
      //            else
      //                window.PutChar (ACS_RARROW);
      // Since we can't find any good looking right arrow/down arrow symbols,
      // just use a diamond...
      window.PutChar(ACS_DIAMOND);
      window.PutChar(ACS_HLINE);
    }
  }

  void DrawTreeForChild(Window &window, Row *child, uint32_t reverse_depth) {
    if (parent)
      parent->DrawTreeForChild(window, this, reverse_depth + 1);

    if (&GetChildren().back() == child) {
      // Last child
      if (reverse_depth == 0) {
        window.PutChar(ACS_LLCORNER);
        window.PutChar(ACS_HLINE);
      } else {
        window.PutChar(' ');
        window.PutChar(' ');
      }
    } else {
      if (reverse_depth == 0) {
        window.PutChar(ACS_LTEE);
        window.PutChar(ACS_HLINE);
      } else {
        window.PutChar(ACS_VLINE);
        window.PutChar(' ');
      }
    }
  }
};

struct DisplayOptions {
  bool show_types;
};

class TreeItem;

class TreeDelegate {
public:
  TreeDelegate() = default;
  virtual ~TreeDelegate() = default;

  virtual void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) = 0;
  virtual void TreeDelegateGenerateChildren(TreeItem &item) = 0;
  virtual void TreeDelegateUpdateSelection(TreeItem &root, int &selection_index,
                                           TreeItem *&selected_item) {}
  // This is invoked when a tree item is selected. If true is returned, the
  // views are updated.
  virtual bool TreeDelegateItemSelected(TreeItem &item) = 0;
  virtual bool TreeDelegateExpandRootByDefault() { return false; }
  // This is mostly useful for root tree delegates. If false is returned,
  // drawing will be skipped completely. This is needed, for instance, in
  // skipping drawing of the threads tree if there is no running process.
  virtual bool TreeDelegateShouldDraw() { return true; }
};

typedef std::shared_ptr<TreeDelegate> TreeDelegateSP;

class TreeItem {
public:
  TreeItem(TreeItem *parent, TreeDelegate &delegate, bool might_have_children)
      : m_parent(parent), m_delegate(delegate), m_children(),
        m_might_have_children(might_have_children) {
    if (m_parent == nullptr)
      m_is_expanded = m_delegate.TreeDelegateExpandRootByDefault();
  }

  TreeItem &operator=(const TreeItem &rhs) {
    if (this != &rhs) {
      m_parent = rhs.m_parent;
      m_delegate = rhs.m_delegate;
      m_user_data = rhs.m_user_data;
      m_identifier = rhs.m_identifier;
      m_row_idx = rhs.m_row_idx;
      m_children = rhs.m_children;
      m_might_have_children = rhs.m_might_have_children;
      m_is_expanded = rhs.m_is_expanded;
    }
    return *this;
  }

  TreeItem(const TreeItem &) = default;

  size_t GetDepth() const {
    if (m_parent)
      return 1 + m_parent->GetDepth();
    return 0;
  }

  int GetRowIndex() const { return m_row_idx; }

  void ClearChildren() { m_children.clear(); }

  void Resize(size_t n, const TreeItem &t) { m_children.resize(n, t); }

  TreeItem &operator[](size_t i) { return m_children[i]; }

  void SetRowIndex(int row_idx) { m_row_idx = row_idx; }

  size_t GetNumChildren() {
    m_delegate.TreeDelegateGenerateChildren(*this);
    return m_children.size();
  }

  void ItemWasSelected() { m_delegate.TreeDelegateItemSelected(*this); }

  void CalculateRowIndexes(int &row_idx) {
    SetRowIndex(row_idx);
    ++row_idx;

    const bool expanded = IsExpanded();

    // The root item must calculate its children, or we must calculate the
    // number of children if the item is expanded
    if (m_parent == nullptr || expanded)
      GetNumChildren();

    for (auto &item : m_children) {
      if (expanded)
        item.CalculateRowIndexes(row_idx);
      else
        item.SetRowIndex(-1);
    }
  }

  TreeItem *GetParent() { return m_parent; }

  bool IsExpanded() const { return m_is_expanded; }

  void Expand() { m_is_expanded = true; }

  void Unexpand() { m_is_expanded = false; }

  bool Draw(Window &window, const int first_visible_row,
            const uint32_t selected_row_idx, int &row_idx, int &num_rows_left) {
    if (num_rows_left <= 0)
      return false;

    if (m_row_idx >= first_visible_row) {
      window.MoveCursor(2, row_idx + 1);

      if (m_parent)
        m_parent->DrawTreeForChild(window, this, 0);

      if (m_might_have_children) {
        // It we can get UTF8 characters to work we should try to use the
        // "symbol" UTF8 string below
        //            const char *symbol = "";
        //            if (row.expanded)
        //                symbol = "\xe2\x96\xbd ";
        //            else
        //                symbol = "\xe2\x96\xb7 ";
        //            window.PutCString (symbol);

        // The ACS_DARROW and ACS_RARROW don't look very nice they are just a
        // 'v' or '>' character...
        //            if (expanded)
        //                window.PutChar (ACS_DARROW);
        //            else
        //                window.PutChar (ACS_RARROW);
        // Since we can't find any good looking right arrow/down arrow symbols,
        // just use a diamond...
        window.PutChar(ACS_DIAMOND);
        window.PutChar(ACS_HLINE);
      }
      bool highlight = (selected_row_idx == static_cast<size_t>(m_row_idx)) &&
                       window.IsActive();

      if (highlight)
        window.AttributeOn(A_REVERSE);

      m_delegate.TreeDelegateDrawTreeItem(*this, window);

      if (highlight)
        window.AttributeOff(A_REVERSE);
      ++row_idx;
      --num_rows_left;
    }

    if (num_rows_left <= 0)
      return false; // We are done drawing...

    if (IsExpanded()) {
      for (auto &item : m_children) {
        // If we displayed all the rows and item.Draw() returns false we are
        // done drawing and can exit this for loop
        if (!item.Draw(window, first_visible_row, selected_row_idx, row_idx,
                       num_rows_left))
          break;
      }
    }
    return num_rows_left >= 0; // Return true if not done drawing yet
  }

  void DrawTreeForChild(Window &window, TreeItem *child,
                        uint32_t reverse_depth) {
    if (m_parent)
      m_parent->DrawTreeForChild(window, this, reverse_depth + 1);

    if (&m_children.back() == child) {
      // Last child
      if (reverse_depth == 0) {
        window.PutChar(ACS_LLCORNER);
        window.PutChar(ACS_HLINE);
      } else {
        window.PutChar(' ');
        window.PutChar(' ');
      }
    } else {
      if (reverse_depth == 0) {
        window.PutChar(ACS_LTEE);
        window.PutChar(ACS_HLINE);
      } else {
        window.PutChar(ACS_VLINE);
        window.PutChar(' ');
      }
    }
  }

  TreeItem *GetItemForRowIndex(uint32_t row_idx) {
    if (static_cast<uint32_t>(m_row_idx) == row_idx)
      return this;
    if (m_children.empty())
      return nullptr;
    if (IsExpanded()) {
      for (auto &item : m_children) {
        TreeItem *selected_item_ptr = item.GetItemForRowIndex(row_idx);
        if (selected_item_ptr)
          return selected_item_ptr;
      }
    }
    return nullptr;
  }

  void *GetUserData() const { return m_user_data; }

  void SetUserData(void *user_data) { m_user_data = user_data; }

  uint64_t GetIdentifier() const { return m_identifier; }

  void SetIdentifier(uint64_t identifier) { m_identifier = identifier; }

  const std::string &GetText() const { return m_text; }

  void SetText(const char *text) {
    if (text == nullptr) {
      m_text.clear();
      return;
    }
    m_text = text;
  }

  void SetMightHaveChildren(bool b) { m_might_have_children = b; }

protected:
  TreeItem *m_parent;
  TreeDelegate &m_delegate;
  void *m_user_data = nullptr;
  uint64_t m_identifier = 0;
  std::string m_text;
  int m_row_idx = -1; // Zero based visible row index, -1 if not visible or for
                      // the root item
  std::vector<TreeItem> m_children;
  bool m_might_have_children;
  bool m_is_expanded = false;
};

class TreeWindowDelegate : public WindowDelegate {
public:
  TreeWindowDelegate(Debugger &debugger, const TreeDelegateSP &delegate_sp)
      : m_debugger(debugger), m_delegate_sp(delegate_sp),
        m_root(nullptr, *delegate_sp, true) {}

  int NumVisibleRows() const { return m_max_y - m_min_y; }

  bool WindowDelegateDraw(Window &window, bool force) override {
    m_min_x = 2;
    m_min_y = 1;
    m_max_x = window.GetWidth() - 1;
    m_max_y = window.GetHeight() - 1;

    window.Erase();
    window.DrawTitleBox(window.GetName());

    if (!m_delegate_sp->TreeDelegateShouldDraw()) {
      m_selected_item = nullptr;
      return true;
    }

    const int num_visible_rows = NumVisibleRows();
    m_num_rows = 0;
    m_root.CalculateRowIndexes(m_num_rows);
    m_delegate_sp->TreeDelegateUpdateSelection(m_root, m_selected_row_idx,
                                               m_selected_item);

    // If we unexpanded while having something selected our total number of
    // rows is less than the num visible rows, then make sure we show all the
    // rows by setting the first visible row accordingly.
    if (m_first_visible_row > 0 && m_num_rows < num_visible_rows)
      m_first_visible_row = 0;

    // Make sure the selected row is always visible
    if (m_selected_row_idx < m_first_visible_row)
      m_first_visible_row = m_selected_row_idx;
    else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx)
      m_first_visible_row = m_selected_row_idx - num_visible_rows + 1;

    int row_idx = 0;
    int num_rows_left = num_visible_rows;
    m_root.Draw(window, m_first_visible_row, m_selected_row_idx, row_idx,
                num_rows_left);
    // Get the selected row
    m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);

    return true; // Drawing handled
  }

  const char *WindowDelegateGetHelpText() override {
    return "Thread window keyboard shortcuts:";
  }

  KeyHelp *WindowDelegateGetKeyHelp() override {
    static curses::KeyHelp g_source_view_key_help[] = {
        {KEY_UP, "Select previous item"},
        {KEY_DOWN, "Select next item"},
        {KEY_RIGHT, "Expand the selected item"},
        {KEY_LEFT,
         "Unexpand the selected item or select parent if not expanded"},
        {KEY_PPAGE, "Page up"},
        {KEY_NPAGE, "Page down"},
        {'h', "Show help dialog"},
        {' ', "Toggle item expansion"},
        {',', "Page up"},
        {'.', "Page down"},
        {'\0', nullptr}};
    return g_source_view_key_help;
  }

  HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
    switch (c) {
    case ',':
    case KEY_PPAGE:
      // Page up key
      if (m_first_visible_row > 0) {
        if (m_first_visible_row > m_max_y)
          m_first_visible_row -= m_max_y;
        else
          m_first_visible_row = 0;
        m_selected_row_idx = m_first_visible_row;
        m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
        if (m_selected_item)
          m_selected_item->ItemWasSelected();
      }
      return eKeyHandled;

    case '.':
    case KEY_NPAGE:
      // Page down key
      if (m_num_rows > m_max_y) {
        if (m_first_visible_row + m_max_y < m_num_rows) {
          m_first_visible_row += m_max_y;
          m_selected_row_idx = m_first_visible_row;
          m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
          if (m_selected_item)
            m_selected_item->ItemWasSelected();
        }
      }
      return eKeyHandled;

    case KEY_UP:
      if (m_selected_row_idx > 0) {
        --m_selected_row_idx;
        m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
        if (m_selected_item)
          m_selected_item->ItemWasSelected();
      }
      return eKeyHandled;

    case KEY_DOWN:
      if (m_selected_row_idx + 1 < m_num_rows) {
        ++m_selected_row_idx;
        m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
        if (m_selected_item)
          m_selected_item->ItemWasSelected();
      }
      return eKeyHandled;

    case KEY_RIGHT:
      if (m_selected_item) {
        if (!m_selected_item->IsExpanded())
          m_selected_item->Expand();
      }
      return eKeyHandled;

    case KEY_LEFT:
      if (m_selected_item) {
        if (m_selected_item->IsExpanded())
          m_selected_item->Unexpand();
        else if (m_selected_item->GetParent()) {
          m_selected_row_idx = m_selected_item->GetParent()->GetRowIndex();
          m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
          if (m_selected_item)
            m_selected_item->ItemWasSelected();
        }
      }
      return eKeyHandled;

    case ' ':
      // Toggle expansion state when SPACE is pressed
      if (m_selected_item) {
        if (m_selected_item->IsExpanded())
          m_selected_item->Unexpand();
        else
          m_selected_item->Expand();
      }
      return eKeyHandled;

    case 'h':
      window.CreateHelpSubwindow();
      return eKeyHandled;

    default:
      break;
    }
    return eKeyNotHandled;
  }

protected:
  Debugger &m_debugger;
  TreeDelegateSP m_delegate_sp;
  TreeItem m_root;
  TreeItem *m_selected_item = nullptr;
  int m_num_rows = 0;
  int m_selected_row_idx = 0;
  int m_first_visible_row = 0;
  int m_min_x = 0;
  int m_min_y = 0;
  int m_max_x = 0;
  int m_max_y = 0;
};

// A tree delegate that just draws the text member of the tree item, it doesn't
// have any children or actions.
class TextTreeDelegate : public TreeDelegate {
public:
  TextTreeDelegate() : TreeDelegate() {}

  ~TextTreeDelegate() override = default;

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    window.PutCStringTruncated(1, item.GetText().c_str());
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {}

  bool TreeDelegateItemSelected(TreeItem &item) override { return false; }
};

class FrameTreeDelegate : public TreeDelegate {
public:
  FrameTreeDelegate() : TreeDelegate() {
    FormatEntity::Parse(
        "#${frame.index}: {${function.name}${function.pc-offset}}}", m_format);
  }

  ~FrameTreeDelegate() override = default;

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    Thread *thread = (Thread *)item.GetUserData();
    if (thread) {
      const uint64_t frame_idx = item.GetIdentifier();
      StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_idx);
      if (frame_sp) {
        StreamString strm;
        const SymbolContext &sc =
            frame_sp->GetSymbolContext(eSymbolContextEverything);
        ExecutionContext exe_ctx(frame_sp);
        if (FormatEntity::Format(m_format, strm, &sc, &exe_ctx, nullptr,
                                 nullptr, false, false)) {
          int right_pad = 1;
          window.PutCStringTruncated(right_pad, strm.GetString().str().c_str());
        }
      }
    }
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {
    // No children for frames yet...
  }

  bool TreeDelegateItemSelected(TreeItem &item) override {
    Thread *thread = (Thread *)item.GetUserData();
    if (thread) {
      thread->GetProcess()->GetThreadList().SetSelectedThreadByID(
          thread->GetID());
      const uint64_t frame_idx = item.GetIdentifier();
      thread->SetSelectedFrameByIndex(frame_idx);
      return true;
    }
    return false;
  }

protected:
  FormatEntity::Entry m_format;
};

class ThreadTreeDelegate : public TreeDelegate {
public:
  ThreadTreeDelegate(Debugger &debugger)
      : TreeDelegate(), m_debugger(debugger) {
    FormatEntity::Parse("thread #${thread.index}: tid = ${thread.id}{, stop "
                        "reason = ${thread.stop-reason}}",
                        m_format);
  }

  ~ThreadTreeDelegate() override = default;

  ProcessSP GetProcess() {
    return m_debugger.GetCommandInterpreter()
        .GetExecutionContext()
        .GetProcessSP();
  }

  ThreadSP GetThread(const TreeItem &item) {
    ProcessSP process_sp = GetProcess();
    if (process_sp)
      return process_sp->GetThreadList().FindThreadByID(item.GetIdentifier());
    return ThreadSP();
  }

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    ThreadSP thread_sp = GetThread(item);
    if (thread_sp) {
      StreamString strm;
      ExecutionContext exe_ctx(thread_sp);
      if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr,
                               nullptr, false, false)) {
        int right_pad = 1;
        window.PutCStringTruncated(right_pad, strm.GetString().str().c_str());
      }
    }
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {
    ProcessSP process_sp = GetProcess();
    if (process_sp && process_sp->IsAlive()) {
      StateType state = process_sp->GetState();
      if (StateIsStoppedState(state, true)) {
        ThreadSP thread_sp = GetThread(item);
        if (thread_sp) {
          if (m_stop_id == process_sp->GetStopID() &&
              thread_sp->GetID() == m_tid)
            return; // Children are already up to date
          if (!m_frame_delegate_sp) {
            // Always expand the thread item the first time we show it
            m_frame_delegate_sp = std::make_shared<FrameTreeDelegate>();
          }

          m_stop_id = process_sp->GetStopID();
          m_tid = thread_sp->GetID();

          TreeItem t(&item, *m_frame_delegate_sp, false);
          size_t num_frames = thread_sp->GetStackFrameCount();
          item.Resize(num_frames, t);
          for (size_t i = 0; i < num_frames; ++i) {
            item[i].SetUserData(thread_sp.get());
            item[i].SetIdentifier(i);
          }
        }
        return;
      }
    }
    item.ClearChildren();
  }

  bool TreeDelegateItemSelected(TreeItem &item) override {
    ProcessSP process_sp = GetProcess();
    if (process_sp && process_sp->IsAlive()) {
      StateType state = process_sp->GetState();
      if (StateIsStoppedState(state, true)) {
        ThreadSP thread_sp = GetThread(item);
        if (thread_sp) {
          ThreadList &thread_list = thread_sp->GetProcess()->GetThreadList();
          std::lock_guard<std::recursive_mutex> guard(thread_list.GetMutex());
          ThreadSP selected_thread_sp = thread_list.GetSelectedThread();
          if (selected_thread_sp->GetID() != thread_sp->GetID()) {
            thread_list.SetSelectedThreadByID(thread_sp->GetID());
            return true;
          }
        }
      }
    }
    return false;
  }

protected:
  Debugger &m_debugger;
  std::shared_ptr<FrameTreeDelegate> m_frame_delegate_sp;
  lldb::user_id_t m_tid = LLDB_INVALID_THREAD_ID;
  uint32_t m_stop_id = UINT32_MAX;
  FormatEntity::Entry m_format;
};

class ThreadsTreeDelegate : public TreeDelegate {
public:
  ThreadsTreeDelegate(Debugger &debugger)
      : TreeDelegate(), m_thread_delegate_sp(), m_debugger(debugger) {
    FormatEntity::Parse("process ${process.id}{, name = ${process.name}}",
                        m_format);
  }

  ~ThreadsTreeDelegate() override = default;

  ProcessSP GetProcess() {
    return m_debugger.GetCommandInterpreter()
        .GetExecutionContext()
        .GetProcessSP();
  }

  bool TreeDelegateShouldDraw() override {
    ProcessSP process = GetProcess();
    if (!process)
      return false;

    if (StateIsRunningState(process->GetState()))
      return false;

    return true;
  }

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    ProcessSP process_sp = GetProcess();
    if (process_sp && process_sp->IsAlive()) {
      StreamString strm;
      ExecutionContext exe_ctx(process_sp);
      if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr,
                               nullptr, false, false)) {
        int right_pad = 1;
        window.PutCStringTruncated(right_pad, strm.GetString().str().c_str());
      }
    }
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {
    ProcessSP process_sp = GetProcess();
    m_update_selection = false;
    if (process_sp && process_sp->IsAlive()) {
      StateType state = process_sp->GetState();
      if (StateIsStoppedState(state, true)) {
        const uint32_t stop_id = process_sp->GetStopID();
        if (m_stop_id == stop_id)
          return; // Children are already up to date

        m_stop_id = stop_id;
        m_update_selection = true;

        if (!m_thread_delegate_sp) {
          // Always expand the thread item the first time we show it
          // item.Expand();
          m_thread_delegate_sp =
              std::make_shared<ThreadTreeDelegate>(m_debugger);
        }

        TreeItem t(&item, *m_thread_delegate_sp, false);
        ThreadList &threads = process_sp->GetThreadList();
        std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
        ThreadSP selected_thread = threads.GetSelectedThread();
        size_t num_threads = threads.GetSize();
        item.Resize(num_threads, t);
        for (size_t i = 0; i < num_threads; ++i) {
          ThreadSP thread = threads.GetThreadAtIndex(i);
          item[i].SetIdentifier(thread->GetID());
          item[i].SetMightHaveChildren(true);
          if (selected_thread->GetID() == thread->GetID())
            item[i].Expand();
        }
        return;
      }
    }
    item.ClearChildren();
  }

  void TreeDelegateUpdateSelection(TreeItem &root, int &selection_index,
                                   TreeItem *&selected_item) override {
    if (!m_update_selection)
      return;

    ProcessSP process_sp = GetProcess();
    if (!(process_sp && process_sp->IsAlive()))
      return;

    StateType state = process_sp->GetState();
    if (!StateIsStoppedState(state, true))
      return;

    ThreadList &threads = process_sp->GetThreadList();
    std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
    ThreadSP selected_thread = threads.GetSelectedThread();
    size_t num_threads = threads.GetSize();
    for (size_t i = 0; i < num_threads; ++i) {
      ThreadSP thread = threads.GetThreadAtIndex(i);
      if (selected_thread->GetID() == thread->GetID()) {
        selected_item =
            &root[i][thread->GetSelectedFrameIndex(SelectMostRelevantFrame)];
        selection_index = selected_item->GetRowIndex();
        return;
      }
    }
  }

  bool TreeDelegateItemSelected(TreeItem &item) override { return false; }

  bool TreeDelegateExpandRootByDefault() override { return true; }

protected:
  std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp;
  Debugger &m_debugger;
  uint32_t m_stop_id = UINT32_MAX;
  bool m_update_selection = false;
  FormatEntity::Entry m_format;
};

class BreakpointLocationTreeDelegate : public TreeDelegate {
public:
  BreakpointLocationTreeDelegate(Debugger &debugger)
      : TreeDelegate(), m_debugger(debugger) {}

  ~BreakpointLocationTreeDelegate() override = default;

  Process *GetProcess() {
    ExecutionContext exe_ctx(
        m_debugger.GetCommandInterpreter().GetExecutionContext());
    return exe_ctx.GetProcessPtr();
  }

  BreakpointLocationSP GetBreakpointLocation(const TreeItem &item) {
    Breakpoint *breakpoint = (Breakpoint *)item.GetUserData();
    return breakpoint->GetLocationAtIndex(item.GetIdentifier());
  }

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    BreakpointLocationSP breakpoint_location = GetBreakpointLocation(item);
    Process *process = GetProcess();
    StreamString stream;
    stream.Printf("%i.%i: ", breakpoint_location->GetBreakpoint().GetID(),
                  breakpoint_location->GetID());
    Address address = breakpoint_location->GetAddress();
    address.Dump(&stream, process, Address::DumpStyleResolvedDescription,
                 Address::DumpStyleInvalid);
    window.PutCStringTruncated(1, stream.GetString().str().c_str());
  }

  StringList ComputeDetailsList(BreakpointLocationSP breakpoint_location) {
    StringList details;

    Address address = breakpoint_location->GetAddress();
    SymbolContext symbol_context;
    address.CalculateSymbolContext(&symbol_context);

    if (symbol_context.module_sp) {
      StreamString module_stream;
      module_stream.PutCString("module = ");
      symbol_context.module_sp->GetFileSpec().Dump(
          module_stream.AsRawOstream());
      details.AppendString(module_stream.GetString());
    }

    if (symbol_context.comp_unit != nullptr) {
      StreamString compile_unit_stream;
      compile_unit_stream.PutCString("compile unit = ");
      symbol_context.comp_unit->GetPrimaryFile().GetFilename().Dump(
          &compile_unit_stream);
      details.AppendString(compile_unit_stream.GetString());

      if (symbol_context.function != nullptr) {
        StreamString function_stream;
        function_stream.PutCString("function = ");
        function_stream.PutCString(
            symbol_context.function->GetName().AsCString("<unknown>"));
        details.AppendString(function_stream.GetString());
      }

      if (symbol_context.line_entry.line > 0) {
        StreamString location_stream;
        location_stream.PutCString("location = ");
        symbol_context.line_entry.DumpStopContext(&location_stream, true);
        details.AppendString(location_stream.GetString());
      }

    } else {
      if (symbol_context.symbol) {
        StreamString symbol_stream;
        if (breakpoint_location->IsReExported())
          symbol_stream.PutCString("re-exported target = ");
        else
          symbol_stream.PutCString("symbol = ");
        symbol_stream.PutCString(
            symbol_context.symbol->GetName().AsCString("<unknown>"));
        details.AppendString(symbol_stream.GetString());
      }
    }

    Process *process = GetProcess();

    StreamString address_stream;
    address.Dump(&address_stream, process, Address::DumpStyleLoadAddress,
                 Address::DumpStyleModuleWithFileAddress);
    details.AppendString(address_stream.GetString());

    BreakpointSiteSP breakpoint_site = breakpoint_location->GetBreakpointSite();
    if (breakpoint_location->IsIndirect() && breakpoint_site) {
      Address resolved_address;
      resolved_address.SetLoadAddress(breakpoint_site->GetLoadAddress(),
                                      &breakpoint_location->GetTarget());
      Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
      if (resolved_symbol) {
        StreamString indirect_target_stream;
        indirect_target_stream.PutCString("indirect target = ");
        indirect_target_stream.PutCString(
            resolved_symbol->GetName().GetCString());
        details.AppendString(indirect_target_stream.GetString());
      }
    }

    bool is_resolved = breakpoint_location->IsResolved();
    StreamString resolved_stream;
    resolved_stream.Printf("resolved = %s", is_resolved ? "true" : "false");
    details.AppendString(resolved_stream.GetString());

    bool is_hardware = is_resolved && breakpoint_site->IsHardware();
    StreamString hardware_stream;
    hardware_stream.Printf("hardware = %s", is_hardware ? "true" : "false");
    details.AppendString(hardware_stream.GetString());

    StreamString hit_count_stream;
    hit_count_stream.Printf("hit count = %-4u",
                            breakpoint_location->GetHitCount());
    details.AppendString(hit_count_stream.GetString());

    return details;
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {
    BreakpointLocationSP breakpoint_location = GetBreakpointLocation(item);
    StringList details = ComputeDetailsList(breakpoint_location);

    if (!m_string_delegate_sp)
      m_string_delegate_sp = std::make_shared<TextTreeDelegate>();
    TreeItem details_tree_item(&item, *m_string_delegate_sp, false);

    item.Resize(details.GetSize(), details_tree_item);
    for (size_t i = 0; i < details.GetSize(); i++) {
      item[i].SetText(details.GetStringAtIndex(i));
    }
  }

  bool TreeDelegateItemSelected(TreeItem &item) override { return false; }

protected:
  Debugger &m_debugger;
  std::shared_ptr<TextTreeDelegate> m_string_delegate_sp;
};

class BreakpointTreeDelegate : public TreeDelegate {
public:
  BreakpointTreeDelegate(Debugger &debugger)
      : TreeDelegate(), m_debugger(debugger),
        m_breakpoint_location_delegate_sp() {}

  ~BreakpointTreeDelegate() override = default;

  BreakpointSP GetBreakpoint(const TreeItem &item) {
    TargetSP target = m_debugger.GetSelectedTarget();
    BreakpointList &breakpoints = target->GetBreakpointList(false);
    return breakpoints.GetBreakpointAtIndex(item.GetIdentifier());
  }

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    BreakpointSP breakpoint = GetBreakpoint(item);
    StreamString stream;
    stream.Format("{0}: ", breakpoint->GetID());
    breakpoint->GetResolverDescription(&stream);
    breakpoint->GetFilterDescription(&stream);
    window.PutCStringTruncated(1, stream.GetString().str().c_str());
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {
    BreakpointSP breakpoint = GetBreakpoint(item);

    if (!m_breakpoint_location_delegate_sp)
      m_breakpoint_location_delegate_sp =
          std::make_shared<BreakpointLocationTreeDelegate>(m_debugger);
    TreeItem breakpoint_location_tree_item(
        &item, *m_breakpoint_location_delegate_sp, true);

    item.Resize(breakpoint->GetNumLocations(), breakpoint_location_tree_item);
    for (size_t i = 0; i < breakpoint->GetNumLocations(); i++) {
      item[i].SetIdentifier(i);
      item[i].SetUserData(breakpoint.get());
    }
  }

  bool TreeDelegateItemSelected(TreeItem &item) override { return false; }

protected:
  Debugger &m_debugger;
  std::shared_ptr<BreakpointLocationTreeDelegate>
      m_breakpoint_location_delegate_sp;
};

class BreakpointsTreeDelegate : public TreeDelegate {
public:
  BreakpointsTreeDelegate(Debugger &debugger)
      : TreeDelegate(), m_debugger(debugger), m_breakpoint_delegate_sp() {}

  ~BreakpointsTreeDelegate() override = default;

  bool TreeDelegateShouldDraw() override {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (!target)
      return false;

    return true;
  }

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    window.PutCString("Breakpoints");
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {
    TargetSP target = m_debugger.GetSelectedTarget();

    BreakpointList &breakpoints = target->GetBreakpointList(false);
    std::unique_lock<std::recursive_mutex> lock;
    breakpoints.GetListMutex(lock);

    if (!m_breakpoint_delegate_sp)
      m_breakpoint_delegate_sp =
          std::make_shared<BreakpointTreeDelegate>(m_debugger);
    TreeItem breakpoint_tree_item(&item, *m_breakpoint_delegate_sp, true);

    item.Resize(breakpoints.GetSize(), breakpoint_tree_item);
    for (size_t i = 0; i < breakpoints.GetSize(); i++) {
      item[i].SetIdentifier(i);
    }
  }

  bool TreeDelegateItemSelected(TreeItem &item) override { return false; }

  bool TreeDelegateExpandRootByDefault() override { return true; }

protected:
  Debugger &m_debugger;
  std::shared_ptr<BreakpointTreeDelegate> m_breakpoint_delegate_sp;
};

class ValueObjectListDelegate : public WindowDelegate {
public:
  ValueObjectListDelegate() : m_rows() {}

  ValueObjectListDelegate(ValueObjectList &valobj_list) : m_rows() {
    SetValues(valobj_list);
  }

  ~ValueObjectListDelegate() override = default;

  void SetValues(ValueObjectList &valobj_list) {
    m_selected_row = nullptr;
    m_selected_row_idx = 0;
    m_first_visible_row = 0;
    m_num_rows = 0;
    m_rows.clear();
    for (auto &valobj_sp : valobj_list.GetObjects())
      m_rows.push_back(Row(valobj_sp, nullptr));
  }

  bool WindowDelegateDraw(Window &window, bool force) override {
    m_num_rows = 0;
    m_min_x = 2;
    m_min_y = 1;
    m_max_x = window.GetWidth() - 1;
    m_max_y = window.GetHeight() - 1;

    window.Erase();
    window.DrawTitleBox(window.GetName());

    const int num_visible_rows = NumVisibleRows();
    const int num_rows = CalculateTotalNumberRows(m_rows);

    // If we unexpanded while having something selected our total number of
    // rows is less than the num visible rows, then make sure we show all the
    // rows by setting the first visible row accordingly.
    if (m_first_visible_row > 0 && num_rows < num_visible_rows)
      m_first_visible_row = 0;

    // Make sure the selected row is always visible
    if (m_selected_row_idx < m_first_visible_row)
      m_first_visible_row = m_selected_row_idx;
    else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx)
      m_first_visible_row = m_selected_row_idx - num_visible_rows + 1;

    DisplayRows(window, m_rows, g_options);

    // Get the selected row
    m_selected_row = GetRowForRowIndex(m_selected_row_idx);
    // Keep the cursor on the selected row so the highlight and the cursor are
    // always on the same line
    if (m_selected_row)
      window.MoveCursor(m_selected_row->x, m_selected_row->y);

    return true; // Drawing handled
  }

  KeyHelp *WindowDelegateGetKeyHelp() override {
    static curses::KeyHelp g_source_view_key_help[] = {
        {KEY_UP, "Select previous item"},
        {KEY_DOWN, "Select next item"},
        {KEY_RIGHT, "Expand selected item"},
        {KEY_LEFT, "Unexpand selected item or select parent if not expanded"},
        {KEY_PPAGE, "Page up"},
        {KEY_NPAGE, "Page down"},
        {'A', "Format as annotated address"},
        {'b', "Format as binary"},
        {'B', "Format as hex bytes with ASCII"},
        {'c', "Format as character"},
        {'d', "Format as a signed integer"},
        {'D', "Format selected value using the default format for the type"},
        {'f', "Format as float"},
        {'h', "Show help dialog"},
        {'i', "Format as instructions"},
        {'o', "Format as octal"},
        {'p', "Format as pointer"},
        {'s', "Format as C string"},
        {'t', "Toggle showing/hiding type names"},
        {'u', "Format as an unsigned integer"},
        {'x', "Format as hex"},
        {'X', "Format as uppercase hex"},
        {' ', "Toggle item expansion"},
        {',', "Page up"},
        {'.', "Page down"},
        {'\0', nullptr}};
    return g_source_view_key_help;
  }

  HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
    switch (c) {
    case 'x':
    case 'X':
    case 'o':
    case 's':
    case 'u':
    case 'd':
    case 'D':
    case 'i':
    case 'A':
    case 'p':
    case 'c':
    case 'b':
    case 'B':
    case 'f':
      // Change the format for the currently selected item
      if (m_selected_row) {
        auto valobj_sp = m_selected_row->value.GetSP();
        if (valobj_sp)
          valobj_sp->SetFormat(FormatForChar(c));
      }
      return eKeyHandled;

    case 't':
      // Toggle showing type names
      g_options.show_types = !g_options.show_types;
      return eKeyHandled;

    case ',':
    case KEY_PPAGE:
      // Page up key
      if (m_first_visible_row > 0) {
        if (static_cast<int>(m_first_visible_row) > m_max_y)
          m_first_visible_row -= m_max_y;
        else
          m_first_visible_row = 0;
        m_selected_row_idx = m_first_visible_row;
      }
      return eKeyHandled;

    case '.':
    case KEY_NPAGE:
      // Page down key
      if (m_num_rows > static_cast<size_t>(m_max_y)) {
        if (m_first_visible_row + m_max_y < m_num_rows) {
          m_first_visible_row += m_max_y;
          m_selected_row_idx = m_first_visible_row;
        }
      }
      return eKeyHandled;

    case KEY_UP:
      if (m_selected_row_idx > 0)
        --m_selected_row_idx;
      return eKeyHandled;

    case KEY_DOWN:
      if (m_selected_row_idx + 1 < m_num_rows)
        ++m_selected_row_idx;
      return eKeyHandled;

    case KEY_RIGHT:
      if (m_selected_row) {
        if (!m_selected_row->expanded)
          m_selected_row->Expand();
      }
      return eKeyHandled;

    case KEY_LEFT:
      if (m_selected_row) {
        if (m_selected_row->expanded)
          m_selected_row->Unexpand();
        else if (m_selected_row->parent)
          m_selected_row_idx = m_selected_row->parent->row_idx;
      }
      return eKeyHandled;

    case ' ':
      // Toggle expansion state when SPACE is pressed
      if (m_selected_row) {
        if (m_selected_row->expanded)
          m_selected_row->Unexpand();
        else
          m_selected_row->Expand();
      }
      return eKeyHandled;

    case 'h':
      window.CreateHelpSubwindow();
      return eKeyHandled;

    default:
      break;
    }
    return eKeyNotHandled;
  }

protected:
  std::vector<Row> m_rows;
  Row *m_selected_row = nullptr;
  uint32_t m_selected_row_idx = 0;
  uint32_t m_first_visible_row = 0;
  uint32_t m_num_rows = 0;
  int m_min_x = 0;
  int m_min_y = 0;
  int m_max_x = 0;
  int m_max_y = 0;

  static Format FormatForChar(int c) {
    switch (c) {
    case 'x':
      return eFormatHex;
    case 'X':
      return eFormatHexUppercase;
    case 'o':
      return eFormatOctal;
    case 's':
      return eFormatCString;
    case 'u':
      return eFormatUnsigned;
    case 'd':
      return eFormatDecimal;
    case 'D':
      return eFormatDefault;
    case 'i':
      return eFormatInstruction;
    case 'A':
      return eFormatAddressInfo;
    case 'p':
      return eFormatPointer;
    case 'c':
      return eFormatChar;
    case 'b':
      return eFormatBinary;
    case 'B':
      return eFormatBytesWithASCII;
    case 'f':
      return eFormatFloat;
    }
    return eFormatDefault;
  }

  bool DisplayRowObject(Window &window, Row &row, DisplayOptions &options,
                        bool highlight, bool last_child) {
    ValueObject *valobj = row.value.GetSP().get();

    if (valobj == nullptr)
      return false;

    const char *type_name =
        options.show_types ? valobj->GetTypeName().GetCString() : nullptr;
    const char *name = valobj->GetName().GetCString();
    const char *value = valobj->GetValueAsCString();
    const char *summary = valobj->GetSummaryAsCString();

    window.MoveCursor(row.x, row.y);

    row.DrawTree(window);

    if (highlight)
      window.AttributeOn(A_REVERSE);

    if (type_name && type_name[0])
      window.PrintfTruncated(1, "(%s) ", type_name);

    if (name && name[0])
      window.PutCStringTruncated(1, name);

    attr_t changd_attr = 0;
    if (valobj->GetValueDidChange())
      changd_attr = COLOR_PAIR(RedOnBlack) | A_BOLD;

    if (value && value[0]) {
      window.PutCStringTruncated(1, " = ");
      if (changd_attr)
        window.AttributeOn(changd_attr);
      window.PutCStringTruncated(1, value);
      if (changd_attr)
        window.AttributeOff(changd_attr);
    }

    if (summary && summary[0]) {
      window.PutCStringTruncated(1, " ");
      if (changd_attr)
        window.AttributeOn(changd_attr);
      window.PutCStringTruncated(1, summary);
      if (changd_attr)
        window.AttributeOff(changd_attr);
    }

    if (highlight)
      window.AttributeOff(A_REVERSE);

    return true;
  }

  void DisplayRows(Window &window, std::vector<Row> &rows,
                   DisplayOptions &options) {
    // >   0x25B7
    // \/  0x25BD

    bool window_is_active = window.IsActive();
    for (auto &row : rows) {
      const bool last_child = row.parent && &rows[rows.size() - 1] == &row;
      // Save the row index in each Row structure
      row.row_idx = m_num_rows;
      if ((m_num_rows >= m_first_visible_row) &&
          ((m_num_rows - m_first_visible_row) <
           static_cast<size_t>(NumVisibleRows()))) {
        row.x = m_min_x;
        row.y = m_num_rows - m_first_visible_row + 1;
        if (DisplayRowObject(window, row, options,
                             window_is_active &&
                                 m_num_rows == m_selected_row_idx,
                             last_child)) {
          ++m_num_rows;
        } else {
          row.x = 0;
          row.y = 0;
        }
      } else {
        row.x = 0;
        row.y = 0;
        ++m_num_rows;
      }

      if (row.expanded) {
        auto &children = row.GetChildren();
        if (!children.empty()) {
          DisplayRows(window, children, options);
        }
      }
    }
  }

  int CalculateTotalNumberRows(std::vector<Row> &rows) {
    int row_count = 0;
    for (auto &row : rows) {
      ++row_count;
      if (row.expanded)
        row_count += CalculateTotalNumberRows(row.GetChildren());
    }
    return row_count;
  }

  static Row *GetRowForRowIndexImpl(std::vector<Row> &rows, size_t &row_index) {
    for (auto &row : rows) {
      if (row_index == 0)
        return &row;
      else {
        --row_index;
        if (row.expanded) {
          auto &children = row.GetChildren();
          if (!children.empty()) {
            Row *result = GetRowForRowIndexImpl(children, row_index);
            if (result)
              return result;
          }
        }
      }
    }
    return nullptr;
  }

  Row *GetRowForRowIndex(size_t row_index) {
    return GetRowForRowIndexImpl(m_rows, row_index);
  }

  int NumVisibleRows() const { return m_max_y - m_min_y; }

  static DisplayOptions g_options;
};

class FrameVariablesWindowDelegate : public ValueObjectListDelegate {
public:
  FrameVariablesWindowDelegate(Debugger &debugger)
      : ValueObjectListDelegate(), m_debugger(debugger) {}

  ~FrameVariablesWindowDelegate() override = default;

  const char *WindowDelegateGetHelpText() override {
    return "Frame variable window keyboard shortcuts:";
  }

  bool WindowDelegateDraw(Window &window, bool force) override {
    ExecutionContext exe_ctx(
        m_debugger.GetCommandInterpreter().GetExecutionContext());
    Process *process = exe_ctx.GetProcessPtr();
    Block *frame_block = nullptr;
    StackFrame *frame = nullptr;

    if (process) {
      StateType state = process->GetState();
      if (StateIsStoppedState(state, true)) {
        frame = exe_ctx.GetFramePtr();
        if (frame)
          frame_block = frame->GetFrameBlock();
      } else if (StateIsRunningState(state)) {
        return true; // Don't do any updating when we are running
      }
    }

    ValueObjectList local_values;
    if (frame_block) {
      // Only update the variables if they have changed
      if (m_frame_block != frame_block) {
        m_frame_block = frame_block;

        VariableList *locals = frame->GetVariableList(true, nullptr);
        if (locals) {
          const DynamicValueType use_dynamic = eDynamicDontRunTarget;
          for (const VariableSP &local_sp : *locals) {
            ValueObjectSP value_sp =
                frame->GetValueObjectForFrameVariable(local_sp, use_dynamic);
            if (value_sp) {
              ValueObjectSP synthetic_value_sp = value_sp->GetSyntheticValue();
              if (synthetic_value_sp)
                local_values.Append(synthetic_value_sp);
              else
                local_values.Append(value_sp);
            }
          }
          // Update the values
          SetValues(local_values);
        }
      }
    } else {
      m_frame_block = nullptr;
      // Update the values with an empty list if there is no frame
      SetValues(local_values);
    }

    return ValueObjectListDelegate::WindowDelegateDraw(window, force);
  }

protected:
  Debugger &m_debugger;
  Block *m_frame_block = nullptr;
};

class RegistersWindowDelegate : public ValueObjectListDelegate {
public:
  RegistersWindowDelegate(Debugger &debugger)
      : ValueObjectListDelegate(), m_debugger(debugger) {}

  ~RegistersWindowDelegate() override = default;

  const char *WindowDelegateGetHelpText() override {
    return "Register window keyboard shortcuts:";
  }

  bool WindowDelegateDraw(Window &window, bool force) override {
    ExecutionContext exe_ctx(
        m_debugger.GetCommandInterpreter().GetExecutionContext());
    StackFrame *frame = exe_ctx.GetFramePtr();

    ValueObjectList value_list;
    if (frame) {
      if (frame->GetStackID() != m_stack_id) {
        m_stack_id = frame->GetStackID();
        RegisterContextSP reg_ctx(frame->GetRegisterContext());
        if (reg_ctx) {
          const uint32_t num_sets = reg_ctx->GetRegisterSetCount();
          for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) {
            value_list.Append(
                ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx));
          }
        }
        SetValues(value_list);
      }
    } else {
      Process *process = exe_ctx.GetProcessPtr();
      if (process && process->IsAlive())
        return true; // Don't do any updating if we are running
      else {
        // Update the values with an empty list if there is no process or the
        // process isn't alive anymore
        SetValues(value_list);
      }
    }
    return ValueObjectListDelegate::WindowDelegateDraw(window, force);
  }

protected:
  Debugger &m_debugger;
  StackID m_stack_id;
};

static const char *CursesKeyToCString(int ch) {
  static char g_desc[32];
  if (ch >= KEY_F0 && ch < KEY_F0 + 64) {
    snprintf(g_desc, sizeof(g_desc), "F%u", ch - KEY_F0);
    return g_desc;
  }
  switch (ch) {
  case KEY_DOWN:
    return "down";
  case KEY_UP:
    return "up";
  case KEY_LEFT:
    return "left";
  case KEY_RIGHT:
    return "right";
  case KEY_HOME:
    return "home";
  case KEY_BACKSPACE:
    return "backspace";
  case KEY_DL:
    return "delete-line";
  case KEY_IL:
    return "insert-line";
  case KEY_DC:
    return "delete-char";
  case KEY_IC:
    return "insert-char";
  case KEY_CLEAR:
    return "clear";
  case KEY_EOS:
    return "clear-to-eos";
  case KEY_EOL:
    return "clear-to-eol";
  case KEY_SF:
    return "scroll-forward";
  case KEY_SR:
    return "scroll-backward";
  case KEY_NPAGE:
    return "page-down";
  case KEY_PPAGE:
    return "page-up";
  case KEY_STAB:
    return "set-tab";
  case KEY_CTAB:
    return "clear-tab";
  case KEY_CATAB:
    return "clear-all-tabs";
  case KEY_ENTER:
    return "enter";
  case KEY_PRINT:
    return "print";
  case KEY_LL:
    return "lower-left key";
  case KEY_A1:
    return "upper left of keypad";
  case KEY_A3:
    return "upper right of keypad";
  case KEY_B2:
    return "center of keypad";
  case KEY_C1:
    return "lower left of keypad";
  case KEY_C3:
    return "lower right of keypad";
  case KEY_BTAB:
    return "back-tab key";
  case KEY_BEG:
    return "begin key";
  case KEY_CANCEL:
    return "cancel key";
  case KEY_CLOSE:
    return "close key";
  case KEY_COMMAND:
    return "command key";
  case KEY_COPY:
    return "copy key";
  case KEY_CREATE:
    return "create key";
  case KEY_END:
    return "end key";
  case KEY_EXIT:
    return "exit key";
  case KEY_FIND:
    return "find key";
  case KEY_HELP:
    return "help key";
  case KEY_MARK:
    return "mark key";
  case KEY_MESSAGE:
    return "message key";
  case KEY_MOVE:
    return "move key";
  case KEY_NEXT:
    return "next key";
  case KEY_OPEN:
    return "open key";
  case KEY_OPTIONS:
    return "options key";
  case KEY_PREVIOUS:
    return "previous key";
  case KEY_REDO:
    return "redo key";
  case KEY_REFERENCE:
    return "reference key";
  case KEY_REFRESH:
    return "refresh key";
  case KEY_REPLACE:
    return "replace key";
  case KEY_RESTART:
    return "restart key";
  case KEY_RESUME:
    return "resume key";
  case KEY_SAVE:
    return "save key";
  case KEY_SBEG:
    return "shifted begin key";
  case KEY_SCANCEL:
    return "shifted cancel key";
  case KEY_SCOMMAND:
    return "shifted command key";
  case KEY_SCOPY:
    return "shifted copy key";
  case KEY_SCREATE:
    return "shifted create key";
  case KEY_SDC:
    return "shifted delete-character key";
  case KEY_SDL:
    return "shifted delete-line key";
  case KEY_SELECT:
    return "select key";
  case KEY_SEND:
    return "shifted end key";
  case KEY_SEOL:
    return "shifted clear-to-end-of-line key";
  case KEY_SEXIT:
    return "shifted exit key";
  case KEY_SFIND:
    return "shifted find key";
  case KEY_SHELP:
    return "shifted help key";
  case KEY_SHOME:
    return "shifted home key";
  case KEY_SIC:
    return "shifted insert-character key";
  case KEY_SLEFT:
    return "shifted left-arrow key";
  case KEY_SMESSAGE:
    return "shifted message key";
  case KEY_SMOVE:
    return "shifted move key";
  case KEY_SNEXT:
    return "shifted next key";
  case KEY_SOPTIONS:
    return "shifted options key";
  case KEY_SPREVIOUS:
    return "shifted previous key";
  case KEY_SPRINT:
    return "shifted print key";
  case KEY_SREDO:
    return "shifted redo key";
  case KEY_SREPLACE:
    return "shifted replace key";
  case KEY_SRIGHT:
    return "shifted right-arrow key";
  case KEY_SRSUME:
    return "shifted resume key";
  case KEY_SSAVE:
    return "shifted save key";
  case KEY_SSUSPEND:
    return "shifted suspend key";
  case KEY_SUNDO:
    return "shifted undo key";
  case KEY_SUSPEND:
    return "suspend key";
  case KEY_UNDO:
    return "undo key";
  case KEY_MOUSE:
    return "Mouse event has occurred";
  case KEY_RESIZE:
    return "Terminal resize event";
#ifdef KEY_EVENT
  case KEY_EVENT:
    return "We were interrupted by an event";
#endif
  case KEY_RETURN:
    return "return";
  case ' ':
    return "space";
  case '\t':
    return "tab";
  case KEY_ESCAPE:
    return "escape";
  default:
    if (llvm::isPrint(ch))
      snprintf(g_desc, sizeof(g_desc), "%c", ch);
    else
      snprintf(g_desc, sizeof(g_desc), "\\x%2.2x", ch);
    return g_desc;
  }
  return nullptr;
}

HelpDialogDelegate::HelpDialogDelegate(const char *text,
                                       KeyHelp *key_help_array)
    : m_text() {
  if (text && text[0]) {
    m_text.SplitIntoLines(text);
    m_text.AppendString("");
  }
  if (key_help_array) {
    for (KeyHelp *key = key_help_array; key->ch; ++key) {
      StreamString key_description;
      key_description.Printf("%10s - %s", CursesKeyToCString(key->ch),
                             key->description);
      m_text.AppendString(key_description.GetString());
    }
  }
}

HelpDialogDelegate::~HelpDialogDelegate() = default;

bool HelpDialogDelegate::WindowDelegateDraw(Window &window, bool force) {
  window.Erase();
  const int window_height = window.GetHeight();
  int x = 2;
  int y = 1;
  const int min_y = y;
  const int max_y = window_height - 1 - y;
  const size_t num_visible_lines = max_y - min_y + 1;
  const size_t num_lines = m_text.GetSize();
  const char *bottom_message;
  if (num_lines <= num_visible_lines)
    bottom_message = "Press any key to exit";
  else
    bottom_message = "Use arrows to scroll, any other key to exit";
  window.DrawTitleBox(window.GetName(), bottom_message);
  while (y <= max_y) {
    window.MoveCursor(x, y);
    window.PutCStringTruncated(
        1, m_text.GetStringAtIndex(m_first_visible_line + y - min_y));
    ++y;
  }
  return true;
}

HandleCharResult HelpDialogDelegate::WindowDelegateHandleChar(Window &window,
                                                              int key) {
  bool done = false;
  const size_t num_lines = m_text.GetSize();
  const size_t num_visible_lines = window.GetHeight() - 2;

  if (num_lines <= num_visible_lines) {
    done = true;
    // If we have all lines visible and don't need scrolling, then any key
    // press will cause us to exit
  } else {
    switch (key) {
    case KEY_UP:
      if (m_first_visible_line > 0)
        --m_first_visible_line;
      break;

    case KEY_DOWN:
      if (m_first_visible_line + num_visible_lines < num_lines)
        ++m_first_visible_line;
      break;

    case KEY_PPAGE:
    case ',':
      if (m_first_visible_line > 0) {
        if (static_cast<size_t>(m_first_visible_line) >= num_visible_lines)
          m_first_visible_line -= num_visible_lines;
        else
          m_first_visible_line = 0;
      }
      break;

    case KEY_NPAGE:
    case '.':
      if (m_first_visible_line + num_visible_lines < num_lines) {
        m_first_visible_line += num_visible_lines;
        if (static_cast<size_t>(m_first_visible_line) > num_lines)
          m_first_visible_line = num_lines - num_visible_lines;
      }
      break;

    default:
      done = true;
      break;
    }
  }
  if (done)
    window.GetParent()->RemoveSubWindow(&window);
  return eKeyHandled;
}

class ApplicationDelegate : public WindowDelegate, public MenuDelegate {
public:
  enum {
    eMenuID_LLDB = 1,
    eMenuID_LLDBAbout,
    eMenuID_LLDBExit,

    eMenuID_Target,
    eMenuID_TargetCreate,
    eMenuID_TargetDelete,

    eMenuID_Process,
    eMenuID_ProcessAttach,
    eMenuID_ProcessDetachResume,
    eMenuID_ProcessDetachSuspended,
    eMenuID_ProcessLaunch,
    eMenuID_ProcessContinue,
    eMenuID_ProcessHalt,
    eMenuID_ProcessKill,

    eMenuID_Thread,
    eMenuID_ThreadStepIn,
    eMenuID_ThreadStepOver,
    eMenuID_ThreadStepOut,

    eMenuID_View,
    eMenuID_ViewBacktrace,
    eMenuID_ViewRegisters,
    eMenuID_ViewSource,
    eMenuID_ViewVariables,
    eMenuID_ViewBreakpoints,

    eMenuID_Help,
    eMenuID_HelpGUIHelp
  };

  ApplicationDelegate(Application &app, Debugger &debugger)
      : WindowDelegate(), MenuDelegate(), m_app(app), m_debugger(debugger) {}

  ~ApplicationDelegate() override = default;

  bool WindowDelegateDraw(Window &window, bool force) override {
    return false; // Drawing not handled, let standard window drawing happen
  }

  HandleCharResult WindowDelegateHandleChar(Window &window, int key) override {
    switch (key) {
    case '\t':
      window.SelectNextWindowAsActive();
      return eKeyHandled;

    case KEY_SHIFT_TAB:
      window.SelectPreviousWindowAsActive();
      return eKeyHandled;

    case 'h':
      window.CreateHelpSubwindow();
      return eKeyHandled;

    case KEY_ESCAPE:
      return eQuitApplication;

    default:
      break;
    }
    return eKeyNotHandled;
  }

  const char *WindowDelegateGetHelpText() override {
    return "Welcome to the LLDB curses GUI.\n\n"
           "Press the TAB key to change the selected view.\n"
           "Each view has its own keyboard shortcuts, press 'h' to open a "
           "dialog to display them.\n\n"
           "Common key bindings for all views:";
  }

  KeyHelp *WindowDelegateGetKeyHelp() override {
    static curses::KeyHelp g_source_view_key_help[] = {
        {'\t', "Select next view"},
        {KEY_BTAB, "Select previous view"},
        {'h', "Show help dialog with view specific key bindings"},
        {',', "Page up"},
        {'.', "Page down"},
        {KEY_UP, "Select previous"},
        {KEY_DOWN, "Select next"},
        {KEY_LEFT, "Unexpand or select parent"},
        {KEY_RIGHT, "Expand"},
        {KEY_PPAGE, "Page up"},
        {KEY_NPAGE, "Page down"},
        {'\0', nullptr}};
    return g_source_view_key_help;
  }

  MenuActionResult MenuDelegateAction(Menu &menu) override {
    switch (menu.GetIdentifier()) {
    case eMenuID_TargetCreate: {
      WindowSP main_window_sp = m_app.GetMainWindow();
      FormDelegateSP form_delegate_sp =
          FormDelegateSP(new TargetCreateFormDelegate(m_debugger));
      Rect bounds = main_window_sp->GetCenteredRect(80, 19);
      WindowSP form_window_sp = main_window_sp->CreateSubWindow(
          form_delegate_sp->GetName().c_str(), bounds, true);
      WindowDelegateSP window_delegate_sp =
          WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
      form_window_sp->SetDelegate(window_delegate_sp);
      return MenuActionResult::Handled;
    }
    case eMenuID_ThreadStepIn: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasThreadScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive() &&
            StateIsStoppedState(process->GetState(), true))
          exe_ctx.GetThreadRef().StepIn(true);
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_ThreadStepOut: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasThreadScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive() &&
            StateIsStoppedState(process->GetState(), true)) {
          Thread *thread = exe_ctx.GetThreadPtr();
          uint32_t frame_idx =
              thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
          exe_ctx.GetThreadRef().StepOut(frame_idx);
        }
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_ThreadStepOver: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasThreadScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive() &&
            StateIsStoppedState(process->GetState(), true))
          exe_ctx.GetThreadRef().StepOver(true);
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_ProcessAttach: {
      WindowSP main_window_sp = m_app.GetMainWindow();
      FormDelegateSP form_delegate_sp = FormDelegateSP(
          new ProcessAttachFormDelegate(m_debugger, main_window_sp));
      Rect bounds = main_window_sp->GetCenteredRect(80, 22);
      WindowSP form_window_sp = main_window_sp->CreateSubWindow(
          form_delegate_sp->GetName().c_str(), bounds, true);
      WindowDelegateSP window_delegate_sp =
          WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
      form_window_sp->SetDelegate(window_delegate_sp);
      return MenuActionResult::Handled;
    }
    case eMenuID_ProcessLaunch: {
      WindowSP main_window_sp = m_app.GetMainWindow();
      FormDelegateSP form_delegate_sp = FormDelegateSP(
          new ProcessLaunchFormDelegate(m_debugger, main_window_sp));
      Rect bounds = main_window_sp->GetCenteredRect(80, 22);
      WindowSP form_window_sp = main_window_sp->CreateSubWindow(
          form_delegate_sp->GetName().c_str(), bounds, true);
      WindowDelegateSP window_delegate_sp =
          WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
      form_window_sp->SetDelegate(window_delegate_sp);
      return MenuActionResult::Handled;
    }

    case eMenuID_ProcessContinue: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasProcessScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive() &&
            StateIsStoppedState(process->GetState(), true))
          process->Resume();
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_ProcessKill: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasProcessScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive())
          process->Destroy(false);
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_ProcessHalt: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasProcessScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive())
          process->Halt();
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_ProcessDetachResume:
    case eMenuID_ProcessDetachSuspended: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasProcessScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive())
          process->Detach(menu.GetIdentifier() ==
                          eMenuID_ProcessDetachSuspended);
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_Process: {
      // Populate the menu with all of the threads if the process is stopped
      // when the Process menu gets selected and is about to display its
      // submenu.
      Menus &submenus = menu.GetSubmenus();
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      Process *process = exe_ctx.GetProcessPtr();
      if (process && process->IsAlive() &&
          StateIsStoppedState(process->GetState(), true)) {
        if (submenus.size() == 7)
          menu.AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
        else if (submenus.size() > 8)
          submenus.erase(submenus.begin() + 8, submenus.end());

        ThreadList &threads = process->GetThreadList();
        std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
        size_t num_threads = threads.GetSize();
        for (size_t i = 0; i < num_threads; ++i) {
          ThreadSP thread_sp = threads.GetThreadAtIndex(i);
          char menu_char = '\0';
          if (i < 9)
            menu_char = '1' + i;
          StreamString thread_menu_title;
          thread_menu_title.Printf("Thread %u", thread_sp->GetIndexID());
          const char *thread_name = thread_sp->GetName();
          if (thread_name && thread_name[0])
            thread_menu_title.Printf(" %s", thread_name);
          else {
            const char *queue_name = thread_sp->GetQueueName();
            if (queue_name && queue_name[0])
              thread_menu_title.Printf(" %s", queue_name);
          }
          menu.AddSubmenu(
              MenuSP(new Menu(thread_menu_title.GetString().str().c_str(),
                              nullptr, menu_char, thread_sp->GetID())));
        }
      } else if (submenus.size() > 7) {
        // Remove the separator and any other thread submenu items that were
        // previously added
        submenus.erase(submenus.begin() + 7, submenus.end());
      }
      // Since we are adding and removing items we need to recalculate the
      // name lengths
      menu.RecalculateNameLengths();
    }
      return MenuActionResult::Handled;

    case eMenuID_ViewVariables: {
      WindowSP main_window_sp = m_app.GetMainWindow();
      WindowSP source_window_sp = main_window_sp->FindSubWindow("Source");
      WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables");
      WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers");
      const Rect source_bounds = source_window_sp->GetBounds();

      if (variables_window_sp) {
        const Rect variables_bounds = variables_window_sp->GetBounds();

        main_window_sp->RemoveSubWindow(variables_window_sp.get());

        if (registers_window_sp) {
          // We have a registers window, so give all the area back to the
          // registers window
          Rect registers_bounds = variables_bounds;
          registers_bounds.size.width = source_bounds.size.width;
          registers_window_sp->SetBounds(registers_bounds);
        } else {
          // We have no registers window showing so give the bottom area back
          // to the source view
          source_window_sp->Resize(source_bounds.size.width,
                                   source_bounds.size.height +
                                       variables_bounds.size.height);
        }
      } else {
        Rect new_variables_rect;
        if (registers_window_sp) {
          // We have a registers window so split the area of the registers
          // window into two columns where the left hand side will be the
          // variables and the right hand side will be the registers
          const Rect variables_bounds = registers_window_sp->GetBounds();
          Rect new_registers_rect;
          variables_bounds.VerticalSplitPercentage(0.50, new_variables_rect,
                                                   new_registers_rect);
          registers_window_sp->SetBounds(new_registers_rect);
        } else {
          // No registers window, grab the bottom part of the source window
          Rect new_source_rect;
          source_bounds.HorizontalSplitPercentage(0.70, new_source_rect,
                                                  new_variables_rect);
          source_window_sp->SetBounds(new_source_rect);
        }
        WindowSP new_window_sp = main_window_sp->CreateSubWindow(
            "Variables", new_variables_rect, false);
        new_window_sp->SetDelegate(
            WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
      }
      touchwin(stdscr);
    }
      return MenuActionResult::Handled;

    case eMenuID_ViewRegisters: {
      WindowSP main_window_sp = m_app.GetMainWindow();
      WindowSP source_window_sp = main_window_sp->FindSubWindow("Source");
      WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables");
      WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers");
      const Rect source_bounds = source_window_sp->GetBounds();

      if (registers_window_sp) {
        if (variables_window_sp) {
          const Rect variables_bounds = variables_window_sp->GetBounds();

          // We have a variables window, so give all the area back to the
          // variables window
          variables_window_sp->Resize(variables_bounds.size.width +
                                          registers_window_sp->GetWidth(),
                                      variables_bounds.size.height);
        } else {
          // We have no variables window showing so give the bottom area back
          // to the source view
          source_window_sp->Resize(source_bounds.size.width,
                                   source_bounds.size.height +
                                       registers_window_sp->GetHeight());
        }
        main_window_sp->RemoveSubWindow(registers_window_sp.get());
      } else {
        Rect new_regs_rect;
        if (variables_window_sp) {
          // We have a variables window, split it into two columns where the
          // left hand side will be the variables and the right hand side will
          // be the registers
          const Rect variables_bounds = variables_window_sp->GetBounds();
          Rect new_vars_rect;
          variables_bounds.VerticalSplitPercentage(0.50, new_vars_rect,
                                                   new_regs_rect);
          variables_window_sp->SetBounds(new_vars_rect);
        } else {
          // No variables window, grab the bottom part of the source window
          Rect new_source_rect;
          source_bounds.HorizontalSplitPercentage(0.70, new_source_rect,
                                                  new_regs_rect);
          source_window_sp->SetBounds(new_source_rect);
        }
        WindowSP new_window_sp =
            main_window_sp->CreateSubWindow("Registers", new_regs_rect, false);
        new_window_sp->SetDelegate(
            WindowDelegateSP(new RegistersWindowDelegate(m_debugger)));
      }
      touchwin(stdscr);
    }
      return MenuActionResult::Handled;

    case eMenuID_ViewBreakpoints: {
      WindowSP main_window_sp = m_app.GetMainWindow();
      WindowSP threads_window_sp = main_window_sp->FindSubWindow("Threads");
      WindowSP breakpoints_window_sp =
          main_window_sp->FindSubWindow("Breakpoints");
      const Rect threads_bounds = threads_window_sp->GetBounds();

      // If a breakpoints window already exists, remove it and give the area
      // it used to occupy to the threads window. If it doesn't exist, split
      // the threads window horizontally into two windows where the top window
      // is the threads window and the bottom window is a newly added
      // breakpoints window.
      if (breakpoints_window_sp) {
        threads_window_sp->Resize(threads_bounds.size.width,
                                  threads_bounds.size.height +
                                      breakpoints_window_sp->GetHeight());
        main_window_sp->RemoveSubWindow(breakpoints_window_sp.get());
      } else {
        Rect new_threads_bounds, breakpoints_bounds;
        threads_bounds.HorizontalSplitPercentage(0.70, new_threads_bounds,
                                                 breakpoints_bounds);
        threads_window_sp->SetBounds(new_threads_bounds);
        breakpoints_window_sp = main_window_sp->CreateSubWindow(
            "Breakpoints", breakpoints_bounds, false);
        TreeDelegateSP breakpoints_delegate_sp(
            new BreakpointsTreeDelegate(m_debugger));
        breakpoints_window_sp->SetDelegate(WindowDelegateSP(
            new TreeWindowDelegate(m_debugger, breakpoints_delegate_sp)));
      }
      touchwin(stdscr);
      return MenuActionResult::Handled;
    }

    case eMenuID_HelpGUIHelp:
      m_app.GetMainWindow()->CreateHelpSubwindow();
      return MenuActionResult::Handled;

    default:
      break;
    }

    return MenuActionResult::NotHandled;
  }

protected:
  Application &m_app;
  Debugger &m_debugger;
};

class StatusBarWindowDelegate : public WindowDelegate {
public:
  StatusBarWindowDelegate(Debugger &debugger) : m_debugger(debugger) {
    FormatEntity::Parse("Thread: ${thread.id%tid}", m_format);
  }

  ~StatusBarWindowDelegate() override = default;

  bool WindowDelegateDraw(Window &window, bool force) override {
    ExecutionContext exe_ctx =
        m_debugger.GetCommandInterpreter().GetExecutionContext();
    Process *process = exe_ctx.GetProcessPtr();
    Thread *thread = exe_ctx.GetThreadPtr();
    StackFrame *frame = exe_ctx.GetFramePtr();
    window.Erase();
    window.SetBackground(BlackOnWhite);
    window.MoveCursor(0, 0);
    if (process) {
      const StateType state = process->GetState();
      window.Printf("Process: %5" PRIu64 " %10s", process->GetID(),
                    StateAsCString(state));

      if (StateIsStoppedState(state, true)) {
        StreamString strm;
        if (thread && FormatEntity::Format(m_format, strm, nullptr, &exe_ctx,
                                           nullptr, nullptr, false, false)) {
          window.MoveCursor(40, 0);
          window.PutCStringTruncated(1, strm.GetString().str().c_str());
        }

        window.MoveCursor(60, 0);
        if (frame)
          window.Printf("Frame: %3u  PC = 0x%16.16" PRIx64,
                        frame->GetFrameIndex(),
                        frame->GetFrameCodeAddress().GetOpcodeLoadAddress(
                            exe_ctx.GetTargetPtr()));
      } else if (state == eStateExited) {
        const char *exit_desc = process->GetExitDescription();
        const int exit_status = process->GetExitStatus();
        if (exit_desc && exit_desc[0])
          window.Printf(" with status = %i (%s)", exit_status, exit_desc);
        else
          window.Printf(" with status = %i", exit_status);
      }
    }
    return true;
  }

protected:
  Debugger &m_debugger;
  FormatEntity::Entry m_format;
};

class SourceFileWindowDelegate : public WindowDelegate {
public:
  SourceFileWindowDelegate(Debugger &debugger)
      : WindowDelegate(), m_debugger(debugger), m_sc(), m_file_sp(),
        m_disassembly_sp(), m_disassembly_range(), m_title() {}

  ~SourceFileWindowDelegate() override = default;

  void Update(const SymbolContext &sc) { m_sc = sc; }

  uint32_t NumVisibleLines() const { return m_max_y - m_min_y; }

  const char *WindowDelegateGetHelpText() override {
    return "Source/Disassembly window keyboard shortcuts:";
  }

  KeyHelp *WindowDelegateGetKeyHelp() override {
    static curses::KeyHelp g_source_view_key_help[] = {
        {KEY_RETURN, "Run to selected line with one shot breakpoint"},
        {KEY_UP, "Select previous source line"},
        {KEY_DOWN, "Select next source line"},
        {KEY_LEFT, "Scroll to the left"},
        {KEY_RIGHT, "Scroll to the right"},
        {KEY_PPAGE, "Page up"},
        {KEY_NPAGE, "Page down"},
        {'b', "Set breakpoint on selected source/disassembly line"},
        {'c', "Continue process"},
        {'D', "Detach with process suspended"},
        {'h', "Show help dialog"},
        {'n', "Step over (source line)"},
        {'N', "Step over (single instruction)"},
        {'f', "Step out (finish)"},
        {'s', "Step in (source line)"},
        {'S', "Step in (single instruction)"},
        {'u', "Frame up"},
        {'d', "Frame down"},
        {',', "Page up"},
        {'.', "Page down"},
        {'\0', nullptr}};
    return g_source_view_key_help;
  }

  bool WindowDelegateDraw(Window &window, bool force) override {
    ExecutionContext exe_ctx =
        m_debugger.GetCommandInterpreter().GetExecutionContext();
    Process *process = exe_ctx.GetProcessPtr();
    Thread *thread = nullptr;

    bool update_location = false;
    if (process) {
      StateType state = process->GetState();
      if (StateIsStoppedState(state, true)) {
        // We are stopped, so it is ok to
        update_location = true;
      }
    }

    m_min_x = 1;
    m_min_y = 2;
    m_max_x = window.GetMaxX() - 1;
    m_max_y = window.GetMaxY() - 1;

    const uint32_t num_visible_lines = NumVisibleLines();
    StackFrameSP frame_sp;
    bool set_selected_line_to_pc = false;

    if (update_location) {
      const bool process_alive = process->IsAlive();
      bool thread_changed = false;
      if (process_alive) {
        thread = exe_ctx.GetThreadPtr();
        if (thread) {
          frame_sp = thread->GetSelectedFrame(SelectMostRelevantFrame);
          auto tid = thread->GetID();
          thread_changed = tid != m_tid;
          m_tid = tid;
        } else {
          if (m_tid != LLDB_INVALID_THREAD_ID) {
            thread_changed = true;
            m_tid = LLDB_INVALID_THREAD_ID;
          }
        }
      }
      const uint32_t stop_id = process ? process->GetStopID() : 0;
      const bool stop_id_changed = stop_id != m_stop_id;
      bool frame_changed = false;
      m_stop_id = stop_id;
      m_title.Clear();
      if (frame_sp) {
        m_sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
        if (m_sc.module_sp) {
          m_title.Printf(
              "%s", m_sc.module_sp->GetFileSpec().GetFilename().GetCString());
          ConstString func_name = m_sc.GetFunctionName();
          if (func_name)
            m_title.Printf("`%s", func_name.GetCString());
        }
        const uint32_t frame_idx = frame_sp->GetFrameIndex();
        frame_changed = frame_idx != m_frame_idx;
        m_frame_idx = frame_idx;
      } else {
        m_sc.Clear(true);
        frame_changed = m_frame_idx != UINT32_MAX;
        m_frame_idx = UINT32_MAX;
      }

      const bool context_changed =
          thread_changed || frame_changed || stop_id_changed;

      if (process_alive) {
        if (m_sc.line_entry.IsValid()) {
          m_pc_line = m_sc.line_entry.line;
          if (m_pc_line != UINT32_MAX)
            --m_pc_line; // Convert to zero based line number...
          // Update the selected line if the stop ID changed...
          if (context_changed)
            m_selected_line = m_pc_line;

          if (m_file_sp && m_file_sp->GetFileSpec() == m_sc.line_entry.file) {
            // Same file, nothing to do, we should either have the lines or
            // not (source file missing)
            if (m_selected_line >= static_cast<size_t>(m_first_visible_line)) {
              if (m_selected_line >= m_first_visible_line + num_visible_lines)
                m_first_visible_line = m_selected_line - 10;
            } else {
              if (m_selected_line > 10)
                m_first_visible_line = m_selected_line - 10;
              else
                m_first_visible_line = 0;
            }
          } else {
            // File changed, set selected line to the line with the PC
            m_selected_line = m_pc_line;
            m_file_sp =
                m_debugger.GetSourceManager().GetFile(m_sc.line_entry.file);
            if (m_file_sp) {
              const size_t num_lines = m_file_sp->GetNumLines();
              m_line_width = 1;
              for (size_t n = num_lines; n >= 10; n = n / 10)
                ++m_line_width;

              if (num_lines < num_visible_lines ||
                  m_selected_line < num_visible_lines)
                m_first_visible_line = 0;
              else
                m_first_visible_line = m_selected_line - 10;
            }
          }
        } else {
          m_file_sp.reset();
        }

        if (!m_file_sp || m_file_sp->GetNumLines() == 0) {
          // Show disassembly
          bool prefer_file_cache = false;
          if (m_sc.function) {
            if (m_disassembly_scope != m_sc.function) {
              m_disassembly_scope = m_sc.function;
              m_disassembly_sp = m_sc.function->GetInstructions(
                  exe_ctx, nullptr, !prefer_file_cache);
              if (m_disassembly_sp) {
                set_selected_line_to_pc = true;
                m_disassembly_range = m_sc.function->GetAddressRange();
              } else {
                m_disassembly_range.Clear();
              }
            } else {
              set_selected_line_to_pc = context_changed;
            }
          } else if (m_sc.symbol) {
            if (m_disassembly_scope != m_sc.symbol) {
              m_disassembly_scope = m_sc.symbol;
              m_disassembly_sp = m_sc.symbol->GetInstructions(
                  exe_ctx, nullptr, prefer_file_cache);
              if (m_disassembly_sp) {
                set_selected_line_to_pc = true;
                m_disassembly_range.GetBaseAddress() =
                    m_sc.symbol->GetAddress();
                m_disassembly_range.SetByteSize(m_sc.symbol->GetByteSize());
              } else {
                m_disassembly_range.Clear();
              }
            } else {
              set_selected_line_to_pc = context_changed;
            }
          }
        }
      } else {
        m_pc_line = UINT32_MAX;
      }
    }

    const int window_width = window.GetWidth();
    window.Erase();
    window.DrawTitleBox("Sources");
    if (!m_title.GetString().empty()) {
      window.AttributeOn(A_REVERSE);
      window.MoveCursor(1, 1);
      window.PutChar(' ');
      window.PutCStringTruncated(1, m_title.GetString().str().c_str());
      int x = window.GetCursorX();
      if (x < window_width - 1) {
        window.Printf("%*s", window_width - x - 1, "");
      }
      window.AttributeOff(A_REVERSE);
    }

    Target *target = exe_ctx.GetTargetPtr();
    const size_t num_source_lines = GetNumSourceLines();
    if (num_source_lines > 0) {
      // Display source
      BreakpointLines bp_lines;
      if (target) {
        BreakpointList &bp_list = target->GetBreakpointList();
        const size_t num_bps = bp_list.GetSize();
        for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
          BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
          const size_t num_bps_locs = bp_sp->GetNumLocations();
          for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; ++bp_loc_idx) {
            BreakpointLocationSP bp_loc_sp =
                bp_sp->GetLocationAtIndex(bp_loc_idx);
            LineEntry bp_loc_line_entry;
            if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry(
                    bp_loc_line_entry)) {
              if (m_file_sp->GetFileSpec() == bp_loc_line_entry.file) {
                bp_lines.insert(bp_loc_line_entry.line);
              }
            }
          }
        }
      }

      for (size_t i = 0; i < num_visible_lines; ++i) {
        const uint32_t curr_line = m_first_visible_line + i;
        if (curr_line < num_source_lines) {
          const int line_y = m_min_y + i;
          window.MoveCursor(1, line_y);
          const bool is_pc_line = curr_line == m_pc_line;
          const bool line_is_selected = m_selected_line == curr_line;
          // Highlight the line as the PC line first (done by passing
          // argument to OutputColoredStringTruncated()), then if the selected
          // line isn't the same as the PC line, highlight it differently.
          attr_t highlight_attr = 0;
          attr_t bp_attr = 0;
          if (line_is_selected && !is_pc_line)
            highlight_attr = A_REVERSE;

          if (bp_lines.find(curr_line + 1) != bp_lines.end())
            bp_attr = COLOR_PAIR(BlackOnWhite);

          if (bp_attr)
            window.AttributeOn(bp_attr);

          window.Printf(" %*u ", m_line_width, curr_line + 1);

          if (bp_attr)
            window.AttributeOff(bp_attr);

          window.PutChar(ACS_VLINE);
          // Mark the line with the PC with a diamond
          if (is_pc_line)
            window.PutChar(ACS_DIAMOND);
          else
            window.PutChar(' ');

          if (highlight_attr)
            window.AttributeOn(highlight_attr);

          StreamString lineStream;

          std::optional<size_t> column;
          if (is_pc_line && m_sc.line_entry.IsValid() && m_sc.line_entry.column)
            column = m_sc.line_entry.column - 1;
          m_file_sp->DisplaySourceLines(curr_line + 1, column, 0, 0,
                                        &lineStream);
          StringRef line = lineStream.GetString();
          if (line.endswith("\n"))
            line = line.drop_back();
          bool wasWritten = window.OutputColoredStringTruncated(
              1, line, m_first_visible_column, is_pc_line);
          if (!wasWritten && (line_is_selected || is_pc_line)) {
            // Draw an empty space to show the selected/PC line if empty,
            // or draw '<' if nothing is visible because of scrolling too much
            // to the right.
            window.PutCStringTruncated(
                1, line.empty() && m_first_visible_column == 0 ? " " : "<");
          }

          if (is_pc_line && frame_sp &&
              frame_sp->GetConcreteFrameIndex() == 0) {
            StopInfoSP stop_info_sp;
            if (thread)
              stop_info_sp = thread->GetStopInfo();
            if (stop_info_sp) {
              const char *stop_description = stop_info_sp->GetDescription();
              if (stop_description && stop_description[0]) {
                size_t stop_description_len = strlen(stop_description);
                int desc_x = window_width - stop_description_len - 16;
                if (desc_x - window.GetCursorX() > 0)
                  window.Printf("%*s", desc_x - window.GetCursorX(), "");
                window.MoveCursor(window_width - stop_description_len - 16,
                                  line_y);
                const attr_t stop_reason_attr = COLOR_PAIR(WhiteOnBlue);
                window.AttributeOn(stop_reason_attr);
                window.PrintfTruncated(1, " <<< Thread %u: %s ",
                                       thread->GetIndexID(), stop_description);
                window.AttributeOff(stop_reason_attr);
              }
            } else {
              window.Printf("%*s", window_width - window.GetCursorX() - 1, "");
            }
          }
          if (highlight_attr)
            window.AttributeOff(highlight_attr);
        } else {
          break;
        }
      }
    } else {
      size_t num_disassembly_lines = GetNumDisassemblyLines();
      if (num_disassembly_lines > 0) {
        // Display disassembly
        BreakpointAddrs bp_file_addrs;
        Target *target = exe_ctx.GetTargetPtr();
        if (target) {
          BreakpointList &bp_list = target->GetBreakpointList();
          const size_t num_bps = bp_list.GetSize();
          for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
            BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
            const size_t num_bps_locs = bp_sp->GetNumLocations();
            for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs;
                 ++bp_loc_idx) {
              BreakpointLocationSP bp_loc_sp =
                  bp_sp->GetLocationAtIndex(bp_loc_idx);
              LineEntry bp_loc_line_entry;
              const lldb::addr_t file_addr =
                  bp_loc_sp->GetAddress().GetFileAddress();
              if (file_addr != LLDB_INVALID_ADDRESS) {
                if (m_disassembly_range.ContainsFileAddress(file_addr))
                  bp_file_addrs.insert(file_addr);
              }
            }
          }
        }

        const attr_t selected_highlight_attr = A_REVERSE;
        const attr_t pc_highlight_attr = COLOR_PAIR(WhiteOnBlue);

        StreamString strm;

        InstructionList &insts = m_disassembly_sp->GetInstructionList();
        Address pc_address;

        if (frame_sp)
          pc_address = frame_sp->GetFrameCodeAddress();
        const uint32_t pc_idx =
            pc_address.IsValid()
                ? insts.GetIndexOfInstructionAtAddress(pc_address)
                : UINT32_MAX;
        if (set_selected_line_to_pc) {
          m_selected_line = pc_idx;
        }

        const uint32_t non_visible_pc_offset = (num_visible_lines / 5);
        if (static_cast<size_t>(m_first_visible_line) >= num_disassembly_lines)
          m_first_visible_line = 0;

        if (pc_idx < num_disassembly_lines) {
          if (pc_idx < static_cast<uint32_t>(m_first_visible_line) ||
              pc_idx >= m_first_visible_line + num_visible_lines)
            m_first_visible_line = pc_idx - non_visible_pc_offset;
        }

        for (size_t i = 0; i < num_visible_lines; ++i) {
          const uint32_t inst_idx = m_first_visible_line + i;
          Instruction *inst = insts.GetInstructionAtIndex(inst_idx).get();
          if (!inst)
            break;

          const int line_y = m_min_y + i;
          window.MoveCursor(1, line_y);
          const bool is_pc_line = frame_sp && inst_idx == pc_idx;
          const bool line_is_selected = m_selected_line == inst_idx;
          // Highlight the line as the PC line first, then if the selected
          // line isn't the same as the PC line, highlight it differently
          attr_t highlight_attr = 0;
          attr_t bp_attr = 0;
          if (is_pc_line)
            highlight_attr = pc_highlight_attr;
          else if (line_is_selected)
            highlight_attr = selected_highlight_attr;

          if (bp_file_addrs.find(inst->GetAddress().GetFileAddress()) !=
              bp_file_addrs.end())
            bp_attr = COLOR_PAIR(BlackOnWhite);

          if (bp_attr)
            window.AttributeOn(bp_attr);

          window.Printf(" 0x%16.16llx ",
                        static_cast<unsigned long long>(
                            inst->GetAddress().GetLoadAddress(target)));

          if (bp_attr)
            window.AttributeOff(bp_attr);

          window.PutChar(ACS_VLINE);
          // Mark the line with the PC with a diamond
          if (is_pc_line)
            window.PutChar(ACS_DIAMOND);
          else
            window.PutChar(' ');

          if (highlight_attr)
            window.AttributeOn(highlight_attr);

          const char *mnemonic = inst->GetMnemonic(&exe_ctx);
          const char *operands = inst->GetOperands(&exe_ctx);
          const char *comment = inst->GetComment(&exe_ctx);

          if (mnemonic != nullptr && mnemonic[0] == '\0')
            mnemonic = nullptr;
          if (operands != nullptr && operands[0] == '\0')
            operands = nullptr;
          if (comment != nullptr && comment[0] == '\0')
            comment = nullptr;

          strm.Clear();

          if (mnemonic != nullptr && operands != nullptr && comment != nullptr)
            strm.Printf("%-8s %-25s ; %s", mnemonic, operands, comment);
          else if (mnemonic != nullptr && operands != nullptr)
            strm.Printf("%-8s %s", mnemonic, operands);
          else if (mnemonic != nullptr)
            strm.Printf("%s", mnemonic);

          int right_pad = 1;
          window.PutCStringTruncated(
              right_pad,
              strm.GetString().substr(m_first_visible_column).data());

          if (is_pc_line && frame_sp &&
              frame_sp->GetConcreteFrameIndex() == 0) {
            StopInfoSP stop_info_sp;
            if (thread)
              stop_info_sp = thread->GetStopInfo();
            if (stop_info_sp) {
              const char *stop_description = stop_info_sp->GetDescription();
              if (stop_description && stop_description[0]) {
                size_t stop_description_len = strlen(stop_description);
                int desc_x = window_width - stop_description_len - 16;
                if (desc_x - window.GetCursorX() > 0)
                  window.Printf("%*s", desc_x - window.GetCursorX(), "");
                window.MoveCursor(window_width - stop_description_len - 15,
                                  line_y);
                if (thread)
                  window.PrintfTruncated(1, "<<< Thread %u: %s ",
                                         thread->GetIndexID(),
                                         stop_description);
              }
            } else {
              window.Printf("%*s", window_width - window.GetCursorX() - 1, "");
            }
          }
          if (highlight_attr)
            window.AttributeOff(highlight_attr);
        }
      }
    }
    return true; // Drawing handled
  }

  size_t GetNumLines() {
    size_t num_lines = GetNumSourceLines();
    if (num_lines == 0)
      num_lines = GetNumDisassemblyLines();
    return num_lines;
  }

  size_t GetNumSourceLines() const {
    if (m_file_sp)
      return m_file_sp->GetNumLines();
    return 0;
  }

  size_t GetNumDisassemblyLines() const {
    if (m_disassembly_sp)
      return m_disassembly_sp->GetInstructionList().GetSize();
    return 0;
  }

  HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
    const uint32_t num_visible_lines = NumVisibleLines();
    const size_t num_lines = GetNumLines();

    switch (c) {
    case ',':
    case KEY_PPAGE:
      // Page up key
      if (static_cast<uint32_t>(m_first_visible_line) > num_visible_lines)
        m_first_visible_line -= num_visible_lines;
      else
        m_first_visible_line = 0;
      m_selected_line = m_first_visible_line;
      return eKeyHandled;

    case '.':
    case KEY_NPAGE:
      // Page down key
      {
        if (m_first_visible_line + num_visible_lines < num_lines)
          m_first_visible_line += num_visible_lines;
        else if (num_lines < num_visible_lines)
          m_first_visible_line = 0;
        else
          m_first_visible_line = num_lines - num_visible_lines;
        m_selected_line = m_first_visible_line;
      }
      return eKeyHandled;

    case KEY_UP:
      if (m_selected_line > 0) {
        m_selected_line--;
        if (static_cast<size_t>(m_first_visible_line) > m_selected_line)
          m_first_visible_line = m_selected_line;
      }
      return eKeyHandled;

    case KEY_DOWN:
      if (m_selected_line + 1 < num_lines) {
        m_selected_line++;
        if (m_first_visible_line + num_visible_lines < m_selected_line)
          m_first_visible_line++;
      }
      return eKeyHandled;

    case KEY_LEFT:
      if (m_first_visible_column > 0)
        --m_first_visible_column;
      return eKeyHandled;

    case KEY_RIGHT:
      ++m_first_visible_column;
      return eKeyHandled;

    case '\r':
    case '\n':
    case KEY_ENTER:
      // Set a breakpoint and run to the line using a one shot breakpoint
      if (GetNumSourceLines() > 0) {
        ExecutionContext exe_ctx =
            m_debugger.GetCommandInterpreter().GetExecutionContext();
        if (exe_ctx.HasProcessScope() && exe_ctx.GetProcessRef().IsAlive()) {
          BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
              nullptr, // Don't limit the breakpoint to certain modules
              m_file_sp->GetFileSpec(), // Source file
              m_selected_line +
                  1, // Source line number (m_selected_line is zero based)
              0,     // Unspecified column.
              0,     // No offset
              eLazyBoolCalculate,  // Check inlines using global setting
              eLazyBoolCalculate,  // Skip prologue using global setting,
              false,               // internal
              false,               // request_hardware
              eLazyBoolCalculate); // move_to_nearest_code
          // Make breakpoint one shot
          bp_sp->GetOptions().SetOneShot(true);
          exe_ctx.GetProcessRef().Resume();
        }
      } else if (m_selected_line < GetNumDisassemblyLines()) {
        const Instruction *inst = m_disassembly_sp->GetInstructionList()
                                      .GetInstructionAtIndex(m_selected_line)
                                      .get();
        ExecutionContext exe_ctx =
            m_debugger.GetCommandInterpreter().GetExecutionContext();
        if (exe_ctx.HasTargetScope()) {
          Address addr = inst->GetAddress();
          BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
              addr,   // lldb_private::Address
              false,  // internal
              false); // request_hardware
          // Make breakpoint one shot
          bp_sp->GetOptions().SetOneShot(true);
          exe_ctx.GetProcessRef().Resume();
        }
      }
      return eKeyHandled;

    case 'b': // 'b' == toggle breakpoint on currently selected line
      ToggleBreakpointOnSelectedLine();
      return eKeyHandled;

    case 'D': // 'D' == detach and keep stopped
    {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasProcessScope())
        exe_ctx.GetProcessRef().Detach(true);
    }
      return eKeyHandled;

    case 'c':
      // 'c' == continue
      {
        ExecutionContext exe_ctx =
            m_debugger.GetCommandInterpreter().GetExecutionContext();
        if (exe_ctx.HasProcessScope())
          exe_ctx.GetProcessRef().Resume();
      }
      return eKeyHandled;

    case 'f':
      // 'f' == step out (finish)
      {
        ExecutionContext exe_ctx =
            m_debugger.GetCommandInterpreter().GetExecutionContext();
        if (exe_ctx.HasThreadScope() &&
            StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
          Thread *thread = exe_ctx.GetThreadPtr();
          uint32_t frame_idx =
              thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
          exe_ctx.GetThreadRef().StepOut(frame_idx);
        }
      }
      return eKeyHandled;

    case 'n': // 'n' == step over
    case 'N': // 'N' == step over instruction
    {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasThreadScope() &&
          StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
        bool source_step = (c == 'n');
        exe_ctx.GetThreadRef().StepOver(source_step);
      }
    }
      return eKeyHandled;

    case 's': // 's' == step into
    case 'S': // 'S' == step into instruction
    {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasThreadScope() &&
          StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
        bool source_step = (c == 's');
        exe_ctx.GetThreadRef().StepIn(source_step);
      }
    }
      return eKeyHandled;

    case 'u': // 'u' == frame up
    case 'd': // 'd' == frame down
    {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasThreadScope()) {
        Thread *thread = exe_ctx.GetThreadPtr();
        uint32_t frame_idx =
            thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
        if (frame_idx == UINT32_MAX)
          frame_idx = 0;
        if (c == 'u' && frame_idx + 1 < thread->GetStackFrameCount())
          ++frame_idx;
        else if (c == 'd' && frame_idx > 0)
          --frame_idx;
        if (thread->SetSelectedFrameByIndex(frame_idx, true))
          exe_ctx.SetFrameSP(thread->GetSelectedFrame(SelectMostRelevantFrame));
      }
    }
      return eKeyHandled;

    case 'h':
      window.CreateHelpSubwindow();
      return eKeyHandled;

    default:
      break;
    }
    return eKeyNotHandled;
  }

  void ToggleBreakpointOnSelectedLine() {
    ExecutionContext exe_ctx =
        m_debugger.GetCommandInterpreter().GetExecutionContext();
    if (!exe_ctx.HasTargetScope())
      return;
    if (GetNumSourceLines() > 0) {
      // Source file breakpoint.
      BreakpointList &bp_list = exe_ctx.GetTargetRef().GetBreakpointList();
      const size_t num_bps = bp_list.GetSize();
      for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
        BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
        const size_t num_bps_locs = bp_sp->GetNumLocations();
        for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; ++bp_loc_idx) {
          BreakpointLocationSP bp_loc_sp =
              bp_sp->GetLocationAtIndex(bp_loc_idx);
          LineEntry bp_loc_line_entry;
          if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry(
                  bp_loc_line_entry)) {
            if (m_file_sp->GetFileSpec() == bp_loc_line_entry.file &&
                m_selected_line + 1 == bp_loc_line_entry.line) {
              bool removed =
                  exe_ctx.GetTargetRef().RemoveBreakpointByID(bp_sp->GetID());
              assert(removed);
              UNUSED_IF_ASSERT_DISABLED(removed);
              return; // Existing breakpoint removed.
            }
          }
        }
      }
      // No breakpoint found on the location, add it.
      BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
          nullptr, // Don't limit the breakpoint to certain modules
          m_file_sp->GetFileSpec(), // Source file
          m_selected_line +
              1, // Source line number (m_selected_line is zero based)
          0,     // No column specified.
          0,     // No offset
          eLazyBoolCalculate,  // Check inlines using global setting
          eLazyBoolCalculate,  // Skip prologue using global setting,
          false,               // internal
          false,               // request_hardware
          eLazyBoolCalculate); // move_to_nearest_code
    } else {
      // Disassembly breakpoint.
      assert(GetNumDisassemblyLines() > 0);
      assert(m_selected_line < GetNumDisassemblyLines());
      const Instruction *inst = m_disassembly_sp->GetInstructionList()
                                    .GetInstructionAtIndex(m_selected_line)
                                    .get();
      Address addr = inst->GetAddress();
      // Try to find it.
      BreakpointList &bp_list = exe_ctx.GetTargetRef().GetBreakpointList();
      const size_t num_bps = bp_list.GetSize();
      for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
        BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
        const size_t num_bps_locs = bp_sp->GetNumLocations();
        for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; ++bp_loc_idx) {
          BreakpointLocationSP bp_loc_sp =
              bp_sp->GetLocationAtIndex(bp_loc_idx);
          LineEntry bp_loc_line_entry;
          const lldb::addr_t file_addr =
              bp_loc_sp->GetAddress().GetFileAddress();
          if (file_addr == addr.GetFileAddress()) {
            bool removed =
                exe_ctx.GetTargetRef().RemoveBreakpointByID(bp_sp->GetID());
            assert(removed);
            UNUSED_IF_ASSERT_DISABLED(removed);
            return; // Existing breakpoint removed.
          }
        }
      }
      // No breakpoint found on the address, add it.
      BreakpointSP bp_sp =
          exe_ctx.GetTargetRef().CreateBreakpoint(addr, // lldb_private::Address
                                                  false,  // internal
                                                  false); // request_hardware
    }
  }

protected:
  typedef std::set<uint32_t> BreakpointLines;
  typedef std::set<lldb::addr_t> BreakpointAddrs;

  Debugger &m_debugger;
  SymbolContext m_sc;
  SourceManager::FileSP m_file_sp;
  SymbolContextScope *m_disassembly_scope = nullptr;
  lldb::DisassemblerSP m_disassembly_sp;
  AddressRange m_disassembly_range;
  StreamString m_title;
  lldb::user_id_t m_tid = LLDB_INVALID_THREAD_ID;
  int m_line_width = 4;
  uint32_t m_selected_line = 0; // The selected line
  uint32_t m_pc_line = 0;       // The line with the PC
  uint32_t m_stop_id = 0;
  uint32_t m_frame_idx = UINT32_MAX;
  int m_first_visible_line = 0;
  int m_first_visible_column = 0;
  int m_min_x = 0;
  int m_min_y = 0;
  int m_max_x = 0;
  int m_max_y = 0;
};

DisplayOptions ValueObjectListDelegate::g_options = {true};

IOHandlerCursesGUI::IOHandlerCursesGUI(Debugger &debugger)
    : IOHandler(debugger, IOHandler::Type::Curses) {}

void IOHandlerCursesGUI::Activate() {
  IOHandler::Activate();
  if (!m_app_ap) {
    m_app_ap = std::make_unique<Application>(GetInputFILE(), GetOutputFILE());

    // This is both a window and a menu delegate
    std::shared_ptr<ApplicationDelegate> app_delegate_sp(
        new ApplicationDelegate(*m_app_ap, m_debugger));

    MenuDelegateSP app_menu_delegate_sp =
        std::static_pointer_cast<MenuDelegate>(app_delegate_sp);
    MenuSP lldb_menu_sp(
        new Menu("LLDB", "F1", KEY_F(1), ApplicationDelegate::eMenuID_LLDB));
    MenuSP exit_menuitem_sp(
        new Menu("Exit", nullptr, 'x', ApplicationDelegate::eMenuID_LLDBExit));
    exit_menuitem_sp->SetCannedResult(MenuActionResult::Quit);
    lldb_menu_sp->AddSubmenu(MenuSP(new Menu(
        "About LLDB", nullptr, 'a', ApplicationDelegate::eMenuID_LLDBAbout)));
    lldb_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
    lldb_menu_sp->AddSubmenu(exit_menuitem_sp);

    MenuSP target_menu_sp(new Menu("Target", "F2", KEY_F(2),
                                   ApplicationDelegate::eMenuID_Target));
    target_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Create", nullptr, 'c', ApplicationDelegate::eMenuID_TargetCreate)));
    target_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Delete", nullptr, 'd', ApplicationDelegate::eMenuID_TargetDelete)));

    MenuSP process_menu_sp(new Menu("Process", "F3", KEY_F(3),
                                    ApplicationDelegate::eMenuID_Process));
    process_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Attach", nullptr, 'a', ApplicationDelegate::eMenuID_ProcessAttach)));
    process_menu_sp->AddSubmenu(
        MenuSP(new Menu("Detach and resume", nullptr, 'd',
                        ApplicationDelegate::eMenuID_ProcessDetachResume)));
    process_menu_sp->AddSubmenu(
        MenuSP(new Menu("Detach suspended", nullptr, 's',
                        ApplicationDelegate::eMenuID_ProcessDetachSuspended)));
    process_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Launch", nullptr, 'l', ApplicationDelegate::eMenuID_ProcessLaunch)));
    process_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
    process_menu_sp->AddSubmenu(
        MenuSP(new Menu("Continue", nullptr, 'c',
                        ApplicationDelegate::eMenuID_ProcessContinue)));
    process_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Halt", nullptr, 'h', ApplicationDelegate::eMenuID_ProcessHalt)));
    process_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Kill", nullptr, 'k', ApplicationDelegate::eMenuID_ProcessKill)));

    MenuSP thread_menu_sp(new Menu("Thread", "F4", KEY_F(4),
                                   ApplicationDelegate::eMenuID_Thread));
    thread_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Step In", nullptr, 'i', ApplicationDelegate::eMenuID_ThreadStepIn)));
    thread_menu_sp->AddSubmenu(
        MenuSP(new Menu("Step Over", nullptr, 'v',
                        ApplicationDelegate::eMenuID_ThreadStepOver)));
    thread_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Step Out", nullptr, 'o', ApplicationDelegate::eMenuID_ThreadStepOut)));

    MenuSP view_menu_sp(
        new Menu("View", "F5", KEY_F(5), ApplicationDelegate::eMenuID_View));
    view_menu_sp->AddSubmenu(
        MenuSP(new Menu("Backtrace", nullptr, 't',
                        ApplicationDelegate::eMenuID_ViewBacktrace)));
    view_menu_sp->AddSubmenu(
        MenuSP(new Menu("Registers", nullptr, 'r',
                        ApplicationDelegate::eMenuID_ViewRegisters)));
    view_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Source", nullptr, 's', ApplicationDelegate::eMenuID_ViewSource)));
    view_menu_sp->AddSubmenu(
        MenuSP(new Menu("Variables", nullptr, 'v',
                        ApplicationDelegate::eMenuID_ViewVariables)));
    view_menu_sp->AddSubmenu(
        MenuSP(new Menu("Breakpoints", nullptr, 'b',
                        ApplicationDelegate::eMenuID_ViewBreakpoints)));

    MenuSP help_menu_sp(
        new Menu("Help", "F6", KEY_F(6), ApplicationDelegate::eMenuID_Help));
    help_menu_sp->AddSubmenu(MenuSP(new Menu(
        "GUI Help", nullptr, 'g', ApplicationDelegate::eMenuID_HelpGUIHelp)));

    m_app_ap->Initialize();
    WindowSP &main_window_sp = m_app_ap->GetMainWindow();

    MenuSP menubar_sp(new Menu(Menu::Type::Bar));
    menubar_sp->AddSubmenu(lldb_menu_sp);
    menubar_sp->AddSubmenu(target_menu_sp);
    menubar_sp->AddSubmenu(process_menu_sp);
    menubar_sp->AddSubmenu(thread_menu_sp);
    menubar_sp->AddSubmenu(view_menu_sp);
    menubar_sp->AddSubmenu(help_menu_sp);
    menubar_sp->SetDelegate(app_menu_delegate_sp);

    Rect content_bounds = main_window_sp->GetFrame();
    Rect menubar_bounds = content_bounds.MakeMenuBar();
    Rect status_bounds = content_bounds.MakeStatusBar();
    Rect source_bounds;
    Rect variables_bounds;
    Rect threads_bounds;
    Rect source_variables_bounds;
    content_bounds.VerticalSplitPercentage(0.80, source_variables_bounds,
                                           threads_bounds);
    source_variables_bounds.HorizontalSplitPercentage(0.70, source_bounds,
                                                      variables_bounds);

    WindowSP menubar_window_sp =
        main_window_sp->CreateSubWindow("Menubar", menubar_bounds, false);
    // Let the menubar get keys if the active window doesn't handle the keys
    // that are typed so it can respond to menubar key presses.
    menubar_window_sp->SetCanBeActive(
        false); // Don't let the menubar become the active window
    menubar_window_sp->SetDelegate(menubar_sp);

    WindowSP source_window_sp(
        main_window_sp->CreateSubWindow("Source", source_bounds, true));
    WindowSP variables_window_sp(
        main_window_sp->CreateSubWindow("Variables", variables_bounds, false));
    WindowSP threads_window_sp(
        main_window_sp->CreateSubWindow("Threads", threads_bounds, false));
    WindowSP status_window_sp(
        main_window_sp->CreateSubWindow("Status", status_bounds, false));
    status_window_sp->SetCanBeActive(
        false); // Don't let the status bar become the active window
    main_window_sp->SetDelegate(
        std::static_pointer_cast<WindowDelegate>(app_delegate_sp));
    source_window_sp->SetDelegate(
        WindowDelegateSP(new SourceFileWindowDelegate(m_debugger)));
    variables_window_sp->SetDelegate(
        WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
    TreeDelegateSP thread_delegate_sp(new ThreadsTreeDelegate(m_debugger));
    threads_window_sp->SetDelegate(WindowDelegateSP(
        new TreeWindowDelegate(m_debugger, thread_delegate_sp)));
    status_window_sp->SetDelegate(
        WindowDelegateSP(new StatusBarWindowDelegate(m_debugger)));

    // All colors with black background.
    init_pair(1, COLOR_BLACK, COLOR_BLACK);
    init_pair(2, COLOR_RED, COLOR_BLACK);
    init_pair(3, COLOR_GREEN, COLOR_BLACK);
    init_pair(4, COLOR_YELLOW, COLOR_BLACK);
    init_pair(5, COLOR_BLUE, COLOR_BLACK);
    init_pair(6, COLOR_MAGENTA, COLOR_BLACK);
    init_pair(7, COLOR_CYAN, COLOR_BLACK);
    init_pair(8, COLOR_WHITE, COLOR_BLACK);
    // All colors with blue background.
    init_pair(9, COLOR_BLACK, COLOR_BLUE);
    init_pair(10, COLOR_RED, COLOR_BLUE);
    init_pair(11, COLOR_GREEN, COLOR_BLUE);
    init_pair(12, COLOR_YELLOW, COLOR_BLUE);
    init_pair(13, COLOR_BLUE, COLOR_BLUE);
    init_pair(14, COLOR_MAGENTA, COLOR_BLUE);
    init_pair(15, COLOR_CYAN, COLOR_BLUE);
    init_pair(16, COLOR_WHITE, COLOR_BLUE);
    // These must match the order in the color indexes enum.
    init_pair(17, COLOR_BLACK, COLOR_WHITE);
    init_pair(18, COLOR_MAGENTA, COLOR_WHITE);
    static_assert(LastColorPairIndex == 18, "Color indexes do not match.");

    define_key("\033[Z", KEY_SHIFT_TAB);
    define_key("\033\015", KEY_ALT_ENTER);
  }
}

void IOHandlerCursesGUI::Deactivate() { m_app_ap->Terminate(); }

void IOHandlerCursesGUI::Run() {
  m_app_ap->Run(m_debugger);
  SetIsDone(true);
}

IOHandlerCursesGUI::~IOHandlerCursesGUI() = default;

void IOHandlerCursesGUI::Cancel() {}

bool IOHandlerCursesGUI::Interrupt() {
  return m_debugger.GetCommandInterpreter().IOHandlerInterrupt(*this);
}

void IOHandlerCursesGUI::GotEOF() {}

void IOHandlerCursesGUI::TerminalSizeChanged() {
  m_app_ap->TerminalSizeChanged();
}

#endif // LLDB_ENABLE_CURSES
