/* TUI windows implemented in Python

   Copyright (C) 2020-2026 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */


#include "arch-utils.h"
#include "python-internal.h"
#include "gdbsupport/intrusive_list.h"

#ifdef TUI

/* Note that Python's public headers may define HAVE_NCURSES_H, so if
   we unconditionally include this (outside the #ifdef above), then we
   can get a compile error when ncurses is not in fact installed.  See
   PR tui/25597; or the upstream Python bug
   https://bugs.python.org/issue20768.  */
#include "gdb_curses.h"

#include "tui/tui-data.h"
#include "tui/tui-io.h"
#include "tui/tui-layout.h"
#include "tui/tui-wingeneral.h"
#include "tui/tui-winsource.h"
#include "observable.h"
#include "py-events.h"
#include "py-event.h"

class tui_py_window;

/* A PyObject representing a TUI window.  */

struct gdbpy_tui_window : public PyObject
{
  /* The TUI window, or nullptr if the window has been deleted.  */
  tui_py_window *window;

  /* Return true if this object is valid.  */
  bool is_valid () const;

  /* Require that this object be valid.  Throws exception if not.  */
  void require_valid () const
  {
    if (!is_valid ())
      gdbpy_err_format (PyExc_RuntimeError, _("TUI window is invalid."));
  }

  /* Erase the TUI window.  */
  void erase ();

  /* Python function that writes some text to a TUI window.  */
  void write (gdbpy_borrowed_ref<> args, gdbpy_opt_borrowed_ref<> kw);

  /* Return the width of the TUI window.  */
  int width () const;

  /* Return the height of the TUI window.  */
  int height () const;

  /* Return the title of the TUI window.  */
  const std::string &title () const;

  /* Set the title of the TUI window.  */
  void set_title (gdbpy_opt_borrowed_ref<> new_title);

  static PyTypeObject *corresponding_object_type;
};

static_assert (gdb::is_python_allocatable_v<gdbpy_tui_window>);

extern PyTypeObject gdbpy_tui_window_object_type;

/* A TUI window written in Python.  */

class tui_py_window : public tui_win_info
{
public:

  tui_py_window (const char *name, gdbpy_ref<gdbpy_tui_window> wrapper)
    : m_name (name),
      m_wrapper (std::move (wrapper))
  {
    m_wrapper->window = this;
  }

  ~tui_py_window ();

  DISABLE_COPY_AND_ASSIGN (tui_py_window);

  /* Set the "user window" to the indicated reference.  The user
     window is the object returned the by user-defined window
     constructor.  */
  void set_user_window (gdbpy_ref<> &&user_window)
  {
    m_window = std::move (user_window);
  }

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

  void rerender () override;
  void do_scroll_vertical (int num_to_scroll) override;
  void do_scroll_horizontal (int num_to_scroll) override;

  void refresh_window () override
  {
    if (m_inner_window != nullptr)
      {
	wnoutrefresh (handle.get ());
	touchwin (m_inner_window.get ());
	wnoutrefresh (m_inner_window.get ());
      }
    else
      tui_win_info::refresh_window ();
  }

  void resize (int height, int width, int origin_x, int origin_y) override;

  void click (int mouse_x, int mouse_y, int mouse_button) override;

  /* Erase and re-box the window.  */
  void erase ()
  {
    if (is_visible () && m_inner_window != nullptr)
      {
	werase (m_inner_window.get ());
	check_and_display_highlight_if_needed ();
      }
  }

  /* Write STR to the window.  FULL_WINDOW is true to erase the window
     contents beforehand.  */
  void output (const char *str, bool full_window);

  /* A helper function to compute the viewport width.  */
  int viewport_width () const
  {
    return std::max (0, width - 2);
  }

  /* A helper function to compute the viewport height.  */
  int viewport_height () const
  {
    return std::max (0, height - 2);
  }

private:

  /* The name of this window.  */
  std::string m_name;

  /* We make our own inner window, so that it is easy to print without
     overwriting the border.  */
  std::unique_ptr<WINDOW, curses_deleter> m_inner_window;

  /* The underlying Python window object.  */
  gdbpy_ref<> m_window;

  /* The Python wrapper for this object.  */
  gdbpy_ref<gdbpy_tui_window> m_wrapper;
};

/* See gdbpy_tui_window declaration above.  */

bool
gdbpy_tui_window::is_valid () const
{
  return window != nullptr && tui_active;
}

