//+------------------------------------------------------------------+
//|                                               DashboardPanel.mqh |
//| CDashboardPanel: renders live cache statistics as chart label    |
//| objects. Updates on every call to Update().                      |
//+------------------------------------------------------------------+
#ifndef DASHBOARDPANEL_MQH
#define DASHBOARDPANEL_MQH

#include "CacheStatistics.mqh"

//+------------------------------------------------------------------+
//| CDashboardPanel                                                  |
//| Purpose: Graphical rendering layer for real-time telemetry       |
//+------------------------------------------------------------------+
class CDashboardPanel
  {
private:
   string               m_prefix;         // Object name prefix for all labels
   int                  m_chart_id;       // Target chart identifier
   int                  m_x_offset;       // Horizontal position in pixels
   int                  m_y_offset;       // Vertical position in pixels
   int                  m_line_spacing;   // Vertical spacing between label rows
   bool                 m_initialized;    // True once label objects have been created

   void                 CreateLabel(string name, int y_pos);
   void                 SetLabelText(string name, string text);

public:
                        CDashboardPanel(int chart_id, int x_offset, int y_offset);
                       ~CDashboardPanel(void);

   void                 Update(int active_handles, CCacheStatistics *stats);
   void                 Remove(void);
  };

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CDashboardPanel::CDashboardPanel(int chart_id, int x_offset, int y_offset)
   :  m_prefix("LAZY_CACHE_"),
      m_chart_id(chart_id),
      m_x_offset(x_offset),
      m_y_offset(y_offset),
      m_line_spacing(18),
      m_initialized(false)
  {
   //--- Initialized UI parameters
  }

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CDashboardPanel::~CDashboardPanel(void)
  {
   Remove();
  }

//+------------------------------------------------------------------+
//| CreateLabel                                                      |
//| Purpose: Handles safe low-level generation of UI text fields     |
//+------------------------------------------------------------------+
void CDashboardPanel::CreateLabel(string name, int y_pos)
  {
   if(ObjectFind(m_chart_id, name) >= 0)
     {
      return;
     }

   ObjectCreate(m_chart_id, name, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(m_chart_id, name, OBJPROP_XDISTANCE, m_x_offset);
   ObjectSetInteger(m_chart_id, name, OBJPROP_YDISTANCE, y_pos);
   ObjectSetInteger(m_chart_id, name, OBJPROP_CORNER,    CORNER_LEFT_UPPER);
   ObjectSetInteger(m_chart_id, name, OBJPROP_FONTSIZE,  9);
   ObjectSetInteger(m_chart_id, name, OBJPROP_COLOR,     clrDodgerBlue);
   ObjectSetString(m_chart_id, name,  OBJPROP_FONT,      "Consolas");
  }

//+------------------------------------------------------------------+
//| SetLabelText                                                     |
//+------------------------------------------------------------------+
void CDashboardPanel::SetLabelText(string name, string text)
  {
   ObjectSetString(m_chart_id, name, OBJPROP_TEXT, text);
  }

//+------------------------------------------------------------------+
//| Update                                                           |
//| Purpose: Pushes refreshed metrics onto the target chart context  |
//+------------------------------------------------------------------+
void CDashboardPanel::Update(int active_handles, CCacheStatistics *stats)
  {
   //--- Construct layout components dynamically on initial runtime loop
   if(!m_initialized)
     {
      CreateLabel(m_prefix + "TITLE",   m_y_offset);
      CreateLabel(m_prefix + "HANDLES", m_y_offset + m_line_spacing);
      CreateLabel(m_prefix + "HITRATE", m_y_offset + m_line_spacing * 2);
      CreateLabel(m_prefix + "MISSES",  m_y_offset + m_line_spacing * 3);
      CreateLabel(m_prefix + "MEMORY",  m_y_offset + m_line_spacing * 4);
      m_initialized = true;
     }

   //--- Bind raw statistics inputs to display formats
   SetLabelText(m_prefix + "TITLE",   "[ Indicator Cache ]");
   SetLabelText(m_prefix + "HANDLES", "Active Handles : " + IntegerToString(active_handles));
   SetLabelText(m_prefix + "HITRATE", "Cache Hit Rate : " + DoubleToString(stats.GetHitRate(), 1) + "%");
   SetLabelText(m_prefix + "MISSES",  "Cache Misses   : " + IntegerToString(stats.GetMissCount()));
   SetLabelText(m_prefix + "MEMORY",  "Est. Memory    : " + DoubleToString(stats.GetMemoryEstKB(), 0) + " KB");

   ChartRedraw(m_chart_id);
  }

//+--------------------------------------------------------------------+
//| Remove                                                             |
//| Purpose: Purges graphic resources sequentially from terminal space |
//+--------------------------------------------------------------------+
void CDashboardPanel::Remove(void)
  {
   string labels[] = {"TITLE", "HANDLES", "HITRATE", "MISSES", "MEMORY"};
   int size = ArraySize(labels);

   for(int i = 0; i < size; i++)
     {
      ObjectDelete(m_chart_id, m_prefix + labels[i]);
     }

   ChartRedraw(m_chart_id);
   m_initialized = false;
  }

#endif // DASHBOARDPANEL_MQH
//+------------------------------------------------------------------+