//+------------------------------------------------------------------+
//|                            Fibo Retracement with Button Controls |
//|                                     Modified with 3 Fibo Buttons |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 1

// ZigZag Settings
extern int     ExtDepth         = 30;
extern int     ExtDeviation     = 5;
extern int     ExtBackstep      = 3;
extern string  FiboLevels       = "0;23.6;38.2;50.0;61.8;76.4;100.0";

// Fibo 1 Settings (oldest/third fibo)
extern color   Fibo1Color       = clrDarkGreen;
extern int     Fibo1Width       = 1;
extern int     Fibo1Style       = STYLE_DOT;
extern int     Fibo1LevelsStyle = STYLE_SOLID;

// Fibo 2 Settings (middle/second fibo)
extern color   Fibo2Color       = clrDarkSlateGray;
extern int     Fibo2Width       = 1;
extern int     Fibo2Style       = STYLE_DOT;
extern int     Fibo2LevelsStyle = STYLE_SOLID;

// Fibo 3 Settings (newest/first fibo)
extern color   Fibo3Color       = clrDodgerBlue;
extern int     Fibo3Width       = 1;
extern int     Fibo3Style       = STYLE_DOT;
extern int     Fibo3LevelsStyle = STYLE_SOLID;

// Golden Fibo Settings (highlights key ratios: 38.2%, 50%, 61.8%)
extern string  golden_note      = "--------- Golden Fibo ---------";
extern bool    ShowGoldenFibo   = true;
extern color   GoldenFiboColor  = clrDarkGoldenrod;
extern int     GoldenFiboWidth  = 2;
extern string  golden_note2     = "------------------------------";

// Button Settings
extern string  button_note1       = "--------- Fibo Buttons ---------";
extern ENUM_BASE_CORNER btn_corner = CORNER_LEFT_UPPER;
extern string  btn_Font           = "Arial";
extern int     btn_FontSize       = 9;
extern color   btn_text_ON_color  = clrLime;
extern color   btn_text_OFF_color = clrRed;
extern color   btn_background_color = clrDimGray;
extern color   btn_border_color   = clrBlack;
extern int     button_x           = 20;
extern int     button_y           = 95;
extern int     btn_Height         = 20;
extern string  UniqueButtonID     = "FIBO_BTN";
extern string  button_note2       = "------------------------------";

// Alert Settings
extern string  _                      = "alerts behaviour";
extern bool    alertsOn               = false;
extern double  alertsTolerance        = 1.0;
extern bool    touchChanell           = false;
extern bool    alertsOnCurrent        = false;
extern bool    alertsMessage          = true;
extern bool    alertsSound            = false;
extern bool    alertsNotify           = false;
extern bool    alertsEmail            = false;
extern bool    alertsShowTouched      = true;
extern string  soundFile              = "alert2.wav"; 

// Candle Display Settings
extern int     barsToShowCandles      = 1000;
extern color   BarUpColor             = clrGreen; 
extern color   BarDownColor           = clrRed; 
extern color   WickColor              = clrGray;
extern int     CandleWidth            = 3;

//+------------------------------------------------------------------+
//| Global Variables                                                 |
//+------------------------------------------------------------------+
double ExtMapBuffer[], ExtLowBuffer[], ExtHighBuffer[], levelv[], values[];
int    totalCandles;
string windowID, levels[];

// Button state variables
bool show_fibo1 = true;
bool show_fibo2 = true;
bool show_fibo3 = true;
string buttonId1, buttonId2, buttonId3;
int btn_Subwindow = 0;