tui_py_window::~tui_py_window ()
{
  gdbpy_enter enter_py;

  /* This can be null if the user-provided Python construction
     function failed.  */
  if (m_window != nullptr
      && PyObject_HasAttrString (m_window.get (), "close"))
    {
      gdbpy_ref<> result = gdbpy_call_method (m_window, "close");
      if (result == nullptr)
	gdbpy_print_stack ();
    }

  /* Unlink.  */
  m_wrapper->window = nullptr;
  /* Explicitly free the Python references.  We have to do this
     manually because we need to hold the GIL while doing so.  */
  m_wrapper.reset (nullptr);
  m_window.reset (nullptr);
}

void
tui_py_window::rerender ()
{
  tui_batch_rendering batch;

  tui_win_info::rerender ();

  gdbpy_enter enter_py;

  int h = viewport_height ();
  int w = viewport_width ();
  if (h == 0 || w == 0)
    {
      /* The window would be too small, so just remove the
	 contents.  */
      m_inner_window.reset (nullptr);
      return;
    }
  m_inner_window.reset (newwin (h, w, y + 1, x + 1));

  if (PyObject_HasAttrString (m_window.get (), "render"))
    {
      gdbpy_ref<> result = gdbpy_call_method (m_window, "render");
      if (result == nullptr)
	gdbpy_print_stack ();
    }
}

void
tui_py_window::do_scroll_horizontal (int num_to_scroll)
{
  tui_batch_rendering batch;

  gdbpy_enter enter_py;

  if (PyObject_HasAttrString (m_window.get (), "hscroll"))
    {
      gdbpy_ref<> result = gdbpy_call_method (m_window, "hscroll",
					      num_to_scroll);
      if (result == nullptr)
	gdbpy_print_stack ();
    }
}

void
tui_py_window::do_scroll_vertical (int num_to_scroll)
{
  tui_batch_rendering batch;

  gdbpy_enter enter_py;

  if (PyObject_HasAttrString (m_window.get (), "vscroll"))
    {
      gdbpy_ref<> result = gdbpy_call_method (m_window, "vscroll",
					      num_to_scroll);
      if (result == nullptr)
	gdbpy_print_stack ();
    }
}

void
tui_py_window::resize (int height_, int width_, int origin_x_, int origin_y_)
{
  m_inner_window.reset (nullptr);

  tui_win_info::resize (height_, width_, origin_x_, origin_y_);
}

void
tui_py_window::click (int mouse_x, int mouse_y, int mouse_button)
{
  tui_batch_rendering batch;

  gdbpy_enter enter_py;

  if (PyObject_HasAttrString (m_window.get (), "click"))
    {
      gdbpy_ref<> result = gdbpy_call_method (m_window, "click",
					      mouse_x, mouse_y, mouse_button);
      if (result == nullptr)
	gdbpy_print_stack ();
    }
}

void
tui_py_window::output (const char *text, bool full_window)
{
  if (m_inner_window != nullptr)
    {
      tui_batch_rendering batch;

      if (full_window)
	werase (m_inner_window.get ());

      tui_puts (text, m_inner_window.get ());
      if (full_window)
	check_and_display_highlight_if_needed ();
      else
	wnoutrefresh (m_inner_window.get ());
    }
}



/* A callable that is used to create a TUI window.  It wraps the
   user-supplied window constructor.  */

class gdbpy_tui_window_maker
  : public intrusive_list_node<gdbpy_tui_window_maker>
{
public:

  explicit gdbpy_tui_window_maker (gdbpy_ref<> &&constr)
    : m_constr (std::move (constr))
  {
    m_window_maker_list.push_back (*this);
  }

  ~gdbpy_tui_window_maker ();

  gdbpy_tui_window_maker (gdbpy_tui_window_maker &&other) noexcept
    : m_constr (std::move (other.m_constr))
  {
    m_window_maker_list.push_back (*this);
  }

  gdbpy_tui_window_maker (const gdbpy_tui_window_maker &other)
  {
    gdbpy_enter enter_py;
    m_constr = other.m_constr;
    m_window_maker_list.push_back (*this);
  }

  gdbpy_tui_window_maker &operator= (gdbpy_tui_window_maker &&other)
  {
    m_constr = std::move (other.m_constr);
    return *this;
  }

  gdbpy_tui_window_maker &operator= (const gdbpy_tui_window_maker &other)
  {
    gdbpy_enter enter_py;
    m_constr = other.m_constr;
    return *this;
  }

  tui_win_info *operator() (const char *name);

  /* Reset the m_constr field of all gdbpy_tui_window_maker objects back to
     nullptr, this will allow the Python object referenced to be
     deallocated.  This function is intended to be called when GDB is
     shutting down the Python interpreter to allow all Python objects to be
     deallocated and cleaned up.  */
  static void
  invalidate_all ()
  {
    gdbpy_enter enter_py;
    for (gdbpy_tui_window_maker &f : m_window_maker_list)
      f.m_constr.reset (nullptr);
  }

private:

  /* A constructor that is called to make a TUI window.  */
  gdbpy_ref<> m_constr;

  /* A global list of all gdbpy_tui_window_maker objects.  */
  static intrusive_list<gdbpy_tui_window_maker> m_window_maker_list;
};

