#property strict
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots 2
#property indicator_label1 "Arrow Up"
#property indicator_type1  DRAW_ARROW
#property indicator_color1 clrAqua
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
#property indicator_label2 "Arrow Down"
#property indicator_type2  DRAW_ARROW
#property indicator_color2 clrMagenta
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
#property indicator_type2 DRAW_NONE
//--- indicator buffers
double ArrowUp[];
double ArrowDn[];
double xATRTrailingStop[];

//--- variables
double nLoss, xATR;

// ------------------------------------------------------------------
input double m          = 3;      // Key value:
input double atrPeriods = 6;     // ATR periods:
input bool   h          = false;  // Signals From Heinken Ashi Candles

input string T1                    = "== Notifications ==";  // ————————————
input bool   notifications         = false;                  // Notifications On?
input bool   desktop_notifications = false;                  // Desktop MT4 Notifications
input bool   email_notifications   = false;                  // Email Notifications
input bool   push_notifications    = false;                  // Push Mobile Notifications
input string T2                    = "== Set Arrows ==";     // ————————————
input bool   ArrowsOn              = true;                   // Arrows On?
input color  ArrowUpClr            = clrAqua;                // Arrow Up Color:
input color  ArrowDnClr            = clrMagenta;             // Arrow Down Color:
// ------------------------------------------------------------------
class CCandle
{
  int    _timeFrame;
  string _symbol;
  double _open;
  double _high;
  double _low;
  double _close;
  float  _size;
  string _type;
  string _direction;
  float  _bodySize;
  float  _shadowSup;
  float  _shadowInf;

 public:
  CCandle() { ; }
  CCandle(string sym, int tf) : _symbol(sym), _timeFrame(tf) {}
  ~CCandle() { ; }

  // Getters
  float  Size(void) { return _size; }
  string Type(void) { return _type; }
  double Open(void) { return _open; }
  double High(void) { return _high; }
  double Low(void) { return _low; }
  double Close(void) { return _close; }
  string Direction(void) { return _direction; }
  float  BodySize(void) { return _bodySize; }
  float  ShadowSup(void) { return _shadowSup; }
  float  ShadowInf(void) { return _shadowInf; }

  void setCandle(int shift = 1)
  {
    _open  = iOpen(_symbol, _timeFrame, shift);
    _high  = iHigh(_symbol, _timeFrame, shift);
    _low   = iLow(_symbol, _timeFrame, shift);
    _close = iClose(_symbol, _timeFrame, shift);

    setDirection();
    setSize();
    setBodySize();
    setShadows();
  }
  void setSize()
  {
    _size = 1;
    if (Distance(_high, _low, _symbol) > 0)
    {
      _size = Distance(_high, _low, _symbol);
    }
  }
  void setBodySize()
  {
    _bodySize = 1;
    if (Distance(_open, _close, _symbol) > 0)
    {
      _bodySize = Distance(_open, _close, _symbol);
    }
  }
  void setDirection()
  {
    if (_open < _close)
    {
      _direction = "up";
    }
    if (_open > _close)
    {
      _direction = "down";
    }
    if (_open == _close)
    {
      _direction = "null";
    }
  }
  void PrintCandle()
  {
    Print(__FUNCTION__, " ", "symbol", " ", _symbol);
    Print(__FUNCTION__, " ", "open", " ", _open);
    Print(__FUNCTION__, " ", "high", " ", _high);
    Print(__FUNCTION__, " ", "low", " ", _low);
    Print(__FUNCTION__, " ", "close", " ", _close);
    Print(__FUNCTION__, " ", "_size;", " ", _size);
    Print(__FUNCTION__, " ", "_type;", " ", _type);
    Print(__FUNCTION__, " ", "_direction;", " ", _direction);
    Print(__FUNCTION__, " ", "_bodySize;", " ", _bodySize);
    Print(__FUNCTION__, " ", "_shadowSup;", " ", _shadowSup);
    Print(__FUNCTION__, " ", "_shadowInf;", " ", _shadowInf);
  }
  void setShadows()
  {
    if (Direction() == "up")
    {
      _shadowInf = Distance(_open, _low, _symbol);
      _shadowSup = Distance(_close, _high, _symbol);
    }
    if (Direction() == "down")
    {
      _shadowInf = Distance(_close, _low, _symbol);
      _shadowSup = Distance(_open, _high, _symbol);
    }
    if (Direction() == "null")
    {
      _shadowInf = Distance(_close, _low, _symbol);
      _shadowSup = Distance(_open, _high, _symbol);
    }
  }
  float Distance(double precioA, double precioB, string par)
  {
    double mPoint     = MarketInfo(par, MODE_POINT);
    double dist       = fabs(precioA - precioB);
    double distReturn = 0;
    if (mPoint > 0) distReturn = dist / mPoint;
    return distReturn;
  }
};
CCandle candle1();
CCandle candle2();

