//------------------------------------------------------------------
#property copyright "mladen"
#property link      "mladenfx@gmail.com"
//------------------------------------------------------------------

#property indicator_chart_window
#property indicator_buffers 9
#property indicator_color1  clrLimeGreen
#property indicator_color2  clrOrangeRed
#property indicator_color3  clrOrangeRed

#property indicator_color4  clrLimeGreen
#property indicator_color5  clrOrangeRed
#property indicator_color6  clrOrangeRed

#property indicator_color7  clrLimeGreen
#property indicator_color8  clrOrangeRed
#property indicator_color9  clrOrangeRed


#property strict

//
//
//
//
//
enum enTimeFrames
{
   tf_cu  = PERIOD_CURRENT, // Current time frame
   tf_m1  = PERIOD_M1,      // 1 minute
   tf_m5  = PERIOD_M5,      // 5 minutes
   tf_m15 = PERIOD_M15,     // 15 minutes
   tf_m30 = PERIOD_M30,     // 30 minutes
   tf_h1  = PERIOD_H1,      // 1 hour
   tf_h4  = PERIOD_H4,      // 4 hours
   tf_d1  = PERIOD_D1,      // Daily
   tf_w1  = PERIOD_W1,      // Weekly
   tf_mn1 = PERIOD_MN1,     // Monthly
   tf_n1  = -1,             // First higher time frame
   tf_n2  = -2,             // Second higher time frame
   tf_n3  = -3              // Third higher time frame
};

extern enTimeFrames       TimeFrame   = tf_cu;           // Time frame
extern int                JawsPeriod  = 13;              // Jaws period
extern int                JawsShift   = 8;               // Jaws shift
extern int                TeethPeriod = 8;               // Teeth period
extern int                TeethShift  = 5;               // Teeth shift
extern int                LipsPeriod  = 5;               // Lips period
extern int                LipsShift   = 3;               // Lips shift
extern ENUM_MA_METHOD     MaMode      = MODE_SMMA;       // Average method
extern ENUM_APPLIED_PRICE MaPrice     = PRICE_MEDIAN;    // Price
extern int                LineWidth   =   2;             // Lines   width
extern bool               Interpolate = true;            // Interpolate in mtf mode?


extern int                btn_Subwindow = 0;
extern ENUM_BASE_CORNER   btn_corner            = CORNER_LEFT_UPPER; 
extern string             btn_text              = "aligator";
extern string             btn_Font              = "Arial";
extern int                btn_FontSize          = 10;                            
extern color              btn_text_ON_color     = clrLime;
extern color              btn_text_OFF_color    = clrRed;
extern string             btn_pressed           = "aligator OFF";            
extern string             btn_unpressed         = "aligator ON";
extern color              btn_background_color  = clrDimGray;
extern color              btn_border_color      = clrBlack;
extern int                button_x              = 850;                                 
extern int                button_y              = 0;                                   
extern int                btn_Width             = 90;                                 
extern int                btn_Height            = 20;                                
extern string             soundBT               = "tick.wav";  


bool                      show_data             = true;
string IndicatorName, IndicatorObjPrefix ,buttonId ;

//
//
//
//
//

double BlueBuffer[],maUa[],maUb[],RedBuffer[],maUa1[],maUb1[],LimeBuffer[],maUa2[],maUb2[],state[],state1[],state2[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,tf_cu,JawsPeriod,0,TeethPeriod,0,LipsPeriod,0,MaMode,MaPrice,LineWidth,Interpolate,btn_Subwindow,btn_corner,btn_text,btn_Font,btn_FontSize,btn_text_ON_color,btn_text_OFF_color,btn_pressed,btn_unpressed,btn_background_color,btn_border_color,button_x,button_y,btn_Width,btn_Height,soundBT,_buff,_ind)

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
string GenerateIndicatorName(const string target)
{
   string name = target;
   int try = 2;
   while (WindowFind(name) != -1)
   {
      name = target + " #" + IntegerToString(try++);
   }
   return name;
}


