//+------------------------------------------------------------------+
//|                                            ReplayController.mqh  |
//+------------------------------------------------------------------+
#ifndef REPLAYCONTROLLER_MQH
#define REPLAYCONTROLLER_MQH

#include "TradeRecord.mqh"
#include "TradeLoader.mqh"
#include "TradeRenderer.mqh"

//+------------------------------------------------------------------+
//| Manages navigation state and drives loader/renderer together     |
//+------------------------------------------------------------------+
class CReplayController
  {
private:
   int               m_current_idx;
   CTradeLoader      m_loader;
   CTradeRenderer    m_renderer;
   string            m_symbol;
   ENUM_TIMEFRAMES   m_tf;

   void              ScrollToTrade(const CTradeRecord &trade);

public:
                     CReplayController(void);
                    ~CReplayController(void);

   bool              Init(const string &symbol, ENUM_TIMEFRAMES tf, long magic,
                          datetime from_time, datetime to_time);
   void              ShowCurrent(void);
   void              Next(void);
   void              Previous(void);
   int               GetCount(void) const;
   int               GetCurrentIdx(void) const;
  };

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CReplayController::CReplayController(void)
  {
   m_current_idx = 0;
   m_symbol      = "";
   m_tf          = PERIOD_CURRENT;
  }

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CReplayController::~CReplayController(void)
  {
  }

//+------------------------------------------------------------------+
//| Load trade history and validate at least one trade was found     |
//+------------------------------------------------------------------+
bool CReplayController::Init(const string &symbol, ENUM_TIMEFRAMES tf, long magic,
                             datetime from_time, datetime to_time)
  {
   m_symbol = symbol;
   m_tf     = tf;

   int count = m_loader.Load(symbol, magic, from_time, to_time);
   m_loader.SortByEntryTime();
   m_current_idx = 0;

   if(count == 0)
     {
      ::Print("CReplayController::Init - no trades found for symbol ", symbol);
      return(false);
     }

   ::Print("CReplayController::Init - loaded ", count, " trades for symbol ", symbol);
   return(true);
  }

//+------------------------------------------------------------------+
//| Compute and apply the chart scroll position to center a trade    |
//+------------------------------------------------------------------+
void CReplayController::ScrollToTrade(const CTradeRecord &trade)
  {
   ::ChartSetInteger(0, CHART_AUTOSCROLL, false);
   ::ChartSetInteger(0, CHART_SHIFT, true);

   int entry_bar = ::iBarShift(m_symbol, m_tf, trade.entry_time, false);
   if(entry_bar < 0)
     {
      ::Print("CReplayController::ScrollToTrade - no bar found for entry time, skipping scroll");
      return;
     }

   int visible_bars = (int)::ChartGetInteger(0, CHART_VISIBLE_BARS);
   int half_window   = visible_bars / 2;
   int target_offset = entry_bar - half_window;

   if(target_offset < 0)
      target_offset = 0;

   ::ChartNavigate(0, CHART_END, -target_offset);
  }

//+------------------------------------------------------------------+
//| Render the current trade and scroll the chart to it              |
//+------------------------------------------------------------------+
void CReplayController::ShowCurrent(void)
  {
   CTradeRecord trade;
   if(!m_loader.GetTrade(m_current_idx, trade))
     {
      ::Print("CReplayController::ShowCurrent - invalid index ", m_current_idx);
      return;
     }

   m_renderer.Clear();
   m_renderer.Render(trade, m_symbol, m_tf);
   ScrollToTrade(trade);

   ::PrintFormat("Trade %d/%d  pos=%I64u  %s  entry=%s  pips=%.1f  R=%s",
                 m_current_idx + 1, m_loader.GetCount(), trade.position_id,
                 (trade.order_type == ORDER_TYPE_BUY ? "BUY" : "SELL"),
                 ::TimeToString(trade.entry_time, TIME_DATE | TIME_MINUTES),
                 trade.PipsProfit(),
                 (trade.RMultiple() == DBL_MAX ? "N/A" : ::DoubleToString(trade.RMultiple(), 2)));
  }

//+------------------------------------------------------------------+
//| Advance to the next trade, clamped to the last index             |
//+------------------------------------------------------------------+
void CReplayController::Next(void)
  {
   int count = m_loader.GetCount();
   if(count == 0)
      return;

   if(m_current_idx < count - 1)
      m_current_idx++;

   ShowCurrent();
  }

//+------------------------------------------------------------------+
//| Move to the previous trade, clamped to index zero                |
//+------------------------------------------------------------------+
void CReplayController::Previous(void)
  {
   int count = m_loader.GetCount();
   if(count == 0)
      return;

   if(m_current_idx > 0)
      m_current_idx--;

   ShowCurrent();
  }

//+------------------------------------------------------------------+
//| Return the total number of loaded trades                         |
//+------------------------------------------------------------------+
int CReplayController::GetCount(void) const
  {
   return(m_loader.GetCount());
  }

//+------------------------------------------------------------------+
//| Return the index of the currently displayed trade                |
//+------------------------------------------------------------------+
int CReplayController::GetCurrentIdx(void) const
  {
   return(m_current_idx);
  }

#endif // REPLAYCONTROLLER_MQH
//+------------------------------------------------------------------+