//------------------------------------------------------------------
#property copyright "www.forex-station.com"
#property link      "www.forex-station.com"
//------------------------------------------------------------------
#property indicator_chart_window
#property indicator_buffers 8
#property indicator_color5  clrMediumSeaGreen
#property indicator_color6  clrMediumSeaGreen
#property indicator_color7  C'225,172,183'
#property indicator_color8  C'225,172,183'

#property indicator_width5  1
#property indicator_width6  1
#property indicator_width7  1
#property indicator_width8  1

#property indicator_style5  STYLE_DOT
#property indicator_style6  STYLE_DOT
#property indicator_style7  STYLE_DOT
#property indicator_style8  STYLE_DOT
#property strict

//
//
//
//
//

extern ENUM_TIMEFRAMES   TimeFrame   = PERIOD_CURRENT;  // Time frame
extern int                SLength              = 40;    // Slow period
extern double             SDeviation           = 1.0;    // Slow deviation
extern int                FLength              = 20;    // Fast period
extern double             FDeviation           = 1.0;    // Fast deviation
extern ENUM_APPLIED_PRICE Price               = PRICE_CLOSE; 
extern bool                showRIBBON    =   true;  // Show ribbon?
input int              RibbonWidth      =   1;                // Width of ribbon
extern color           ribbonUP                = clrMediumSeaGreen;      // Bullish ribbon  color
extern color           ribbonDN                = C'225,172,183';;      // Bearish ribbon  color  
extern int                btn_Subwindow = 0;
extern ENUM_BASE_CORNER   btn_corner            = CORNER_LEFT_UPPER; 
extern string             btn_text              = "BB";
extern string             btn_Font              = "Arial";
extern int                btn_FontSize          = 8;                        
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              = 900;                                   
extern int                button_y              = 20;                                   
//extern int                btn_Width             = 60;                                
//extern int                btn_Height            = 20;                               
input bool               Interpolate = true;            // Interpolate in multi time frame mode on/off?
bool show_data = true;
bool recalc    = true;  
string IndicatorName, IndicatorObjPrefix,buttonId;  


double ssmh1[],ssmh2[],ssml1[],ssml2[],slope1[],slope2[],U1[],L1[],U2[],L2[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,SLength,SDeviation,FLength,FDeviation,Price,showRIBBON,RibbonWidth,ribbonUP,ribbonDN,btn_Subwindow,btn_corner,btn_text,btn_Font,btn_FontSize,btn_text_ON_color,btn_text_OFF_color,button_x,button_y,_buff,_ind)

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
string GenerateIndicatorName(const string target) 
{
   string name = target;
   int try = 2;
   while (WindowFind(name) != -1)
   {
      name = target + " #" + IntegerToString(try++);
   }
   return name;
}
//
//
//
//