/* See comment in class declaration above.  */

intrusive_list<gdbpy_tui_window_maker>
  gdbpy_tui_window_maker::m_window_maker_list;

gdbpy_tui_window_maker::~gdbpy_tui_window_maker ()
{
  /* Remove this gdbpy_tui_window_maker from the global list.  */
  if (is_linked ())
    m_window_maker_list.erase (m_window_maker_list.iterator_to (*this));

  if (m_constr != nullptr)
    {
      gdbpy_enter enter_py;
      m_constr.reset (nullptr);
    }
}

tui_win_info *
gdbpy_tui_window_maker::operator() (const char *win_name)
{
  gdbpy_enter enter_py;

  gdbpy_ref<gdbpy_tui_window> wrapper
    (PyObject_New (gdbpy_tui_window, &gdbpy_tui_window_object_type));
  if (wrapper == nullptr)
    {
      gdbpy_print_stack ();
      return nullptr;
    }

  std::unique_ptr<tui_py_window> window
    (new tui_py_window (win_name, wrapper));

  /* There's only two ways that m_constr can be reset back to nullptr,
     first when the parent gdbpy_tui_window_maker object is deleted, in
     which case it should be impossible to call this method, or second, as
     a result of a gdbpy_tui_window_maker::invalidate_all call, but this is
     only called when GDB's Python interpreter is being shut down, after
     which, this method should not be called.  */
  gdb_assert (m_constr != nullptr);

  gdbpy_ref<> user_window
    (PyObject_CallFunctionObjArgs (m_constr.get (),
				   (PyObject *) wrapper.get (),
				   nullptr));
  if (user_window == nullptr)
    {
      gdbpy_print_stack ();
      return nullptr;
    }

  window->set_user_window (std::move (user_window));
  /* Window is now owned by the TUI.  */
  return window.release ();
}

/* Implement "gdb.register_window_type".  */

void
gdbpy_register_tui_window (gdbpy_borrowed_ref<> args,
			   gdbpy_opt_borrowed_ref<> kw)
{
  static const char *keywords[] = { "name", "constructor", nullptr };
  const char *name;
  PyObject *cons_obj;
  gdbpy_arg_parse_tuple_and_keywords (args, kw, "sO", keywords,
				      &name, &cons_obj);

  gdbpy_tui_window_maker constr (gdbpy_ref<>::new_reference (cons_obj));
  tui_register_window (name, constr);
}



/* Python function that erases the TUI window.  */
void
gdbpy_tui_window::erase ()
{
  require_valid ();
  window->erase ();
}

/* Python function that writes some text to a TUI window.  */
void
gdbpy_tui_window::write (gdbpy_borrowed_ref<> args,
			 gdbpy_opt_borrowed_ref<> kw)
{
  require_valid ();

  static const char *keywords[] = { "string", "full_window", nullptr };

  const char *text;
  int full_window = 0;

  gdbpy_arg_parse_tuple_and_keywords (args, kw, "s|i", keywords,
				      &text, &full_window);

  window->output (text, full_window);
}

int
gdbpy_tui_window::width () const
{
  require_valid ();
  return window->viewport_width ();
}

int
gdbpy_tui_window::height () const
{
  require_valid ();
  return window->viewport_height ();
}

const std::string &
gdbpy_tui_window::title () const
{
  require_valid ();
  return window->title ();
}

/* Set the title of the TUI window.  */
void
gdbpy_tui_window::set_title (gdbpy_opt_borrowed_ref<> new_title)
{
  require_valid ();

  if (new_title == nullptr)
    gdbpy_err_format (PyExc_TypeError,
		      _("Cannot delete \"title\" attribute."));

  /* FIXME: Python safety.  Ideally python_string_to_host_string would
     throw on error, but this can't be done until more of the code has
     been converted.  */
  gdb::unique_xmalloc_ptr<char> value
    = python_string_to_host_string (new_title);
  if (value == nullptr)
    throw gdb_python_exception ();

  window->set_title (value.get ());
}