int init()
{
   for (int i=0; i<indicator_buffers; i++) SetIndexStyle(i,DRAW_LINE);
   IndicatorBuffers(13);
   SetIndexBuffer(0,BlueBuffer);    SetIndexStyle(0,DRAW_LINE,EMPTY,LineWidth);   SetIndexLabel(0,"Gator Jaws");
   SetIndexBuffer(1,maUa);          SetIndexStyle(1,DRAW_LINE,EMPTY,LineWidth);
   SetIndexBuffer(2,maUb);          SetIndexStyle(2,DRAW_LINE,EMPTY,LineWidth);
   SetIndexBuffer(3,RedBuffer);     SetIndexStyle(3,DRAW_LINE,EMPTY,LineWidth);   SetIndexLabel(3,"Gator Teeth");
   SetIndexBuffer(4,maUa1);         SetIndexStyle(4,DRAW_LINE,EMPTY,LineWidth);
   SetIndexBuffer(5,maUb1);         SetIndexStyle(5,DRAW_LINE,EMPTY,LineWidth);
   SetIndexBuffer(6,LimeBuffer);    SetIndexStyle(6,DRAW_LINE,EMPTY,LineWidth);   SetIndexLabel(6,"Gator Lips");
   SetIndexBuffer(7,maUa2);         SetIndexStyle(7,DRAW_LINE,EMPTY,LineWidth);
   SetIndexBuffer(8,maUb2);         SetIndexStyle(8,DRAW_LINE,EMPTY,LineWidth);
   SetIndexBuffer(9,state);
   SetIndexBuffer(10,state1);
   SetIndexBuffer(11,state2);
   SetIndexBuffer(12,count);
  
   
      //
      //
      //
      //
      //
     
         indicatorFileName = WindowExpertName();
         TimeFrame         = (enTimeFrames)timeFrameValue(TimeFrame);
         SetIndexShift(0,JawsShift  * TimeFrame/_Period); 
         SetIndexShift(1,JawsShift  * TimeFrame/_Period); 
         SetIndexShift(2,JawsShift  * TimeFrame/_Period);  
         SetIndexShift(3,TeethShift * TimeFrame/_Period);
         SetIndexShift(4,TeethShift * TimeFrame/_Period);
         SetIndexShift(5,TeethShift * TimeFrame/_Period);  
         SetIndexShift(6,LipsShift  * TimeFrame/_Period); 
         SetIndexShift(7,LipsShift  * TimeFrame/_Period); 
         SetIndexShift(8,LipsShift  * TimeFrame/_Period);  
   IndicatorShortName(timeFrameToString(TimeFrame)+"   Alligator");
   
    IndicatorName = GenerateIndicatorName(btn_text);
   IndicatorObjPrefix = "__" + IndicatorName + "__";
   IndicatorShortName(WindowExpertName());
   IndicatorDigits(Digits);
      double val;
   if (GlobalVariableGet(IndicatorName + "_visibility", val))
   show_data = val != 0;

   ChartSetInteger(ChartID(), CHART_EVENT_MOUSE_MOVE, 1);
   buttonId = IndicatorObjPrefix+btn_text;
   createButton(buttonId, btn_text, btn_Width, btn_Height, btn_Font, btn_FontSize, btn_background_color, btn_border_color, btn_text_ON_color);
   ObjectSetInteger(ChartID(), buttonId, OBJPROP_YDISTANCE, button_y);
   ObjectSetInteger(ChartID(), buttonId, OBJPROP_XDISTANCE, button_x);
   
   
   return(0);
}

void createButton(string buttonID,string buttonText,int width,int height,string font,int fontSize,color bgColor,color borderColor,color txtColor)
{
      ObjectDelete    (ChartID(),buttonID);
      ObjectCreate (ChartID(),buttonID,OBJ_BUTTON,btn_Subwindow,0,0);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_COLOR,txtColor);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_BGCOLOR,bgColor);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_BORDER_COLOR,borderColor);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_XSIZE,width);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_YSIZE,height);
      ObjectSetString (ChartID(),buttonID,OBJPROP_FONT,font);
      ObjectSetString (ChartID(),buttonID,OBJPROP_TEXT,buttonText);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_FONTSIZE,fontSize);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_SELECTABLE,0);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_CORNER,btn_corner);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_HIDDEN,1);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_XDISTANCE,9999);
      ObjectSetInteger(ChartID(),buttonID,OBJPROP_YDISTANCE,9999);
}


