//+------------------------------------------------------------------+
//|                                               ATR_Calculator.mqh |
//|         VERSION 2.10: Added Percent mode.                        |
//|                                        Copyright 2025, xxxxxxxx  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, xxxxxxxx"

#include <MyIncludes\HeikinAshi_Tools.mqh>

//--- CORRECTED: Moved enum here to be accessible by other calculators ---
enum ENUM_CANDLE_SOURCE { CANDLE_STANDARD, CANDLE_HEIKIN_ASHI };

//--- NEW: Enum for display mode ---
enum ENUM_ATR_DISPLAY_MODE { ATR_POINTS, ATR_PERCENT };

//+==================================================================+
//|                                                                  |
//|             CLASS 1: CATRCalculator (Base Class)                 |
//|                                                                  |
//+==================================================================+
class CATRCalculator
  {
protected:
   int               m_atr_period;
   ENUM_ATR_DISPLAY_MODE m_display_mode;

   //--- Virtual method for preparing the raw True Range values.
   virtual void      PrepareTrueRange(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], double &tr_buffer[]);

public:
                     CATRCalculator(void) {};
   virtual          ~CATRCalculator(void) {};

   //--- Public methods
   bool              Init(int period, ENUM_ATR_DISPLAY_MODE mode);
   int               GetPeriod(void) const { return m_atr_period; }
   void              Calculate(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], double &atr_buffer[]);
  };

//+------------------------------------------------------------------+
//| CATRCalculator: Initialization                                   |
//+------------------------------------------------------------------+
bool CATRCalculator::Init(int period, ENUM_ATR_DISPLAY_MODE mode)
  {
   m_atr_period = (period < 1) ? 1 : period;
   m_display_mode = mode;
   return true;
  }

//+------------------------------------------------------------------+
//| CATRCalculator: Main Calculation Method (Shared Logic)           |
//+------------------------------------------------------------------+
void CATRCalculator::Calculate(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], double &atr_buffer[])
  {
   if(rates_total <= m_atr_period)
      return;

//--- STEP 1: Calculate True Range (delegated to virtual method)
   double tr[];
   PrepareTrueRange(rates_total, open, high, low, close, tr);

//--- STEP 2: Calculate ATR (Wilder's Smoothing)
   for(int i = 1; i < rates_total; i++)
     {
      if(i == m_atr_period) // Initialization with a simple average of TR
        {
         double sum_tr = 0;
         for(int j = 1; j <= m_atr_period; j++)
            sum_tr += tr[j];
         atr_buffer[i] = sum_tr / m_atr_period;
        }
      else
         if(i > m_atr_period) // Recursive calculation
           {
            atr_buffer[i] = (atr_buffer[i-1] * (m_atr_period - 1) + tr[i]) / m_atr_period;
           }
     }

//--- Step 3: Convert to percentage if requested ---
   if(m_display_mode == ATR_PERCENT)
     {
      for(int i = m_atr_period; i < rates_total; i++)
        {
         if(close[i] > 0)
            atr_buffer[i] = (atr_buffer[i] / close[i]) * 100.0;
         else
            atr_buffer[i] = 0;
        }
     }
  }

//+------------------------------------------------------------------+
//| CATRCalculator: Prepares raw TR from standard prices.            |
//+------------------------------------------------------------------+
void CATRCalculator::PrepareTrueRange(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], double &tr_buffer[])
  {
   ArrayResize(tr_buffer, rates_total);
   for(int i = 1; i < rates_total; i++)
     {
      double range1 = high[i] - low[i];
      double range2 = MathAbs(high[i] - close[i-1]);
      double range3 = MathAbs(low[i] - close[i-1]);
      tr_buffer[i] = MathMax(range1, MathMax(range2, range3));
     }
  }

//+==================================================================+
//|                                                                  |
//|             CLASS 2: CATRCalculator_HA (Heikin Ashi)             |
//|                                                                  |
//+==================================================================+
class CATRCalculator_HA : public CATRCalculator
  {
private:
   CHeikinAshi_Calculator m_ha_calculator;
protected:
   //--- Overridden method to prepare Heikin Ashi based TR
   virtual void      PrepareTrueRange(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], double &tr_buffer[]) override;
  };

//+------------------------------------------------------------------+
//| CATRCalculator_HA: Prepares raw TR from HA prices.               |
//+------------------------------------------------------------------+
void CATRCalculator_HA::PrepareTrueRange(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], double &tr_buffer[])
  {
//--- Intermediate Heikin Ashi Buffers
   double ha_open[], ha_high[], ha_low[], ha_close[];
   ArrayResize(ha_open, rates_total);
   ArrayResize(ha_high, rates_total);
   ArrayResize(ha_low, rates_total);
   ArrayResize(ha_close, rates_total);

//--- Calculate the HA candles first
   m_ha_calculator.Calculate(rates_total, open, high, low, close, ha_open, ha_high, ha_low, ha_close);

//--- Now, calculate TR using the HA candles
   ArrayResize(tr_buffer, rates_total);
   for(int i = 1; i < rates_total; i++)
     {
      double range1 = ha_high[i] - ha_low[i];
      double range2 = MathAbs(ha_high[i] - ha_close[i-1]);
      double range3 = MathAbs(ha_low[i] - ha_close[i-1]);
      tr_buffer[i] = MathMax(range1, MathMax(range2, range3));
     }
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