static gdb_PyGetSetDef tui_object_getset[] =
{
  { "width", wrap_getter<gdbpy_tui_window, &gdbpy_tui_window::width>, nullptr,
    "Width of the window.", nullptr },
  { "height", wrap_getter<gdbpy_tui_window, &gdbpy_tui_window::height>, nullptr,
    "Height of the window.", nullptr },
  { "title", wrap_getter<gdbpy_tui_window, &gdbpy_tui_window::title>,
    wrap_setter<gdbpy_tui_window, &gdbpy_tui_window::set_title>,
    "Title of the window.", nullptr },
  { nullptr }  /* Sentinel */
};

static PyMethodDef tui_object_methods[] =
{
  noargs_method<gdbpy_tui_window, &gdbpy_tui_window::is_valid> ("is_valid",
    "is_valid () -> Boolean\n\
Return true if this TUI window is valid, false if not."),
  noargs_method<gdbpy_tui_window, &gdbpy_tui_window::erase>
    ("erase", "Erase the TUI window."),
  varargs_method<gdbpy_tui_window, &gdbpy_tui_window::write> ("write",
    "Append a string to the TUI window."),
  { nullptr } /* Sentinel.  */
};

PyTypeObject gdbpy_tui_window_object_type =
{
  PyVarObject_HEAD_INIT (NULL, 0)
  "gdb.TuiWindow",		  /*tp_name*/
  sizeof (gdbpy_tui_window),	  /*tp_basicsize*/
  0,				  /*tp_itemsize*/
  0,				  /*tp_dealloc*/
  0,				  /*tp_print*/
  0,				  /*tp_getattr*/
  0,				  /*tp_setattr*/
  0,				  /*tp_compare*/
  0,				  /*tp_repr*/
  0,				  /*tp_as_number*/
  0,				  /*tp_as_sequence*/
  0,				  /*tp_as_mapping*/
  0,				  /*tp_hash */
  0,				  /*tp_call*/
  0,				  /*tp_str*/
  0,				  /*tp_getattro*/
  0,				  /*tp_setattro */
  0,				  /*tp_as_buffer*/
  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
  "GDB TUI window object",	  /* tp_doc */
  0,				  /* tp_traverse */
  0,				  /* tp_clear */
  0,				  /* tp_richcompare */
  0,				  /* tp_weaklistoffset */
  0,				  /* tp_iter */
  0,				  /* tp_iternext */
  tui_object_methods,		  /* tp_methods */
  0,				  /* tp_members */
  tui_object_getset,		  /* tp_getset */
  0,				  /* tp_base */
  0,				  /* tp_dict */
  0,				  /* tp_descr_get */
  0,				  /* tp_descr_set */
  0,				  /* tp_dictoffset */
  0,				  /* tp_init */
  0,				  /* tp_alloc */
};

PyTypeObject *gdbpy_tui_window::corresponding_object_type
    = &gdbpy_tui_window_object_type;

/* Called when TUI is enabled or disabled.  */

static void
gdbpy_tui_enabled (bool state)
{
  gdbpy_enter enter_py;

  if (evregpy_no_listeners_p (gdb_py_events.tui_enabled))
    return;

  gdbpy_ref<> event_obj = create_event_object (&tui_enabled_event_object_type);
  if (event_obj == nullptr)
    {
      gdbpy_print_stack ();
      return;
    }

  gdbpy_ref<> code (PyBool_FromLong (state));
  if (evpy_add_attribute (event_obj.get (), "enabled", code.get ()) < 0
      || evpy_emit_event (event_obj.get (), gdb_py_events.tui_enabled) < 0)
    gdbpy_print_stack ();
}

#endif /* TUI */

/* Initialize this module.  */

static int
gdbpy_initialize_tui ()
{
#ifdef TUI
  gdbpy_tui_window_object_type.tp_new = PyType_GenericNew;
  if (gdbpy_type_ready (&gdbpy_tui_window_object_type) < 0)
    return -1;

  gdb::observers::tui_enabled.attach (gdbpy_tui_enabled, "py-tui");
#endif	/* TUI */

  return 0;
}

/* Finalize this module.  */

static void
gdbpy_finalize_tui ()
{
#ifdef TUI
  gdbpy_tui_window_maker::invalidate_all ();
#endif	/* TUI */
}

GDBPY_INITIALIZE_FILE (gdbpy_initialize_tui, gdbpy_finalize_tui);