class CNewCandle
{
 private:
  int    _initialCandles;
  string _symbol;
  int    _tf;

 public:
  CNewCandle(string symbol, int tf) : _symbol(symbol), _tf(tf), _initialCandles(iBars(symbol, tf)) {}
  CNewCandle()
  {
    // toma los valores del chart actual
    _initialCandles = iBars(Symbol(), Period());
    _symbol         = Symbol();
    _tf             = Period();
  }
  ~CNewCandle() { ; }

  bool IsNewCandle()
  {
    int _currentCandles = iBars(_symbol, _tf);
    if (_currentCandles > _initialCandles)
    {
      _initialCandles = _currentCandles;
      return true;
    }

    return false;
  }
};
CNewCandle newCandle();

// ------------------------------------------------------------------
int OnInit()
{
  //--- indicator buffers mapping
  SetIndexBuffer(0, ArrowUp, INDICATOR_DATA);
  SetIndexArrow(0, 221);
  SetIndexStyle(0, DRAW_ARROW, EMPTY, 1, ArrowUpClr);
  SetIndexBuffer(1, ArrowDn, INDICATOR_DATA);
  SetIndexArrow(1, 222);
  SetIndexStyle(1, DRAW_ARROW, EMPTY, 1, ArrowDnClr);
  SetIndexBuffer(2, xATRTrailingStop);
  SetIndexStyle(2, DRAW_NONE);

  if (!ArrowsOn)
  {
    SetIndexStyle(0, DRAW_NONE);
    SetIndexStyle(1, DRAW_NONE);
  }
  //---
  return (INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {}
// ------------------------------------------------------------------

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 i = 1000;
  if (i >= rates_total) i = rates_total - 1;
  for (; i > 0; i--)
  {
    xATR  = iATR(NULL, 0, atrPeriods, i);
    nLoss = m * xATR;

    double cl  = close[i];
    double cl1 = close[i + 1];
	
		// clang-format off
    xATRTrailingStop[i] = cl > xATRTrailingStop[i + 1] && cl1 > xATRTrailingStop[i + 1] ? fmax(xATRTrailingStop[i + 1], cl - nLoss) : 
		   									  cl < xATRTrailingStop[i + 1] && cl1 < xATRTrailingStop[i + 1] ? fmin(xATRTrailingStop[i + 1], cl + nLoss) : 
													cl > xATRTrailingStop[i + 1] ? cl - nLoss : cl + nLoss;
    
		
		
		bool crossUp = cl > xATRTrailingStop[i] && cl1 < xATRTrailingStop[i+1];
		bool crossDn = cl < xATRTrailingStop[i] && cl1 > xATRTrailingStop[i+1];

		if (cl > xATRTrailingStop[i] && crossUp==true)
    {
      ArrowUp[i] = low[i] - xATR/2;

      if (newCandle.IsNewCandle()) { Notifications(0); }
    }

    if (cl < xATRTrailingStop[i] && crossDn == true)
    {
      ArrowDn[i] = high[i] + xATR/2;

      if (newCandle.IsNewCandle()) { Notifications(1); }
    }
  }

  return (rates_total);
}

// ------------------------------------------------------------------
void setCandles(int i, int shift)
{
  candle1.setCandle(i + shift);
  candle2.setCandle(i);
}

// clang-format off
bool haveSignalUp(int i) 
{
  // TODO: signal up
	
	// double cl =  iClose(NULL,0,i);
	
	// if(cl > xATRTrailingStop[i] )
  // {
  //   return true;
  // }

  return false;
}

bool haveSignalDown(int i)
{
  // TODO: signal down
  
	// double cl =  iClose(NULL,0,i);

	// if(cl  < xATRTrailingStop[i] )
  // {
  //   return true;
  // }

  return false;
}

void Notifications(int type)
{
  string text = "";
  if (type == 0)
    text += _Symbol + " " + GetTimeFrame(_Period) + " BUY ";
  else
    text += _Symbol + " " + GetTimeFrame(_Period) + " SELL ";

  text += " ";

  if (!notifications)
    return;
  if (desktop_notifications)
    Alert(text);
  if (push_notifications)
    SendNotification(text);
  if (email_notifications)
    SendMail("MetaTrader Notification", text);
}

string GetTimeFrame(int lPeriod)
{
  switch (lPeriod)
  {
    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 ("MN1");
  }
  return IntegerToString(lPeriod);
}
