//+------------------------------------------------------------------+
//|                                                     Ichimoku.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property description "Ichimoku Kinko Hyo"
//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots   4
#property indicator_type1   DRAW_LINE
#property indicator_type2   DRAW_LINE
#property indicator_type3   DRAW_FILLING
#property indicator_type4   DRAW_LINE
#property indicator_color1  clrNONE//clrSeashell
#property indicator_color2  clrNONE//clrHoneydew
#property indicator_color3  clrHoneydew,clrSeashell
#property indicator_color4  clrNONE//clrLime
#property indicator_label1  "Tenkan-sen"
#property indicator_label2  "Kijun-sen"
#property indicator_label3  "Senkou Span A;Senkou Span B"
#property indicator_label4  "Chikou Span"
//--- input parameters
input int InpTenkan=1;     // Tenkan-sen
input int InpKijun=1;      // Kijun-sen
input int InpSenkou=89;    // Senkou Span B

//Forex-Station button template start41; copy and paste
input string             button_note1          = "------------------------------"; // ------------------------------
input int                btn_Subwindow         = 0;                 // What window to put the button on.  If <0, the button will use the same sub-window as the indicator.
input ENUM_BASE_CORNER   btn_corner            = CORNER_LEFT_UPPER; // chart btn_corner for anchoring
input string             btn_text              = "ICHI";            // Display id
input string             btn_Font              = "Arial";           // button font name
input int                btn_FontSize          = 9;                 // btn__font size
input color              btn_text_ON_color     = clrLime;           // ON color when the button is turned on
input color              btn_text_OFF_color    = clrRed;            // OFF color when the button is turned off
input color              btn_background_color  = clrDimGray;        // background color of the button
input color              btn_border_color      = clrBlack;          // border color the button
input int                button_x              = 20;                // Horizontal location
input int                button_y              = 135;               // Vertical location
input int                btn_Width             = 80;                // btn__width
input int                btn_Height            = 20;                // btn__height
input string             UniqueButtonID        = "Ichimoku";        // Unique ID for each button        
input string             button_note2          = "------------------------------"; // ------------------------------

string IndicatorObjPrefix, buttonId;
bool IndicatorEnabled = true;
//Forex-Station button template end41; copy and paste

//--- indicator buffers
double    ExtTenkanBuffer[], ExtKijunBuffer[], ExtSpanABuffer[], ExtSpanBBuffer[], ExtChikouBuffer[];
//+------------------------------------------------------------------+ 
//| Custom indicator initialization function                         | 
//+------------------------------------------------------------------+ 
int OnInit()
{
   IndicatorObjPrefix = "__" + btn_text + "__";
   buttonId = "_" + UniqueButtonID + IndicatorObjPrefix + "_BT_";
   
   // Check if button already exists and get its current state
   bool buttonExists = (ObjectFind(0, buttonId) >= 0);
   bool currentButtonState = false; // Default to OFF
   
   if (buttonExists)
   {
      currentButtonState = (bool)ObjectGetInteger(0, buttonId, OBJPROP_STATE);
      Print("Button exists with state: ", currentButtonState ? "ON" : "OFF");
   }
   else
   {
      createButton(buttonId, btn_text, btn_Width, btn_Height, btn_Font, btn_FontSize, btn_background_color, btn_border_color, btn_text_ON_color);
      ObjectSetInteger(0, buttonId, OBJPROP_YDISTANCE, button_y);
      ObjectSetInteger(0, buttonId, OBJPROP_XDISTANCE, button_x);
      Print("New button created with default state: ON");
   }
    
   IndicatorEnabled = currentButtonState;
   // Initialize indicator regardless of state to ensure proper buffer setup
   init2();
         
   // Set button appearance based on current state
   if (currentButtonState)
   {
      ObjectSetInteger(0, buttonId, OBJPROP_COLOR, btn_text_ON_color);
      ObjectSetString(0, buttonId, OBJPROP_TEXT, btn_text);
      Print("Ichimoku indicator ENABLED");
      PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
      PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_LINE);
      PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_FILLING);                  
      PlotIndexSetInteger(3, PLOT_DRAW_TYPE, DRAW_LINE);
      ChartRedraw();
   }
   else
   {
      ObjectSetInteger(0, buttonId, OBJPROP_COLOR, btn_text_OFF_color);
      ObjectSetString(0, buttonId, OBJPROP_TEXT, btn_text);
      // Hide all plots
      PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_NONE);
      PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_NONE);                  
      PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_NONE);                  
      PlotIndexSetInteger(3, PLOT_DRAW_TYPE, DRAW_NONE);                  
      Print("Ichimoku indicator DISABLED");
   }
   
   ObjectSetInteger(0, buttonId, OBJPROP_STATE, currentButtonState);
   
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Button Creation Function                                         |
//+------------------------------------------------------------------+
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, false);
   ObjectSetInteger(0, buttonID, OBJPROP_CORNER, btn_corner);
   ObjectSetInteger(0, buttonID, OBJPROP_HIDDEN, true);
   ObjectSetInteger(0, buttonID, OBJPROP_XDISTANCE, 9999);
   ObjectSetInteger(0, buttonID, OBJPROP_YDISTANCE, 9999);
   ObjectSetInteger(0, buttonId, OBJPROP_STATE, true);
}