//+------------------------------------------------------------------+
//| Initialization                                                   |
//+------------------------------------------------------------------+
int init() {
   // Parse Fibo Levels
   FiboLevels = StringTrimLeft(StringTrimRight(FiboLevels));
   if (StringSubstr(FiboLevels, StringLen(FiboLevels), 1) != ";")
      FiboLevels = StringConcatenate(FiboLevels, ";");

   int s = 0;
   int i = StringFind(FiboLevels, ";", s);
   string current;
   
   while (i > 0) {
      current = StringSubstr(FiboLevels, s, i - s);
      ArrayResize(levels, ArraySize(levels) + 1);
      levels[ArraySize(levels) - 1] = "(F" + current + "%%) - $%$";
      ArrayResize(levelv, ArraySize(levelv) + 1);
      levelv[ArraySize(levelv) - 1] = StrToDouble(current);
      s = i + 1;
      i = StringFind(FiboLevels, ";", s);
   }
   ArrayResize(values, ArraySize(levelv));
   
   // Setup buffers
   IndicatorBuffers(4);
   SetIndexBuffer(1, ExtMapBuffer);
   SetIndexBuffer(2, ExtLowBuffer);
   SetIndexBuffer(3, ExtHighBuffer);
   SetIndexEmptyValue(1, 0.0);
   SetIndexEmptyValue(2, 0.0);
   SetIndexEmptyValue(3, 0.0);
   IndicatorShortName("Fibo Retracement(" + ExtDepth + "," + ExtDeviation + "," + ExtBackstep + ")");
   
   // Create buttons
   buttonId1 = "_" + UniqueButtonID + "_BT1_";
   buttonId2 = "_" + UniqueButtonID + "_BT2_";
   buttonId3 = "_" + UniqueButtonID + "_BT3_";
   
   if (ObjectFind(buttonId1) < 0) 
      createButton(buttonId1, "FIB1", 35, btn_Height, btn_Font, btn_FontSize, btn_background_color, btn_border_color, btn_text_ON_color);
   if (ObjectFind(buttonId2) < 0) 
      createButton(buttonId2, "FIB2", 35, btn_Height, btn_Font, btn_FontSize, btn_background_color, btn_border_color, btn_text_ON_color);
   if (ObjectFind(buttonId3) < 0) 
      createButton(buttonId3, "FIB3", 35, btn_Height, btn_Font, btn_FontSize, btn_background_color, btn_border_color, btn_text_ON_color);
   
   // Position buttons horizontally
   ObjectSetInteger(0, buttonId1, OBJPROP_XDISTANCE, button_x);
   ObjectSetInteger(0, buttonId1, OBJPROP_YDISTANCE, button_y);
   
   ObjectSetInteger(0, buttonId2, OBJPROP_XDISTANCE, button_x + 35);
   ObjectSetInteger(0, buttonId2, OBJPROP_YDISTANCE, button_y);
   
   ObjectSetInteger(0, buttonId3, OBJPROP_XDISTANCE, button_x + 70);
   ObjectSetInteger(0, buttonId3, OBJPROP_YDISTANCE, button_y);
   
   // Restore button states from global variables
   string gv_fib1 = "FIBO_" + _Symbol + "_fib1";
   string gv_fib2 = "FIBO_" + _Symbol + "_fib2";
   string gv_fib3 = "FIBO_" + _Symbol + "_fib3";
   
   if (GlobalVariableCheck(gv_fib1)) {
      show_fibo1 = (GlobalVariableGet(gv_fib1) > 0);
      ObjectSetInteger(0, buttonId1, OBJPROP_STATE, show_fibo1);
   } else {
      show_fibo1 = ObjectGetInteger(0, buttonId1, OBJPROP_STATE);
   }
   
   if (GlobalVariableCheck(gv_fib2)) {
      show_fibo2 = (GlobalVariableGet(gv_fib2) > 0);
      ObjectSetInteger(0, buttonId2, OBJPROP_STATE, show_fibo2);
   } else {
      show_fibo2 = ObjectGetInteger(0, buttonId2, OBJPROP_STATE);
   }
   
   if (GlobalVariableCheck(gv_fib3)) {
      show_fibo3 = (GlobalVariableGet(gv_fib3) > 0);
      ObjectSetInteger(0, buttonId3, OBJPROP_STATE, show_fibo3);
   } else {
      show_fibo3 = ObjectGetInteger(0, buttonId3, OBJPROP_STATE);
   }
   
   // Save states
   GlobalVariableSet(gv_fib1, show_fibo1 ? 1 : 0);
   GlobalVariableSet(gv_fib2, show_fibo2 ? 1 : 0);
   GlobalVariableSet(gv_fib3, show_fibo3 ? 1 : 0);
   
   // Set button colors
   if (show_fibo1) ObjectSetInteger(0, buttonId1, OBJPROP_COLOR, btn_text_ON_color);
   else ObjectSetInteger(0, buttonId1, OBJPROP_COLOR, btn_text_OFF_color);
   
   if (show_fibo2) ObjectSetInteger(0, buttonId2, OBJPROP_COLOR, btn_text_ON_color);
   else ObjectSetInteger(0, buttonId2, OBJPROP_COLOR, btn_text_OFF_color);
   
   if (show_fibo3) ObjectSetInteger(0, buttonId3, OBJPROP_COLOR, btn_text_ON_color);
   else ObjectSetInteger(0, buttonId3, OBJPROP_COLOR, btn_text_OFF_color);
   
   return(0);
}

