#property copyright "KK"
#property version   "4.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots   4

#property indicator_label1  "MA1"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrAqua
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

#property indicator_label2  "MA2"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrYellow
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2

#property indicator_label3  "BUY"
#property indicator_type3   DRAW_ARROW
#property indicator_color3  clrBlue
#property indicator_width3  2

#property indicator_label4  "SELL"
#property indicator_type4   DRAW_ARROW
#property indicator_color4  clrRed
#property indicator_width4  2

//===========================================
input int                MA1_Period = 4;
input ENUM_MA_METHOD     MA1_Method = MODE_SMMA;
input ENUM_APPLIED_PRICE MA1_Price  = PRICE_CLOSE;

input int                MA2_Period = 21;
input ENUM_MA_METHOD     MA2_Method = MODE_SMA;
input ENUM_APPLIED_PRICE MA2_Price  = PRICE_CLOSE;

input bool  ShowLines      = true;
input bool  ShowArrows     = true;

input color MA1_Color      = clrAqua;
input color MA2_Color      = clrYellow;
input int   LineWidth      = 2;

input color ArrowUpColor   = clrBlue;
input color ArrowDownColor = clrRed;
input int   ArrowSize      = 1;

input int    ArrowGap      = 5;
input bool   EnableAlert   = false;
input bool   EnableSound   = false;
input bool   EnablePush    = false;
input string SoundFile     = "alert.wav";

//===========================================
double MA1Buf[];
double MA2Buf[];
double UpBuf[];
double DnBuf[];
double SigBuf[];

int handleMA1, handleMA2;
datetime lastAlertBar = 0;

//+------------------------------------------------------------------+
int OnInit()
{
   SetIndexBuffer(0, MA1Buf, INDICATOR_DATA);
   SetIndexBuffer(1, MA2Buf, INDICATOR_DATA);
   SetIndexBuffer(2, UpBuf,  INDICATOR_DATA);
   SetIndexBuffer(3, DnBuf,  INDICATOR_DATA);
   SetIndexBuffer(4, SigBuf, INDICATOR_CALCULATIONS);

   // --- NE legyen ArraySetAsSeries a buffereken! ---
   // Az MT5 indicator bufferek mindig forward indexelésűek maradnak.

   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, ShowLines ? DRAW_LINE : DRAW_NONE);
   PlotIndexSetInteger(0, PLOT_LINE_WIDTH, LineWidth);
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, MA1_Color);

   PlotIndexSetInteger(1, PLOT_DRAW_TYPE, ShowLines ? DRAW_LINE : DRAW_NONE);
   PlotIndexSetInteger(1, PLOT_LINE_WIDTH, LineWidth);
   PlotIndexSetInteger(1, PLOT_LINE_COLOR, MA2_Color);

   PlotIndexSetInteger(2, PLOT_DRAW_TYPE, ShowArrows ? DRAW_ARROW : DRAW_NONE);
   PlotIndexSetInteger(2, PLOT_ARROW, 233);
   PlotIndexSetInteger(2, PLOT_LINE_COLOR, ArrowUpColor);
   PlotIndexSetInteger(2, PLOT_LINE_WIDTH, ArrowSize);
   PlotIndexSetDouble (2, PLOT_EMPTY_VALUE, 0.0);

   PlotIndexSetInteger(3, PLOT_DRAW_TYPE, ShowArrows ? DRAW_ARROW : DRAW_NONE);
   PlotIndexSetInteger(3, PLOT_ARROW, 234);
   PlotIndexSetInteger(3, PLOT_LINE_COLOR, ArrowDownColor);
   PlotIndexSetInteger(3, PLOT_LINE_WIDTH, ArrowSize);
   PlotIndexSetDouble (3, PLOT_EMPTY_VALUE, 0.0);

   handleMA1 = iMA(_Symbol, _Period, MA1_Period, 0, MA1_Method, MA1_Price);
   handleMA2 = iMA(_Symbol, _Period, MA2_Period, 0, MA2_Method, MA2_Price);

   if(handleMA1 == INVALID_HANDLE || handleMA2 == INVALID_HANDLE)
   {
      Print("MA handle létrehozása sikertelen!");
      return(INIT_FAILED);
   }

   IndicatorSetString(INDICATOR_SHORTNAME,
      "DualMA_Cross(" + (string)MA1_Period + "," + (string)MA2_Period + ")");

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   if(handleMA1 != INVALID_HANDLE) IndicatorRelease(handleMA1);
   if(handleMA2 != INVALID_HANDLE) IndicatorRelease(handleMA2);
}

