//===-- 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/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("Unknown core file format!");
      return;
    }

    Status status = process_sp->LoadCore();
    if (status.Fail()) {
      SetError("Unknown core file format!");
      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 lldb::CompletionType.
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);
    lldb_private::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 lldb::CompletionType.
  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), 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;

struct TreeItemData {
  TreeItemData(TreeItem *parent, TreeDelegate &delegate,
               bool might_have_children, bool is_expanded)
      : m_parent(parent), m_delegate(&delegate),
        m_might_have_children(might_have_children), m_is_expanded(is_expanded) {
  }

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
  bool m_might_have_children;
  bool m_is_expanded = false;
};

class TreeItem : public TreeItemData {
public:
  TreeItem(TreeItem *parent, TreeDelegate &delegate, bool might_have_children)
      : TreeItemData(parent, delegate, might_have_children,
                     parent == nullptr
                         ? delegate.TreeDelegateExpandRootByDefault()
                         : false),
        m_children() {}

  TreeItem(const TreeItem &) = delete;
  TreeItem &operator=(const TreeItem &rhs) = delete;

  TreeItem &operator=(TreeItem &&rhs) {
    if (this != &rhs) {
      TreeItemData::operator=(std::move(rhs));
      AdoptChildren(rhs.m_children);
    }
    return *this;
  }

  TreeItem(TreeItem &&rhs) : TreeItemData(std::move(rhs)) {
    AdoptChildren(rhs.m_children);
  }

  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, TreeDelegate &delegate, bool might_have_children) {
    if (m_children.size() >= n) {
      m_children.erase(m_children.begin() + n, m_children.end());
      return;
    }
    m_children.reserve(n);
    std::generate_n(std::back_inserter(m_children), n - m_children.size(),
                    [&, parent = this]() {
                      return TreeItem(parent, delegate, might_have_children);
                    });
  }

  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:
  void AdoptChildren(std::vector<TreeItem> &children) {
    m_children = std::move(children);
    for (auto &child : m_children)
      child.m_parent = this;
  }

  std::vector<TreeItem> m_children;
};

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();

          size_t num_frames = thread_sp->GetStackFrameCount();
          item.Resize(num_frames, *m_frame_delegate_sp, false);
          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);
        }

        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, *m_thread_delegate_sp, false);
        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>();

    item.Resize(details.GetSize(), *m_string_delegate_sp, false);
    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);

    item.Resize(breakpoint->GetNumLocations(),
                *m_breakpoint_location_delegate_sp, true);
    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);

    item.Resize(breakpoints.GetSize(), *m_breakpoint_delegate_sp, true);
    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.ends_with("\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