//+------------------------------------------------------------------+
//| Create Button                                                    |
//+------------------------------------------------------------------+
void createButton(string buttonID, string buttonText, int width2, int height, string font, int fontSize, color bgColor, color borderColor, color txtColor) {
   ObjectDelete(0, buttonID);
   ObjectCreate(0, buttonID, OBJ_BUTTON, btn_Subwindow, 0, 0);
   ObjectSetInteger(0, buttonID, OBJPROP_COLOR, txtColor);
   ObjectSetInteger(0, buttonID, OBJPROP_BGCOLOR, bgColor);
   ObjectSetInteger(0, buttonID, OBJPROP_BORDER_COLOR, borderColor);
   ObjectSetInteger(0, buttonID, OBJPROP_BORDER_TYPE, BORDER_RAISED);
   ObjectSetInteger(0, buttonID, OBJPROP_XSIZE, width2);
   ObjectSetInteger(0, buttonID, OBJPROP_YSIZE, height);
   ObjectSetString(0, buttonID, OBJPROP_FONT, font);
   ObjectSetString(0, buttonID, OBJPROP_TEXT, buttonText);
   ObjectSetInteger(0, buttonID, OBJPROP_FONTSIZE, fontSize);
   ObjectSetInteger(0, buttonID, OBJPROP_SELECTABLE, 0);
   ObjectSetInteger(0, buttonID, OBJPROP_CORNER, btn_corner);
   ObjectSetInteger(0, buttonID, OBJPROP_HIDDEN, 1);
   ObjectSetInteger(0, buttonID, OBJPROP_XDISTANCE, 9999);
   ObjectSetInteger(0, buttonID, OBJPROP_YDISTANCE, 9999);
   ObjectSetInteger(0, buttonID, OBJPROP_STATE, true);
}

//+------------------------------------------------------------------+
//| Chart Event Handler                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) {
   if(id == CHARTEVENT_OBJECT_CREATE || id == CHARTEVENT_OBJECT_DELETE) return;
   if(id == CHARTEVENT_MOUSE_MOVE || id == CHARTEVENT_MOUSE_WHEEL) return;

   // Handle FIB1 button
   if (id == CHARTEVENT_OBJECT_CLICK && sparam == buttonId1) {
      show_fibo1 = ObjectGetInteger(0, buttonId1, OBJPROP_STATE);
      GlobalVariableSet("FIBO_" + _Symbol + "_fib1", show_fibo1 ? 1 : 0);
      
      if (show_fibo1) {
         ObjectSetInteger(0, buttonId1, OBJPROP_COLOR, btn_text_ON_color);
         start();  // Recreate Fibo object
      } else {
         ObjectSetInteger(0, buttonId1, OBJPROP_COLOR, btn_text_OFF_color);
         ObjectDelete("Fibo1");
         ObjectDelete("GoldenFibo1");  // Also delete golden fibo
      }
   }
   
   // Handle FIB2 button
   if (id == CHARTEVENT_OBJECT_CLICK && sparam == buttonId2) {
      show_fibo2 = ObjectGetInteger(0, buttonId2, OBJPROP_STATE);
      GlobalVariableSet("FIBO_" + _Symbol + "_fib2", show_fibo2 ? 1 : 0);
      
      if (show_fibo2) {
         ObjectSetInteger(0, buttonId2, OBJPROP_COLOR, btn_text_ON_color);
         start();  // Recreate Fibo object
      } else {
         ObjectSetInteger(0, buttonId2, OBJPROP_COLOR, btn_text_OFF_color);
         ObjectDelete("Fibo2");
         ObjectDelete("GoldenFibo2");  // Also delete golden fibo
      }
   }
   
   // Handle FIB3 button
   if (id == CHARTEVENT_OBJECT_CLICK && sparam == buttonId3) {
      show_fibo3 = ObjectGetInteger(0, buttonId3, OBJPROP_STATE);
      GlobalVariableSet("FIBO_" + _Symbol + "_fib3", show_fibo3 ? 1 : 0);
      
      if (show_fibo3) {
         ObjectSetInteger(0, buttonId3, OBJPROP_COLOR, btn_text_ON_color);
         start();  // Recreate Fibo object
      } else {
         ObjectSetInteger(0, buttonId3, OBJPROP_COLOR, btn_text_OFF_color);
         ObjectDelete("Fibo3");
         ObjectDelete("GoldenFibo3");  // Also delete golden fibo
      }
   }
}


//+------------------------------------------------------------------+
//| Deinitialization                                                 |
//+------------------------------------------------------------------+
int deinit() {
   if (ObjectFind(buttonId1) >= 0) ObjectDelete(buttonId1);
   if (ObjectFind(buttonId2) >= 0) ObjectDelete(buttonId2);
   if (ObjectFind(buttonId3) >= 0) ObjectDelete(buttonId3);
   
   ObjectDelete("Fibo1");
   ObjectDelete("Fibo2");
   ObjectDelete("Fibo3");
   ObjectDelete("GoldenFibo1");
   ObjectDelete("GoldenFibo2");
   ObjectDelete("GoldenFibo3");
   deleteCandles();
   return(0);
}

