
///
/// Dial drawing library : used to display anything from compass display to arcs of "meter" displays
///
#pragma once
#include <cstdint>

class displayDial_t
{
public:
  /// \param display the parent display
  /// \param x x pos
  /// \param y y pos
  /// \param siz = size
  /// \param angle Angle from straight up for lowest (-angle) and highest (angle) reading
  displayDial_t(display_t &display,
                uint8_t x,
                uint8_t y,
                uint8_t siz,
                uint16_t angle = 90);

  /// @brief Construct a display with angle from Angle high to angle low
  /// @param display
  /// @param x
  /// @param y
  /// @param siz
  /// @param angle_high Angle relative to straight up for highest reading
  /// @param angle_low Angle relative to straight up for lowest reading
  displayDial_t(display_t &display,
                uint8_t x,
                uint8_t y,
                uint8_t siz,
                int16_t angle_low,
                int16_t angle_high);

  /// @brief  Put the dial needle on the display
  /// @param position values are from  0 .. math.SINE_STEPS
  void draw_needle(int16_t position);

  /// @brief draw the scale
  /// \param low low end of range
  /// \param high high end of range
  /// \param width length of long marker
  /// \param num_step number of ticks
  /// \param scale
  void draw_scale(int16_t low, int16_t high, uint8_t width, uint8_t num_step, int16_t scale);

  /// @brief print min/max limits
  virtual void draw_limits(){};

  /// @brief Draw value on display
  /// @param val integer value to show with fake decimal point
  /// @param dp  decimal point code
  virtual void draw_value(int val, int dp){};

  /// @brief Set units string on display
  /// @param str Constant string to refer to
  void set_units(char const *str){m_unitStr = str; };

protected:

  void draw_value_items(int val, int dpCode, int wid,  int x , int y );


  display_t &m_display;
  uint8_t const m_xo;         ///< Position of origin
  uint8_t const m_yo;         ///< Position of origin
  uint8_t const m_siz;        ///< Display size
  int16_t const m_angleLow;   ///< Angle for lowest value
  int16_t const m_angleRange; ///< Angle range from lowest to highest  value
  int16_t m_low;              ///< lower scale limit
  int16_t m_high;             ///< upper scale limit
  char const *  m_unitStr;     ///< Units_string 
};

//////////////////////////////////////////////////
/// A display using the whole graphics area, 180 degree sweep
class displayFullDial_t : public displayDial_t
{
public:
  /// @brief Constructor for full-screen display
  /// @param display The display it is being shown on
  displayFullDial_t(display_t &display);

  /// @brief  draw axes limits
  virtual void draw_limits() final;

  /// @brief Draw value on display
  /// @param val integer value to show with fake decimal point
  /// @param dp  decimal point code
  virtual void draw_value(int val, int dp) final;


};

//////////////////////////////////////////////////
/// A display using left hand side of graphics area, 90 degree quadrant
class displayLeftQuadrantDial_t : public displayDial_t
{
public:
  /// @brief Constructor for left quadrant display
  /// @param display The display it is being shown on
  displayLeftQuadrantDial_t(display_t &display);

  /// @brief  draw axes limits
  virtual void draw_limits() final;

  /// @brief Draw value on display
  /// @param val integer value to show with fake decimal point
  /// @param dp  decimal point code
  virtual void draw_value(int val, int dp) final;

 
};

//////////////////////////////////////////////////
/// A display using right hand side of graphics area, 90 degree quadrant
class displayRightQuadrantDial_t : public displayDial_t
{
public:
  /// @brief Constructor for right quadrant display
  /// @param display The display it is being shown on
  displayRightQuadrantDial_t(display_t &display);
  /// @brief  draw axes limits
  virtual void draw_limits() final;

  /// @brief Draw value on display
  /// @param val integer value to show with fake decimal point
  /// @param dp  decimal point code
  virtual void draw_value(int val, int dp) final;


};