
// SPDX-License-Identifier: CC-BY-NC-SA-4.0
//
// Copyright (C) 2026 Bit by Bit Signal Processing LLC (https://bxbsp.com)
//
// This work is placed under the "Creative Commons Attribution
// NonCommercial ShareAlike 4.0 International" license, known
// by the shortened acronym "CC-BY-NC-SA-4.0".
//
// This work 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.
//
// A CC-BY-NC-SA-4.0 license allows you to use this work for
// noncommercial purposes so long as attribution is made to the
// original author.  Modified versions of this work may be distributed,
// but only under the same license.  For further details, see the
// Creative Commons License "CC-BY-NC-SA-4.0".
//
// You should have received a copy of the CC-BY-NC-SA-4.0 license
// along with this work. If not, see
// <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
//

//

#ifndef DISPLAY_HH
#define DISPLAY_HH

#include "panel.hh"
#include "multiwindow_multipane.hh"
#include "event_listener.hh"
#include "input_event_handler.hh"
#include "beeper.hh"
#include "draw_text.hh"

#ifndef DATA_POINT
#define DATA_POINT
struct data_point
{
  float min_y;
  float max_y;
};
#endif

//
// This handles the three buffers for each display, and flips the active
// one when asked for double-buffering.  You draw into the drawing panel.
// The active panel is currenly being or soon to be displayed.  The
// flip_pending panel is possibly still being displayed but soon will not
// be.
//
// There is also a static_panel in the window that can be copied directly
// over to the display for quick erasure of all dynamic drawing while
// keeping all static items.
//
class display : public multiwindow_multipane
{
protected:
  bool             trash_events_flag;
  long             us_to_trash_events;
  struct timeval   time_to_start_trashing_events;

    // New displays are created by check_for_new_displays() in a subclass.  Only it calls this constructor.
  display(int w, int h, int num_panes);

public:

  virtual void touch_recognized_beep() = 0;
  virtual void entry_accepted_beep()   = 0;
  virtual void entry_rejected_beep()   = 0;

  virtual void beginDrawToStatic()     = 0;
  virtual void endDrawToStatic()       = 0;
  virtual void clearDrawToStatic()     = 0;

  //
  // Event handling
  //
  List<window> priority_event_listeners;

  virtual void      claim_events(window* w=0);
  virtual void      release_events(window* w=0);
  virtual void      release_all_events();
  virtual void      trash_events_until_release();
  virtual void      trash_events_for_us(long microseconds);

  //
  // Note that if drawing is too fast, then page_flip() may get called twice before a vblank interval.  In that case,
  // the second update is thrown out and never displayed.

  virtual bool   draw()                   = 0;

  virtual void   pane_change();
  
  virtual void   get_and_process_events() = 0;
  virtual bool   handle_event(my_event& me);  

  // If something very timely is happening on the display, other processes
  // can know about it from this and disable other tasks, like data collection.
  virtual bool   need_fast_display() { return false; }

  //
  // Point, rect, and line drawing functions.
  //
  virtual void   draw_point_no_boundscheck(point p, color c) = 0;
  virtual color  get_point_no_boundscheck(point p)           = 0;

  //
  // Text drawing functions.
  //
  // multicolor text uses ASCII x = 10 (0x0A) and up to indicate a switch to color
  // c[x-10].  Flags are in draw_text.hh
  //
  virtual void   draw_text(const char* text, color c, int x, int y, int flags = 0)                      = 0;
  virtual void   draw_text(const wchar_t* text, color c, int x, int y, int flags = 0)                      = 0;
  virtual void   draw_text(const char16_t* text, color c, int x, int y, int flags = 0)                      = 0;
  virtual void   draw_text(const char32_t* text, color c, int x, int y, int flags = 0)                      = 0;
  virtual void   draw_multicolored_text(const char* text, int start_color, dt_colors& c, int x, int y, int flags = 0)        = 0;
  virtual void   draw_multicolored_text(const wchar_t* text, int start_color, dt_colors& c, int x, int y, int flags = 0)        = 0;
  virtual void   draw_multicolored_text(const char16_t* text, int start_color, dt_colors& c, int x, int y, int flags = 0)        = 0;
  virtual void   draw_multicolored_text(const char32_t* text, int start_color, dt_colors& c, int x, int y, int flags = 0)        = 0;
  virtual int    calculate_text_width(const char*      text)                                                 = 0;
  virtual int    calculate_text_width(const wchar_t*   text)                                                 = 0;
  virtual int    calculate_text_width(const char16_t*  text)                                                 = 0;
  virtual int    calculate_text_width(const char32_t*  text)                                                 = 0;
  virtual int    calculate_text_height(const char*     text)                                                = 0;
  virtual int    calculate_text_height(const wchar_t*  text)                                                = 0;
  virtual int    calculate_text_height(const char16_t* text)                                                = 0;
  virtual int    calculate_text_height(const char32_t* text)                                                = 0;
  virtual void   set_text_size(int height_pixels)                                                       = 0;

  virtual void   draw_svg_from_data(uint8_t* svg_data, int svg_data_length, int offset_x=0, int offset_y=0, int draw_width=0, int draw_height=0) = 0;

  virtual void   clear_rect(color c, point corner1, point corner2)                      = 0;
  virtual void   draw_line_known_background(pointf p0, pointf p1, color c, color bg)    = 0;
  virtual void   draw_line(pointf p0, pointf p1, color c)                               = 0;
  virtual void   draw_line_vertical(point p0, point p1, color c)                        = 0;
  virtual void   draw_line_horizontal(point p0, point p1, color c)                      = 0;


  virtual void   draw_graph_data(uint32_t     color,
				 int          num_points,
				 float        x_start,
				 float        x_step,
				 float        x_at_left,
				 float        x_at_right,
				 float        y_at_bottom,
				 float        y_at_top,
				 float        x_offset,
				 float        y_offset,
				 float        width,
				 float        height,
				 data_point*  y_data) = 0;

  virtual void draw_ephemeral_alert(const char* text, int text_height, color c, color bg) = 0;

  virtual bool ready_for_more_graph_data() { return true; }

  virtual void end_inner_event_loop() { printf("wrong end_inner_event_loop called.  It should be the one in class displays.\n"); exit(20); }
  virtual void event_loop() { printf("wrong event_loop called.  It should be the one in class displays.\n"); exit(20); }

  virtual class display* get_display();

  virtual ~display();
};





#endif