//+------------------------------------------------------------------+
//| Main Start Function                                              |
//+------------------------------------------------------------------+
int start() {
   CalculateZigZag();

   string fibo;
   int i;
   int LastZigZag;
   int PreviousZigZag;
   int PPreviousZigZag;
   int PPPreviousZigZag;
   
   for (int z=0; z<Bars; z++) { if (ExtMapBuffer[z]!=0) break; } LastZigZag=z;
   for (z++; z<Bars; z++) { if (ExtMapBuffer[z]!=0) break; } PreviousZigZag=z;
   for (z++; z<Bars; z++) { if (ExtMapBuffer[z]!=0) break; } PPreviousZigZag=z;
   for (z++; z<Bars; z++) { if (ExtMapBuffer[z]!=0) break; } PPPreviousZigZag=z;
   
   // === FIBO 3 (Newest/Latest) ===
   if (show_fibo3) {
      fibo = "Fibo3";           
      if (ObjectFind(fibo) == -1) {
         ObjectCreate(fibo, OBJ_FIBO, 0, Time[PreviousZigZag], ExtMapBuffer[LastZigZag], Time[LastZigZag], ExtMapBuffer[PreviousZigZag]);
         ObjectSet(fibo, OBJPROP_COLOR, Fibo3Color);
         ObjectSet(fibo, OBJPROP_STYLE, Fibo3Style);
         ObjectSet(fibo, OBJPROP_WIDTH, Fibo3Width);
         ObjectSet(fibo, OBJPROP_LEVELCOLOR, Fibo3Color);
         ObjectSet(fibo, OBJPROP_LEVELSTYLE, Fibo3LevelsStyle);
         // Only show 4 levels: 0%, 23.6%, 76.4%, 100%
         ObjectSet(fibo, OBJPROP_FIBOLEVELS, 4);
         ObjectSet(fibo, OBJPROP_FIRSTLEVEL + 0, 0.0); 
         ObjectSetFiboDescription(fibo, 0, "(F0.0%%) - $%$");
         ObjectSet(fibo, OBJPROP_FIRSTLEVEL + 1, 0.236); 
         ObjectSetFiboDescription(fibo, 1, "(F23.6%%) - $%$");
         ObjectSet(fibo, OBJPROP_FIRSTLEVEL + 2, 0.764); 
         ObjectSetFiboDescription(fibo, 2, "(F76.4%%) - $%$");
         ObjectSet(fibo, OBJPROP_FIRSTLEVEL + 3, 1.0); 
         ObjectSetFiboDescription(fibo, 3, "(F100.0%%) - $%$");
      }
      ObjectSet(fibo, OBJPROP_TIME1, Time[PreviousZigZag]);
      ObjectSet(fibo, OBJPROP_TIME2, Time[LastZigZag]);
      ObjectSet(fibo, OBJPROP_PRICE1, ExtMapBuffer[LastZigZag]);
      ObjectSet(fibo, OBJPROP_PRICE2, ExtMapBuffer[PreviousZigZag]);
      
      // Create Golden Fibo overlay
      if (ShowGoldenFibo) {
         CreateGoldenFibo("GoldenFibo3", Time[PreviousZigZag], ExtMapBuffer[LastZigZag], Time[LastZigZag], ExtMapBuffer[PreviousZigZag]);
      } else {
         ObjectDelete("GoldenFibo3");
      }
   } else {
      ObjectDelete("GoldenFibo3");
   }
   
   // === FIBO 2 (Middle) ===
   if (show_fibo2) {
      fibo = "Fibo2";
      if (ObjectFind(fibo) == -1) {
         ObjectCreate(fibo, OBJ_FIBO, 0, Time[PPreviousZigZag], ExtMapBuffer[PreviousZigZag], Time[PreviousZigZag], ExtMapBuffer[PPreviousZigZag]);
         ObjectSet(fibo, OBJPROP_COLOR, Fibo2Color);
         ObjectSet(fibo, OBJPROP_STYLE, Fibo2Style);
         ObjectSet(fibo, OBJPROP_WIDTH, Fibo2Width);
         ObjectSet(fibo, OBJPROP_LEVELCOLOR, Fibo2Color);
         ObjectSet(fibo, OBJPROP_LEVELSTYLE, Fibo2LevelsStyle);
         // Only show 4 levels: 0%, 23.6%, 76.4%, 100%
         ObjectSet(fibo, OBJPROP_FIBOLEVELS, 4);
         ObjectSet(fibo, OBJPROP_FIRSTLEVEL + 0, 0.0); 
         ObjectSetFiboDescription(fibo, 0, "(F0.0%%) - $%$");
         ObjectSet(fibo, OBJPROP_FIRSTLEVEL + 1, 0.236); 
         ObjectSetFiboDescription(fibo, 1, "(F23.6%%) - $%$");
         ObjectSet(fibo, OBJPROP_FIRSTLEVEL + 2, 0.764); 
         ObjectSetFiboDescription(fibo, 2, "(F76.4%%) - $%$");
         ObjectSet(fibo, OBJPROP_FIRSTLEVEL + 3, 1.0); 
         ObjectSetFiboDescription(fibo, 3, "(F100.0%%) - $%$");
      }
      ObjectSet(fibo, OBJPROP_TIME1, Time[PPreviousZigZag]);
      ObjectSet(fibo, OBJPROP_TIME2, Time[PreviousZigZag]);
      ObjectSet(fibo, OBJPROP_PRICE1, ExtMapBuffer[PreviousZigZag]);
      ObjectSet(fibo, OBJPROP_PRICE2, ExtMapBuffer[PPreviousZigZag]);
      
      // Create Golden Fibo overlay
      if (ShowGoldenFibo) {
         CreateGoldenFibo("GoldenFibo2", Time[PPreviousZigZag], ExtMapBuffer[PreviousZigZag], Time[PreviousZigZag], ExtMapBuffer[PPreviousZigZag]);
      } else {
         ObjectDelete("GoldenFibo2");
      }
   } else {
      ObjectDelete("GoldenFibo2");
   }
   
   // === FIBO 1 (Oldest) ===
   if (show_fibo1) {
      fibo = "Fibo1";
      if (ObjectFind(fibo) == -1) {
         ObjectCreate(fibo, OBJ_FIBO, 0, Time[PPPreviousZigZag], ExtMapBuffer[PPreviousZigZag], Time[PPreviousZigZag], ExtMapBuffer[PPPreviousZigZag]);
         ObjectSet(fibo, OBJPROP_COLOR, Fibo1Color);
         ObjectSet(fibo, OBJPROP_STYLE, Fibo1Style);
         ObjectSet(fibo, OBJPROP_WIDTH, Fibo1Width);
         ObjectSet(fibo, OBJPROP_LEVELCOLOR, Fibo1Color);
         ObjectSet(fibo, OBJPROP_LEVELSTYLE, Fibo1LevelsStyle);
         // Only show 4 levels: 0%, 23.6%, 76.4%, 100%
         ObjectSet(fibo, OBJPROP_FIBOLEVELS, 4);
         ObjectSet(fibo, OBJPROP_FIRSTLEVEL + 0, 0.0); 
         ObjectSetFiboDescription(fibo, 0, "(F0.0%%) - $%$");
         ObjectSet(fibo, OBJPROP_FIRSTLEVEL + 1, 0.236); 
         ObjectSetFiboDescription(fibo, 1, "(F23.6%%) - $%$");
         ObjectSet(fibo, OBJPROP_FIRSTLEVEL + 2, 0.764); 
         ObjectSetFiboDescription(fibo, 2, "(F76.4%%) - $%$");
         ObjectSet(fibo, OBJPROP_FIRSTLEVEL + 3, 1.0); 
         ObjectSetFiboDescription(fibo, 3, "(F100.0%%) - $%$");
      }
      ObjectSet(fibo, OBJPROP_TIME1, Time[PPPreviousZigZag]);
      ObjectSet(fibo, OBJPROP_TIME2, Time[PPreviousZigZag]);
      ObjectSet(fibo, OBJPROP_PRICE1, ExtMapBuffer[PPreviousZigZag]);
      ObjectSet(fibo, OBJPROP_PRICE2, ExtMapBuffer[PPPreviousZigZag]);
      
      // Create Golden Fibo overlay
      if (ShowGoldenFibo) {
         CreateGoldenFibo("GoldenFibo1", Time[PPPreviousZigZag], ExtMapBuffer[PPreviousZigZag], Time[PPreviousZigZag], ExtMapBuffer[PPPreviousZigZag]);
      } else {
         ObjectDelete("GoldenFibo1");
      }
   } else {
      ObjectDelete("GoldenFibo1");
   }

   if (alertsShowTouched) ShowCandles();
   if (alertsOn) CheckTouches();
   return(0);
}