int deinit()
 {
 
  ObjectsDeleteAll(0,"aligator");
   ObjectsDeleteAll(ChartID(), IndicatorObjPrefix);
   
  return(0); 
  }     

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
bool recalc = true;
 void handleButtonClicks()
{
   if (ObjectGetInteger(ChartID(), buttonId, OBJPROP_STATE))
   {
      ObjectSetInteger(ChartID(), 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)
   {
   if (soundBT!="") PlaySound(soundBT);     
   }
}
//
//

int start()
{
 handleButtonClicks();
   recalc = false;
   
   start2();
    SetIndexStyle(0,DRAW_LINE,EMPTY,LineWidth);  
    SetIndexStyle(1,DRAW_LINE,EMPTY,LineWidth);
    SetIndexStyle(2,DRAW_LINE,EMPTY,LineWidth);
    SetIndexStyle(3,DRAW_LINE,EMPTY,LineWidth);   
    SetIndexStyle(4,DRAW_LINE,EMPTY,LineWidth);
    SetIndexStyle(5,DRAW_LINE,EMPTY,LineWidth);
    SetIndexStyle(6,DRAW_LINE,EMPTY,LineWidth);   
    SetIndexStyle(7,DRAW_LINE,EMPTY,LineWidth);
    SetIndexStyle(8,DRAW_LINE,EMPTY,LineWidth);
   
   if (show_data)
      {
      ObjectSetInteger(ChartID(),buttonId,OBJPROP_COLOR,btn_text_ON_color);
      ObjectSetString(ChartID(),buttonId,OBJPROP_TEXT,btn_unpressed);
      }
      else
      {
      ObjectSetInteger(ChartID(),buttonId,OBJPROP_COLOR,btn_text_OFF_color);
      ObjectSetString(ChartID(),buttonId,OBJPROP_TEXT,btn_pressed);
        SetIndexStyle(0,DRAW_NONE);
        SetIndexStyle(1,DRAW_NONE);
        SetIndexStyle(2,DRAW_NONE);
        SetIndexStyle(3,DRAW_NONE);
        SetIndexStyle(4,DRAW_NONE);
        SetIndexStyle(5,DRAW_NONE);
        SetIndexStyle(6,DRAW_NONE);
        SetIndexStyle(7,DRAW_NONE);
        SetIndexStyle(8,DRAW_NONE);
       
       
      
   
      //template code     
      }
       return(0);
      }
      
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int start2()
{
   int counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
         int limit = fmin(Bars-counted_bars,Bars-1); count[0]=limit;
         if (TimeFrame!=_Period)
         {
            limit = (int)fmax(limit,fmin(Bars-1,_mtfCall(12,0)*TimeFrame/_Period));
             if (state[limit]== -1) CleanPoint(limit,maUa,maUb);
             if (state1[limit]== -1) CleanPoint(limit,maUa1,maUb1);
             if (state2[limit]== -1) CleanPoint(limit,maUa2,maUb2);
            for (int i=limit; i>=0; i--)
            {   
               int y = iBarShift(NULL,TimeFrame,Time[i]);
                  BlueBuffer[i] = _mtfCall(0,y);
                  RedBuffer[i]  = _mtfCall(3,y);
                  LimeBuffer[i] = _mtfCall(6,y);
                  
                  maUa[i] = maUb[i]    = EMPTY_VALUE;
                  maUa1[i] = maUb1[i]  = EMPTY_VALUE;
                  maUa2[i] = maUb2[i]  = EMPTY_VALUE;
                   
                  state[i]  = _mtfCall(9,y);
                  state1[i] = _mtfCall(10,y);
                  state2[i] = _mtfCall(11,y);
                  
                  //
                  //
                  //
                  //
                  //
                  
                  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 time = iTime(NULL,TimeFrame,y);
                        for(n = 1; (i+n)<Bars && Time[i+n] >= time; n++) continue;	
                        for(k = 1; k<n && (i+n)<Bars && (i+k)<Bars; k++) 
                        {
                           _interpolate(BlueBuffer);
                           _interpolate(RedBuffer);
                           _interpolate(LimeBuffer);
                        }                        
            }
             for(int i=limit;i>=0; i--)
         {      
            if (state[i]  == -1)  PlotPoint(i,maUa,maUb,BlueBuffer);
            if (state1[i] == -1)  PlotPoint(i,maUa1,maUb1,RedBuffer); 
            if (state2[i] == -1)  PlotPoint(i,maUa2,maUb2,LimeBuffer); 
            
            
               
                  
               
         }
            return(0);
         }       

   //
   //
   //
   //
   //
   if (state[limit]== -1) CleanPoint(limit,maUa,maUb);
   if (state1[limit]== -1) CleanPoint(limit,maUa1,maUb1);
   if (state2[limit]== -1) CleanPoint(limit,maUa2,maUb2);
   for (int i = limit; i >= 0 ; i--)
   {
      BlueBuffer[i] = iMA(NULL,0,JawsPeriod, 0,MaMode,MaPrice,i);
      RedBuffer[i]  = iMA(NULL,0,TeethPeriod,0,MaMode,MaPrice,i);
      LimeBuffer[i] = iMA(NULL,0,LipsPeriod, 0,MaMode,MaPrice,i);
      
      state[i] = (i<Bars-1) ?  (BlueBuffer[i]>BlueBuffer[i+1]) ? 1 : (BlueBuffer[i]<BlueBuffer[i+1]) ? -1 :  state[i+1]   : 0;
      state1[i] = (i<Bars-1) ? (RedBuffer[i]>RedBuffer[i+1])   ? 1 : (RedBuffer[i]<RedBuffer[i+1])   ? -1 :  state1[i+1]  : 0;
      state2[i] = (i<Bars-1) ? (LimeBuffer[i]>LimeBuffer[i+1]) ? 1 : (LimeBuffer[i]<LimeBuffer[i+1]) ? -1 :  state2[i+1]  : 0;
      
      maUa[i] = maUb[i]    = EMPTY_VALUE;
      maUa1[i] = maUb1[i]  = EMPTY_VALUE;
      maUa2[i] = maUb2[i]  = EMPTY_VALUE;
                  
                  
      if (state[i]  == -1)  PlotPoint(i,maUa,maUb,BlueBuffer);
      if (state1[i] == -1)  PlotPoint(i,maUa1,maUb1,RedBuffer); 
      if (state2[i] == -1)  PlotPoint(i,maUa2,maUb2,LimeBuffer);     
   }
   return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
void CleanPoint(int i,double& first[],double& second[])
{
   if (i>=Bars-3) return;
   if ((second[i]  != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE))
        second[i+1] = EMPTY_VALUE;
   else
      if ((first[i] != EMPTY_VALUE) && (first[i+1] != EMPTY_VALUE) && (first[i+2] == EMPTY_VALUE))
          first[i+1] = EMPTY_VALUE;
}

void PlotPoint(int i,double& first[],double& second[],double& from[])
{
   if (i>=Bars-2) return;
   if (first[i+1] == EMPTY_VALUE)
      if (first[i+2] == EMPTY_VALUE) 
            { first[i]  = from[i]; first[i+1]  = from[i+1]; second[i] = EMPTY_VALUE; }
      else  { second[i] = from[i]; second[i+1] = from[i+1]; first[i]  = EMPTY_VALUE; }
   else     { first[i]  = from[i];                          second[i] = EMPTY_VALUE; }
}
//
//
//

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("");
}
int timeFrameValue(int _tf)
{
   int add  = (_tf>=0) ? 0 : MathAbs(_tf);
   if (add != 0) _tf = _Period;
   int size = ArraySize(iTfTable); 
      int i =0; for (;i<size; i++) if (iTfTable[i]==_tf) break;
                                   if (i==size) return(_Period);
                                                return(iTfTable[(int)MathMin(i+add,size-1)]);
}