//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double   &open[],
                const double   &high[],
                const double   &low[],
                const double   &close[],
                const long     &tick_volume[],
                const long     &volume[],
                const int      &spread[])
{
   int minBars = MathMax(MA1_Period, MA2_Period) + 3;
   if(rates_total < minBars) return(0);

   // Temp tömbök a CopyBuffer-hez (forward sorrend: [0]=legrégibb)
   double tmpMA1[], tmpMA2[];

   if(CopyBuffer(handleMA1, 0, 0, rates_total, tmpMA1) < rates_total) return(prev_calculated);
   if(CopyBuffer(handleMA2, 0, 0, rates_total, tmpMA2) < rates_total) return(prev_calculated);

   // Másoljuk az indicator bufferekbe (forward = MT5 natív sorrend)
   ArrayCopy(MA1Buf, tmpMA1);
   ArrayCopy(MA2Buf, tmpMA2);

   // Kezdőindex meghatározása
   // prev_calculated == 0 → teljes újraszámítás (TF váltás is ezt triggereli)
   int start;
   if(prev_calculated <= 0)
   {
      // Teljes törlés TF váltáskor
      ArrayInitialize(UpBuf,  0.0);
      ArrayInitialize(DnBuf,  0.0);
      ArrayInitialize(SigBuf, 0.0);
      start = minBars; // legrégibb számítható bar
   }
   else
   {
      start = prev_calculated - 1; // utolsó ismert bar újraszámítása
   }

   double gap = ArrowGap * _Point;

   //--------------------------------------------------------------------
   // Főciklus (forward: i=régi → i=új, [rates_total-1] = legfrissebb)
   //--------------------------------------------------------------------
   for(int i = start; i < rates_total; i++)
   {
      // Ha már zárt és rögzített jel van → skip
      // (csak i < rates_total-1 esetén, a live barra mindig újraszámolunk)
      if(i < rates_total - 1 && SigBuf[i] != 0.0)
         continue;

      double ma1_cur  = tmpMA1[i];
      double ma2_cur  = tmpMA2[i];
      double ma1_prev = tmpMA1[i-1];
      double ma2_prev = tmpMA2[i-1];

      bool crossUp   = (ma1_prev <  ma2_prev) && (ma1_cur >= ma2_cur);
      bool crossDown = (ma1_prev >  ma2_prev) && (ma1_cur <= ma2_cur);

      UpBuf[i] = 0.0;
      DnBuf[i] = 0.0;

      if(crossUp)
      {
         UpBuf[i]  = low[i] - gap;
         SigBuf[i] = 1.0;
      }
      else if(crossDown)
      {
         DnBuf[i]  = high[i] + gap;
         SigBuf[i] = -1.0;
      }
      else
      {
         SigBuf[i] = 0.0;
      }
   }

   //--------------------------------------------------------------------
   // Alert (csak az aktuális barra)
   //--------------------------------------------------------------------
   int last = rates_total - 1;
   if(EnableAlert && prev_calculated > 0 && lastAlertBar != time[last])
   {
      bool isUp   = (UpBuf[last] != 0.0);
      bool isDn   = (DnBuf[last] != 0.0);
      if(isUp || isDn)
      {
         string dir = isUp ? "BUY  MA1 crossed above MA2" : "SELL  MA1 crossed below MA2";
         string msg = _Symbol + " " + TFtoStr(_Period) + " | DualMA: " + dir;
         Alert(msg);
         if(EnableSound) PlaySound(SoundFile);
         if(EnablePush)  SendNotification(msg);
         lastAlertBar = time[last];
      }
   }

   return(rates_total);
}

//+------------------------------------------------------------------+
string TFtoStr(ENUM_TIMEFRAMES tf)
{
   switch(tf)
   {
      case PERIOD_M1:  return("M1");
      case PERIOD_M5:  return("M5");
      case PERIOD_M15: return("M15");
      case PERIOD_M30: return("M30");
      case PERIOD_H1:  return("H1");
      case PERIOD_H4:  return("H4");
      case PERIOD_D1:  return("D1");
      case PERIOD_W1:  return("W1");
      case PERIOD_MN1: return("MN");
      default:         return("TF");
   }
}