//+------------------------------------------------------------------+
//| Create Golden Fibo Overlay                                       |
//+------------------------------------------------------------------+
void CreateGoldenFibo(string name, datetime time1, double price1, datetime time2, double price2) {
   if (ObjectFind(name) == -1) {
      ObjectCreate(name, OBJ_FIBO, 0, time1, price1, time2, price2);
   }
   
   // Update position
   ObjectSet(name, OBJPROP_TIME1, time1);
   ObjectSet(name, OBJPROP_TIME2, time2);
   ObjectSet(name, OBJPROP_PRICE1, price1);
   ObjectSet(name, OBJPROP_PRICE2, price2);
   
   // Set golden fibo style
   ObjectSet(name, OBJPROP_STYLE, STYLE_SOLID);
   ObjectSet(name, OBJPROP_WIDTH, GoldenFiboWidth);
   ObjectSet(name, OBJPROP_LEVELCOLOR, GoldenFiboColor);
   ObjectSet(name, OBJPROP_LEVELSTYLE, STYLE_SOLID);
   ObjectSet(name, OBJPROP_LEVELWIDTH, GoldenFiboWidth);
   ObjectSet(name, OBJPROP_RAY, true);
   ObjectSet(name, OBJPROP_BACK, true);
   
   // Set only the 3 golden ratio levels
   ObjectSet(name, OBJPROP_FIBOLEVELS, 3);
   ObjectSet(name, OBJPROP_FIRSTLEVEL + 0, 0.382);
   ObjectSetFiboDescription(name, 0, "(F38.2%%) - $%$");
   ObjectSet(name, OBJPROP_FIRSTLEVEL + 1, 0.500);
   ObjectSetFiboDescription(name, 1, "(F50.0%%) - $%$");
   ObjectSet(name, OBJPROP_FIRSTLEVEL + 2, 0.618);
   ObjectSetFiboDescription(name, 2, "(F61.8%%) - $%$");
}