int OnInit()
{
 IndicatorName = GenerateIndicatorName(btn_text);
   IndicatorObjPrefix = "__" + IndicatorName + "__";
   IndicatorShortName(IndicatorName);
   IndicatorDigits(Digits);
   
   double val;
   if (GlobalVariableGet(IndicatorName + "_visibility", val))
      show_data = val != 0;
      
   IndicatorBuffers(11);
   SetIndexBuffer(0,ssmh1); SetIndexStyle(0,showRIBBON  ? DRAW_HISTOGRAM :  DRAW_NONE,0, RibbonWidth,ribbonDN);
   SetIndexBuffer(1,ssmh2); SetIndexStyle(1,showRIBBON  ? DRAW_HISTOGRAM :  DRAW_NONE,0, RibbonWidth,ribbonUP);
   SetIndexBuffer(2,ssml1); SetIndexStyle(2,showRIBBON  ? DRAW_HISTOGRAM :  DRAW_NONE,0, RibbonWidth,ribbonDN);
   SetIndexBuffer(3,ssml2); SetIndexStyle(3,showRIBBON  ? DRAW_HISTOGRAM :  DRAW_NONE,0, RibbonWidth,ribbonUP);
   
   SetIndexBuffer(4,U1,   INDICATOR_DATA); SetIndexStyle(4,DRAW_LINE);
   SetIndexBuffer(5,L1, INDICATOR_DATA); SetIndexStyle(5,DRAW_LINE);
   SetIndexBuffer(6,U2, INDICATOR_DATA); SetIndexStyle(6,DRAW_LINE);
   SetIndexBuffer(7,L2, INDICATOR_DATA); SetIndexStyle(7,DRAW_LINE); 
   
   SetIndexBuffer(8,slope1);
   SetIndexBuffer(9,slope2);
   
   SetIndexBuffer(10,count);
   
   indicatorFileName = WindowExpertName();
   TimeFrame         = fmax(TimeFrame,_Period); 
   
  
   
   IndicatorSetString(INDICATOR_SHORTNAME,timeFrameToString(TimeFrame)+"  ("+(string)FLength+")");
   
  
    ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, 1);
   buttonId = IndicatorObjPrefix + (btn_text);
   createButton(buttonId, btn_text, 60, 20, btn_Font, btn_FontSize, clrDimGray, clrBlack, btn_text_ON_color);
   ObjectSetInteger(0, buttonId, OBJPROP_YDISTANCE, button_y);
   ObjectSetInteger(0, buttonId, OBJPROP_XDISTANCE, button_x);
   
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)

{ 
ObjectsDeleteAll(ChartID(), IndicatorObjPrefix);

  }