//+------------------------------------------------------------------+
//| OnDeinit                                                         |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // Only delete the button if the indicator is being completely removed
   if(reason == REASON_REMOVE) 
   {
      ObjectDelete(0, buttonId);
   }
}

//+------------------------------------------------------------------+
//| OnChartEvent                                                     |
//+------------------------------------------------------------------+
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;

   static string prevState = "";
   if(id == CHARTEVENT_OBJECT_CLICK && sparam == buttonId)
   {
      bool currentState = ObjectGetInteger(0, buttonId, OBJPROP_STATE);
      string newState = currentState ? "on" : "off";
      
      if(newState == "on")
      {
         ObjectSetInteger(0, buttonId, OBJPROP_COLOR, btn_text_ON_color);
         ObjectSetString (0, buttonId, OBJPROP_TEXT, btn_text);
         IndicatorEnabled = true;
         
         // Reinitialize indicator with new handles
         PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
         PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_LINE);
         PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_FILLING);                  
         PlotIndexSetInteger(3, PLOT_DRAW_TYPE, DRAW_LINE);
//         ChartRedraw();
         Print("Button turned ON - Ichimoku indicator ENABLED");
      }
      else
      {
         ObjectSetInteger(0, buttonId, OBJPROP_COLOR, btn_text_OFF_color);
         ObjectSetString(0, buttonId, OBJPROP_TEXT, btn_text);
         IndicatorEnabled = false;         
         // Hide all plots
         PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_NONE);
         PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_NONE);                  
         PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_NONE);                  
         PlotIndexSetInteger(3, PLOT_DRAW_TYPE, DRAW_NONE);                  
         Print("Button turned OFF - Ichimoku indicator DISABLED");
      }
      
      prevState = newState;
      Print("Button state changed to: ", newState);
   }
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init2()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtTenkanBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ExtKijunBuffer,INDICATOR_DATA);
   SetIndexBuffer(2,ExtSpanABuffer,INDICATOR_DATA);
   SetIndexBuffer(3,ExtSpanBBuffer,INDICATOR_DATA);
   SetIndexBuffer(4,ExtChikouBuffer,INDICATOR_DATA);
//---
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
//--- sets first bar from what index will be drawn
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpTenkan);
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,InpKijun);
   PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,InpSenkou-1);
//--- lines shifts when drawing
   PlotIndexSetInteger(2,PLOT_SHIFT,InpKijun);
   PlotIndexSetInteger(3,PLOT_SHIFT,-InpKijun);
//--- change labels for DataWindow 
   PlotIndexSetString(0,PLOT_LABEL,"Tenkan-sen("+string(InpTenkan)+")");
   PlotIndexSetString(1,PLOT_LABEL,"Kijun-sen("+string(InpKijun)+")");
   PlotIndexSetString(2,PLOT_LABEL,"Senkou Span A;Senkou Span B("+string(InpSenkou)+")");
   return (0);
//--- initialization done
  }
//+------------------------------------------------------------------+
//| get highest value for range                                      |
//+------------------------------------------------------------------+
double Highest(const double&array[],int range,int fromIndex)
  {
   double res=0;
//---
   res=array[fromIndex];
   for(int i=fromIndex;i>fromIndex-range && i>=0;i--)
     {
      if(res<array[i]) res=array[i];
     }
//---
   return(res);
  }
//+------------------------------------------------------------------+
//| get lowest value for range                                       |
//+------------------------------------------------------------------+
double Lowest(const double&array[],int range,int fromIndex)
  {
   double res=0;
//---
   res=array[fromIndex];
   for(int i=fromIndex;i>fromIndex-range && i>=0;i--)
     {
      if(res>array[i]) res=array[i];
     }
//---
   return(res);
  }
//+------------------------------------------------------------------+
//| Ichimoku Kinko Hyo                                               |
//+------------------------------------------------------------------+
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 &TickVolume[],
                const long &Volume[],
                const int &Spread[])
  {
          int limit;
          //---
          if(prev_calculated==0) limit=0;
          else                   limit=prev_calculated-1;
          //---
          for (int i=limit;i<rates_total && !IsStopped();i++)
               {
                ExtChikouBuffer[i]=Close[i];
                //--- tenkan sen
                double high=Highest(High,InpTenkan,i);
                double low=Lowest(Low,InpTenkan,i);
                ExtTenkanBuffer[i]=(high+low)/2.0;
                //--- kijun sen
                high=Highest(High,InpKijun,i);
                low=Lowest(Low,InpKijun,i);
                ExtKijunBuffer[i]=(high+low)/2.0;
                //--- senkou span a
                ExtSpanABuffer[i]=(ExtTenkanBuffer[i]+ExtKijunBuffer[i])/2.0;
                //--- senkou span b
                high=Highest(High,InpSenkou,i);
                low=Lowest(Low,InpSenkou,i);
                ExtSpanBBuffer[i]=(high+low)/2.0;
               }
//--- done
   return(rates_total);
  }
//+------------------------------------------------------------------+