//+------------------------------------------------------------------+
//| Calculate ZigZag                                                 |
//+------------------------------------------------------------------+
void CalculateZigZag() {
   int shift, back, lasthighpos, lastlowpos, index;
   double val, res;
   double curlow, curhigh, lasthigh, lastlow;

   for(shift = Bars - ExtDepth; shift >= 0; shift--) {
      index = iLowest(NULL, 0, MODE_LOW, ExtDepth, shift);
      val = Low[index];
      if(val == lastlow) val = 0.0;
      else {
         lastlow = val;
         if((Low[shift] - val) > (ExtDeviation * Point)) val = 0.0;
         else {
            for(back = 1; back <= ExtBackstep; back++) {
               res = ExtLowBuffer[shift + back];
               if((res != 0) && (res > val)) ExtLowBuffer[shift + back] = 0.0;
            }
         }
      }
      ExtLowBuffer[shift] = 0.0;
      if(val != 0.0) ExtLowBuffer[index] = val;

      index = iHighest(NULL, 0, MODE_HIGH, ExtDepth, shift);
      val = High[index];
      if(val == lasthigh) val = 0.0;
      else {
         lasthigh = val;
         if((val - High[shift]) > (ExtDeviation * Point)) val = 0.0;
         else {
            for(back = 1; back <= ExtBackstep; back++) {
               res = ExtHighBuffer[shift + back];
               if((res != 0) && (res < val)) ExtHighBuffer[shift + back] = 0.0;
            }
         }
      }
      ExtHighBuffer[shift] = 0.0;
      if(val != 0.0) ExtHighBuffer[index] = val;
   }

   lasthigh = -1; lasthighpos = -1;
   lastlow = -1; lastlowpos = -1;

   for(shift = Bars - ExtDepth; shift >= 0; shift--) {
      curlow = ExtLowBuffer[shift];
      curhigh = ExtHighBuffer[shift];
      if(curlow == 0 && curhigh == 0) continue;

      if(curhigh != 0) {
         if(lasthigh > 0) {
            if(lasthigh < curhigh) ExtHighBuffer[lasthighpos] = 0;
            else ExtHighBuffer[shift] = 0;
         }
         if(lasthigh < curhigh || lasthigh < 0) {
            lasthigh = curhigh;
            lasthighpos = shift;
         }
         lastlow = -1;
      }

      if(curlow != 0) {
         if(lastlow > 0) {
            if(lastlow > curlow) ExtLowBuffer[lastlowpos] = 0;
            else ExtLowBuffer[shift] = 0;
         }
         if((curlow < lastlow) || (lastlow < 0)) {
            lastlow = curlow;
            lastlowpos = shift;
         }
         lasthigh = -1;
      }
   }

   lasthighpos = -1;
   lastlowpos = -1;
   for(shift = Bars - 1; shift >= 0; shift--) {
      if(shift >= Bars - ExtDepth) ExtMapBuffer[shift] = 0.0;
      else {
         curlow = ExtLowBuffer[shift];
         curhigh = ExtHighBuffer[shift];

         res = 0;
         if(curlow != 0) {
            if(lastlowpos == -1) {
               res = curlow;
               lastlowpos = shift;
            } else {
               if(lasthighpos != -1 && lastlowpos > lasthighpos) {
                  res = curlow;
                  lastlowpos = shift;
               }
            }
         }
         if(curhigh != 0) {
            if(lasthighpos == -1) {
               res = curhigh;
               lasthighpos = shift;
            } else {
               if(lastlowpos != -1 && lasthighpos > lastlowpos) {
                  res = curhigh;
                  lasthighpos = shift;
               }
            }
         }
         ExtMapBuffer[shift] = res;
      }
   }
}