//
//
void createButton(string buttonID,string buttonText,int width,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,width);
      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);
}
//+------------------------------------------------------------------+
void handleButtonClicks()
{
   if (ObjectGetInteger(0, buttonId, OBJPROP_STATE))
   {
      ObjectSetInteger(0, buttonId, OBJPROP_STATE, false);
      show_data = !show_data;
      GlobalVariableSet(IndicatorName + "_visibility", show_data ? 1.0 : 0.0);
      recalc = true;
     // start();
   }
}
//+------------------------------------------------------------------+
void OnChartEvent(const int id, 
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   
  
   
   
   handleButtonClicks();
   if (id==CHARTEVENT_OBJECT_CLICK && ObjectGet(sparam,OBJPROP_TYPE)==OBJ_BUTTON)
   
   
   SetIndexStyle(0,showRIBBON  ? DRAW_HISTOGRAM :  DRAW_NONE,0, RibbonWidth,ribbonDN);
   SetIndexStyle(1,showRIBBON  ? DRAW_HISTOGRAM :  DRAW_NONE,0, RibbonWidth,ribbonUP);
   SetIndexStyle(2,showRIBBON  ? DRAW_HISTOGRAM :  DRAW_NONE,0, RibbonWidth,ribbonDN);
   SetIndexStyle(3,showRIBBON  ? DRAW_HISTOGRAM :  DRAW_NONE,0, RibbonWidth,ribbonUP);
   
   SetIndexStyle(4,DRAW_LINE);
   SetIndexStyle(5,DRAW_LINE);
   SetIndexStyle(6,DRAW_LINE);
   SetIndexStyle(7,DRAW_LINE); 
   
   if (show_data)
   {
   ObjectSetInteger(ChartID(),buttonId,OBJPROP_COLOR,btn_text_ON_color);
     
      }
      else
      {
        ObjectSetInteger(ChartID(),buttonId,OBJPROP_COLOR,btn_text_OFF_color);
        for (int banzai=0; banzai<indicator_buffers; banzai++)
            SetIndexStyle(banzai,DRAW_NONE);
      } 
   
         
   
}
//

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,limit=fmin(rates_total-prev_calculated+1,rates_total-1); count[0] = limit;
  
      if (TimeFrame!=_Period)
      {
         limit = (int)fmax(limit,fmin(rates_total-1,_mtfCall(10,0)*TimeFrame/_Period));
       
         for (i=limit;i>=0 && !_StopFlag; i--)
         {
            int y = iBarShift(NULL,TimeFrame,time[i]);
               ssmh1[i]   = _mtfCall(0,y);
               ssmh2[i]   = _mtfCall(1,y);
               ssml1[i]   = _mtfCall(2,y);
               ssml2[i]   = _mtfCall(3,y);
               
               U1[i]   = _mtfCall(4,y);
               L1[i] = _mtfCall(5,y);
               U2[i] = _mtfCall(6,y);
               L2[i] = _mtfCall(7,y);
               slope1[i] = _mtfCall(8,y);
               slope2[i] = _mtfCall(9,y);      
               //
               //
               //
                if (slope1[i] == 1)
            {
               ssmh1[i] = U1[i];
               ssmh2[i] = U2[i];
            }
            else
            {
               ssmh2[i] = U2[i];
               ssmh1[i] = U1[i];
            }               
            if (slope2[i] == 1)
            {
               ssml1[i] = L1[i];
               ssml2[i] = L2[i];
            }
            else
            {
               ssml2[i] = L2[i];
               ssml1[i] = L1[i];
            }  
            
                  
               if (!Interpolate || (i>0 && y==iBarShift(NULL,TimeFrame,time[i-1]))) continue;
                  
               //
               //
               //
                  
               #define _interpolate(buff) buff[i+k] = buff[i]+(buff[i+n]-buff[i])*k/n
               int n,k; datetime dtime = iTime(NULL,TimeFrame,y);
                  for(n = 1; (i+n)<rates_total && time[i+n] >= dtime; n++) continue;	
                  for(k = 1; k<n && (i+n)<rates_total && (i+k)<rates_total; k++) 
                  {
                     _interpolate(U1); 
                     _interpolate(L1);
                     _interpolate(U2);  
                     _interpolate(L2); 
                     
                      if (slope1[i] == 1)
            {
               ssmh1[i+k] = U1[i+k];
               ssmh2[i+k] = U2[i+k];
            }
            else
            {
               ssmh2[i+k] = U2[i+k];
               ssmh1[i+k] = U1[i+k];
            }               
            if (slope2[i] == 1)
            {
               ssml1[i+k] = L1[i+k];
               ssml2[i+k] = L2[i+k];
            }
            else
            {
               ssml2[i+k] = L2[i+k];
               ssml1[i+k] = L1[i+k];
            }  
            
                  }                    
         } 
        
   return(rates_total);
   } 
      
   //
   //
   //
          
  
   for(i=limit;i>=0; i--)
   {  
      U1[i]    = iBands(NULL,0,SLength,SDeviation,0,Price,MODE_UPPER,i); // 1 
      L1[i]    = iBands(NULL,0,SLength,SDeviation,0,Price,MODE_LOWER,i); // 2 
      
      U2[i]    = iBands(NULL,0,FLength,FDeviation,0,Price,MODE_UPPER,i); // 1 
      L2[i]    = iBands(NULL,0,FLength,FDeviation,0,Price,MODE_LOWER,i); // 2
      
       slope1[i] = (i<rates_total-1) ? (U2[i]>U1[i]) ? 1 : (U2[i]<U1[i]) ? -1  : slope1[i+1]  : 0; 
       slope2[i] = (i<rates_total-1) ? (L2[i]>L1[i]) ? 1 : (L2[i]<L1[i]) ? -1  : slope2[i+1]  : 0; 
      
     if (slope1[i] == 1)
            {
               ssmh1[i] = U1[i];
               ssmh2[i] = U2[i];
            }
            else
            {
               ssmh2[i] = U2[i];
               ssmh1[i] = U1[i];
            }               
            if (slope2[i] == 1)
            {
               ssml1[i] = L1[i];
               ssml2[i] = L2[i];
            }
            else
            {
               ssml2[i] = L2[i];
               ssml1[i] = L1[i];
            }  
   }
return(rates_total);
}

//------------------------------------------------------------------
//                                                                  
//------------------------------------------------------------------
//
//
//
//
//


//-------------------------------------------------------------------
//
//-------------------------------------------------------------------
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}
 