//+------------------------------------------------------------------+
//| Fill Fibo Values                                                 |
//+------------------------------------------------------------------+
void fillValues(string forFibo) {
   int fibLines = ObjectGet(forFibo, OBJPROP_FIBOLEVELS);
   double price1 = ObjectGet(forFibo, OBJPROP_PRICE1);
   double price2 = ObjectGet(forFibo, OBJPROP_PRICE2);
   
   for (int i = 0; i < fibLines; i++) {
      if (price1 > price2) values[i] = NormalizeDouble(price2 + (levelv[i] / 100 * (price1 - price2)), Digits);
      if (price1 < price2) values[i] = NormalizeDouble(price1 + (levelv[i] / 100 * (price2 - price1)), Digits);
   }
}

//+------------------------------------------------------------------+
//| Check Touches                                                    |
//+------------------------------------------------------------------+
void CheckTouches() {
   if (show_fibo2 && ObjectFind("Fibo2") >= 0) {
      fillValues("Fibo2");
      for (int i = 0; i < ArraySize(levelv); i++) CheckIfTouched(i, values[i]);
   }
   if (show_fibo1 && ObjectFind("Fibo1") >= 0) {
      fillValues("Fibo1");
      for (i = 0; i < ArraySize(levelv); i++) CheckIfTouched(i, values[i]);
   }
   if (show_fibo3 && ObjectFind("Fibo3") >= 0) {
      fillValues("Fibo3");
      for (i = 0; i < ArraySize(levelv); i++) CheckIfTouched(i, values[i]);
   }
}

//+------------------------------------------------------------------+
//| Check If Touched                                                 |
//+------------------------------------------------------------------+
int CheckIfTouched(int index, double compareTo, bool checking = false, int forBar = 0) {
   int answer = 0;
   double diff = NormalizeDouble(alertsTolerance * Point, Digits);
   double correction;
   double highDiff;
   double lowDiff;
   
   if (touchChanell) {
      correction = NormalizeDouble(alertsTolerance * Point, Digits);
      diff = NormalizeDouble(alertsTolerance * Point * 2, Digits);
   } else correction = 0.00;
   
   int add;
   if (alertsOnCurrent) add = 0;
   else add = 1;
   
   double value = NormalizeDouble(compareTo, Digits);
   highDiff = NormalizeDouble((value + correction) - High[add + forBar], Digits);
   lowDiff = NormalizeDouble(Low[add + forBar] - (value - correction), Digits);
   
   if (checking) {
      if ((highDiff >= 0) && (highDiff <= diff)) answer = -1;
      if ((lowDiff >= 0) && (lowDiff <= diff)) answer = 1;
   } else {
      if ((highDiff >= 0) && (highDiff <= diff)) doAlert("fibo level " + DoubleToStr(levelv[index], 1) + " line touched from down");
      if ((lowDiff >= 0) && (lowDiff <= diff)) doAlert("fibo level " + DoubleToStr(levelv[index], 1) + " line touched from up");
   }
   return(answer);
}

//+------------------------------------------------------------------+
//| Alert Function                                                   |
//+------------------------------------------------------------------+
void doAlert(string doWhat) {
   static string previousAlert = "nothing";
   static datetime previousTime;
   string message;
   
   if (previousAlert != doWhat || previousTime != Time[0]) {
      previousAlert = doWhat;
      previousTime = Time[0];
      
      message = StringConcatenate(Symbol(), " - ", TimeFrameToString(Period()), " chart, at ", TimeToStr(TimeLocal(), TIME_SECONDS), " ", doWhat);
      if (alertsMessage) Alert(message);
      if (alertsNotify) SendNotification(StringConcatenate(Symbol(), Period(), " pivot line touch " + " " + message));
      if (alertsEmail) SendMail(StringConcatenate(Symbol(), " pivot line touch"), message);
      if (alertsSound) PlaySound(soundFile);
   }
}

//+------------------------------------------------------------------+
//| Delete Candles                                                   |
//+------------------------------------------------------------------+
void deleteCandles() {
   while(totalCandles > 0) {
      ObjectDelete(StringConcatenate(windowID, "c-", totalCandles));
      totalCandles -= 1;
   }
}

//+------------------------------------------------------------------+
//| Show Candles                                                     |
//+------------------------------------------------------------------+
void ShowCandles() {
   datetime time1;
   datetime time2;
   
   deleteCandles();
   
   if (show_fibo2 && ObjectFind("Fibo2") >= 0) {
      fillValues("Fibo2");
      time1 = MathMin(ObjectGet("Fibo2", OBJPROP_TIME1), ObjectGet("Fibo2", OBJPROP_TIME2));
      time2 = MathMax(ObjectGet("Fibo2", OBJPROP_TIME1), ObjectGet("Fibo2", OBJPROP_TIME2));
      for (int i = 0; i < barsToShowCandles; i++) {
         if ((Time[i] >= time1) && (Time[i] <= time2)) {
            for (int k = 0; k < ArraySize(levelv); k++)
               if (CheckSingle(k, values[k], i)) continue;
         }
      }
   }
   
   if (show_fibo1 && ObjectFind("Fibo1") >= 0) {
      fillValues("Fibo1");
      time1 = MathMin(ObjectGet("Fibo1", OBJPROP_TIME1), ObjectGet("Fibo1", OBJPROP_TIME2));
      time2 = MathMax(ObjectGet("Fibo1", OBJPROP_TIME1), ObjectGet("Fibo1", OBJPROP_TIME2));
      for (i = 0; i < barsToShowCandles; i++) {
         if ((Time[i] >= time1) && (Time[i] <= time2)) {
            for (k = 0; k < ArraySize(levelv); k++)
               if (CheckSingle(k, values[k], i)) continue;
         }
      }
   }
   
   if (show_fibo3 && ObjectFind("Fibo3") >= 0) {
      fillValues("Fibo3");
      time1 = MathMin(ObjectGet("Fibo3", OBJPROP_TIME1), ObjectGet("Fibo3", OBJPROP_TIME2));
      time2 = MathMax(ObjectGet("Fibo3", OBJPROP_TIME1), ObjectGet("Fibo3", OBJPROP_TIME2));
      for (i = 0; i < barsToShowCandles; i++) {
         if ((Time[i] >= time1) && (Time[i] <= time2)) {
            for (k = 0; k < ArraySize(levelv); k++)
               if (CheckSingle(k, values[k], i)) continue;
         }
      }
   }
}

//+------------------------------------------------------------------+
//| Check Single                                                     |
//+------------------------------------------------------------------+
bool CheckSingle(int index, double array, int shift) {
   int result = CheckIfTouched(index, array, true, shift);
   if (result != 0) {
      if (alertsOnCurrent) DrawCandle(shift, result);
      else DrawCandle(shift + 1, result);
      return(true);
   } else {
      return(false);
   }
}

//+------------------------------------------------------------------+
//| Draw Candle                                                      |
//+------------------------------------------------------------------+
void DrawCandle(int shift, int upDown) {
   datetime time = Time[shift];
   double high = iHigh(NULL, 0, shift);
   double low = iLow(NULL, 0, shift);
   double open = iOpen(NULL, 0, shift);
   double close = iClose(NULL, 0, shift);
   string name;
   
   totalCandles += 1;
   name = windowID + "c-" + totalCandles;
   ObjectCreate(name, OBJ_TREND, 0, time, high, time, low);
   ObjectSet(name, OBJPROP_COLOR, WickColor);
   ObjectSet(name, OBJPROP_RAY, false);
   
   totalCandles += 1;
   name = windowID + "c-" + totalCandles;
   ObjectCreate(name, OBJ_TREND, 0, time, open, time, close);
   ObjectSet(name, OBJPROP_WIDTH, CandleWidth);
   ObjectSet(name, OBJPROP_RAY, false);
   if (upDown > 0)
      ObjectSet(name, OBJPROP_COLOR, BarUpColor);
   else
      ObjectSet(name, OBJPROP_COLOR, BarDownColor);
}

//+------------------------------------------------------------------+
//| TimeFrame To String                                              |
//+------------------------------------------------------------------+
string TimeFrameToString(int tf) {
   string tfs = "Current time frame";
   switch(tf) {
      case PERIOD_M1: tfs = "M1"; break;
      case PERIOD_M5: tfs = "M5"; break;
      case PERIOD_M15: tfs = "M15"; break;
      case PERIOD_M30: tfs = "M30"; break;
      case PERIOD_H1: tfs = "H1"; break;
      case PERIOD_H4: tfs = "H4"; break;
      case PERIOD_D1: tfs = "D1"; break;
      case PERIOD_W1: tfs = "W1"; break;
      case PERIOD_MN1: tfs = "MN1";
   }
   return(tfs);
}
//+------------------------------------------------------------------+
