//+------------------------------------------------------------------+
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      ""

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1  LimeGreen
#property indicator_color2  Red
#property indicator_color3  LimeGreen
#property indicator_color4  Red
#property indicator_width1  1
#property indicator_width2  1
#property indicator_width3  2
#property indicator_width4  2

//
//
//
//
//

extern ENUM_TIMEFRAMES  TimeFrame       = PERIOD_M1;
extern double  TouchTolerance  = 5.0;
extern bool    ShowInfo        = true;
extern bool    ShowTouched     = true;
extern bool    NormalizeValues = false;

//
//
//
//
//

extern string  __              = "alerts";
extern bool    alertsOn        = false;
extern bool    alertsOnCurrent = false;
extern bool    alertsMessage   = true;
extern bool    alertsSound     = false;
extern bool    alertsEmail     = false;

//
//
//
//
//

extern string  ___             = "colors";
extern color   ColorUp         = ForestGreen;
extern color   ColorNeutral    = Gray;
extern color   ColorDown       = OrangeRed;
extern color   ColorLabels     = Gray;

//
//
//
//
//

extern string  ____               = "other";
extern int     DistanceFromBorder = 200;
extern int     WindowCorner       = 1;
extern string  UniqueID           = "PivotLines1";
extern string  T="n";

//
//
//
//
//

double Buffer1[];
double Buffer2[];
double Buffer3[];
double Buffer4[];

//
//
//
//
//

int      window = 0;
int      totalLabels;
string   shortName;
int      maxVals = 7;
double   pivotValues[7];
string   pivotLabels[8] = {"R3","R2","R1","pivot","S1","S2","S3"};
int      timeFrame;
datetime TimeArray[];

//
//
//
//
//

#define arr_alertedTime   0
#define arr_alertedValue  1
#define arr_maCValue      2
#define arr_lastTouched   3
#define arr_lastType      4
#define arr_prevTouched   5
#define arr_prevType      6
double  pivSaves[][7];


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   timeFrame = stringToTimeFrame(TimeFrame);
   SetIndexBuffer(0,Buffer1);
   SetIndexBuffer(1,Buffer2);
   SetIndexBuffer(2,Buffer3);
   SetIndexBuffer(3,Buffer4);
   SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexStyle(2,DRAW_HISTOGRAM);
   SetIndexStyle(3,DRAW_HISTOGRAM);

   //
   //
   //
   //
   //

   ArrayResize(pivSaves,maxVals);
   shortName   = UniqueID+ TimeFrame ;
   totalLabels = 0;

   return(0);
}

//
//
//
//
//

int deinit()
{
   while (totalLabels>0) { ObjectDelete(StringConcatenate(shortName,totalLabels)); totalLabels--;}
   return(0);
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int start()
{
   double   maValue;
   int      counted_bars=IndicatorCounted(),limit,i,m,y;


   if(counted_bars < 0) return(-1);
   if(counted_bars > 0) counted_bars--;
         limit = Bars-counted_bars;

   //
   //
   //
   //
   //

   ArrayCopySeries(TimeArray ,MODE_TIME,NULL,timeFrame);
   for(m=0;m<maxVals;m++)
      {
         pivSaves[m][arr_lastTouched] = EMPTY_VALUE;
         pivSaves[m][arr_lastType]    = EMPTY_VALUE;
      }

   //
   //
   //
   //
   //

                  
   for(i=limit; i>=0; i--)
      {
         checkTime(i,y);
         double LastLow  = iiLow(timeFrame,y);
         double LastHigh = iiHigh(timeFrame,y);
         double P;
                  
         //
         //
         //
         //
         //
         //

         P  = (LastHigh+LastLow+iiClose(timeFrame,y))/3;
         pivotValues[0] = (2*P)+(LastHigh-(2*LastLow));
         pivotValues[1] = P+(LastHigh - LastLow);
         pivotValues[2] = (2*P)-LastLow;
         pivotValues[3] = P;
         pivotValues[4] = (2*P)-LastHigh;
         pivotValues[5] = P-(LastHigh - LastLow);
         pivotValues[6] = (2*P)-((2* LastHigh)-LastLow); 

         //
         //
         //
         //
         //
               
         int inReach = 0;
         for (m=0;m<maxVals;m++)
            {
               maValue = pivotValues[m];
               
               //
               //
               //
               //
               //

                              
               if ((High[i] <= maValue) && (High[i]+TouchTolerance*Point) >= maValue)
                  {
                     inReach += 1; 
                     if (i > 0)
                        {
                           pivSaves[m][arr_prevTouched] = Time[i];
                           pivSaves[m][arr_prevType]    = inReach;
                        }                               
                     else
                        {
                            pivSaves[m][arr_lastTouched] = Time[i];
                            pivSaves[m][arr_lastType]    = inReach;
                        }                               
                  }
               if (( Low[i] >= maValue) && ( Low[i]-TouchTolerance*Point) <= maValue)
                  {
                     inReach -= 1;
                     if (i > 0)
                        {
                           pivSaves[m][arr_prevTouched] = Time[i];
                           pivSaves[m][arr_prevType]    = inReach;
                        }                               
                     else
                        {
                            pivSaves[m][arr_lastTouched] = Time[i];
                            pivSaves[m][arr_lastType]    = inReach;
                        }                               
                  }

               //
               //
               //
               //
               //
                  
               if (i==0) pivSaves[m][arr_maCValue] = maValue;
            }
   
            //
            //
            //
            //
            //
                     
            Buffer1[i] = EMPTY_VALUE;
            Buffer2[i] = EMPTY_VALUE;
            Buffer3[i] = EMPTY_VALUE;
            Buffer4[i] = EMPTY_VALUE;
            if (ShowTouched)
            {
               if (inReach  < 0)
               { 
                     Buffer1[i] = High[i];
                     Buffer2[i] = Low[i];
                     Buffer3[i] = MathMax(Open[i],Close[i]);
                     Buffer4[i] = MathMin(Open[i],Close[i]);
               }
               if (inReach  > 0)
               { 
                     Buffer1[i] = Low[i];
                     Buffer2[i] = High[i];
                     Buffer3[i] = MathMin(Open[i],Close[i]);
                     Buffer4[i] = MathMax(Open[i],Close[i]);
               }
            }               
      }

   //
   //
   //
   //
   //
  
   totalLabels = 0;   
   for(m=0;m<maxVals;m++) checkAlerts(m);
   for(m=0;m<maxVals;m++) DisplayInfo(m);
   return(0);
}



  
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

void DisplayInfo(int i)
{
   double pDistance = NormalizeDouble(Close[0]-pivSaves[i][arr_maCValue],Digits);
   int    yDistance = i*14+DistanceFromBorder;
   int    tDistance;
   color  tmpColor;


   if (!ShowInfo) return;
   setObject(next(),pivotLabels[i],10,yDistance,ColorLabels);

   //
   //
   //
   //
   //
   
   if (pDistance <0)  tmpColor = ColorDown;
   if (pDistance==0)  tmpColor = ColorNeutral;
   if (pDistance >0)  tmpColor = ColorUp;
         setObject(next(),T,55,yDistance,tmpColor,"Wingdings",10);
         setObject(next(),DoubleToStr(MathAbs(pDistance/Point),0),75,yDistance,tmpColor);
         
   //
   //
   //
   //
   //

   if (pivSaves[i][arr_lastTouched]==EMPTY_VALUE)
         tDistance = iBarShift(NULL,0,pivSaves[i][arr_prevTouched]);
   else  tDistance = iBarShift(NULL,0,pivSaves[i][arr_lastTouched]);
   setObject(next(),DoubleToStr(tDistance,0),100,yDistance,ColorLabels);
}

//
//
//
//
//

string next() { totalLabels++; return(totalLabels); }  
void setObject(string name,string text,int x,int y,color theColor, string font = "Arial",int size=9,int angle=0)
{
   string labelName = StringConcatenate(shortName,name);

   //
   //
   //
   //
   //
      
      if (ObjectFind(labelName) == -1)
          {
             ObjectCreate(labelName,OBJ_LABEL,window,0,0);
             ObjectSet(labelName,OBJPROP_CORNER,WindowCorner);
             if (angle != 0)
                  ObjectSet(labelName,OBJPROP_ANGLE,angle);
          }               
       ObjectSet(labelName,OBJPROP_XDISTANCE,x);
       ObjectSet(labelName,OBJPROP_YDISTANCE,y);
       ObjectSetText(labelName,text,size,font,theColor);
}


//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
//
//
//
//
//

void checkTime(int i,int& y) { y = iBarShift(NULL,timeFrame,Time[i]);}
double iiLow(int tf,int y)   { return(iLow(NULL,tf,y+1));  }
double iiHigh(int tf,int y)  { return(iHigh(NULL,tf,y+1)); }
double iiClose(int tf,int y) { return(iClose(NULL,tf,y+1));}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

void checkAlerts(int element)
{
   if(alertsOnCurrent)
      {
         if(iBarShift(NULL,0,pivSaves[element][arr_lastTouched]) == 0)
         {
                        checkAlert(0,element);
         }                        
      }
   else                     
      {
         if(iBarShift(NULL,0,pivSaves[element][arr_prevTouched]) == 1)
         {
                        checkAlert(1,element);
         }                        
      }
}

//
//
//
//
//

void checkAlert(int i, int element)
{
   if (alertsOn) {
   if (pivSaves[element][arr_alertedTime] != Time[0]) {
       pivSaves[element][arr_alertedTime]  = Time[0];
       doAlert(pivotLabels[element]);
   }}
}

//
//
//
//
//

void doAlert(string forWhat)
{
   string message;
   
   message =  StringConcatenate(Symbol()," - ",TimeFrameToString(Period())," chart, ",forWhat," touched at ",TimeToStr(TimeLocal(),TIME_SECONDS));
   
    
     if (alertsMessage) Alert(message);
     if (alertsSound)   PlaySound("alert2.wav");
     if (alertsEmail)   SendMail(StringConcatenate(Symbol()," Pivot touched"),message);
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

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);
}
int stringToTimeFrame(string tfs)
{
   int tf=0;
       tfs = StringUpperCase(tfs);
         if (tfs=="M1" || tfs=="1")     tf=PERIOD_M1;
         if (tfs=="M5" || tfs=="5")     tf=PERIOD_M5;
         if (tfs=="M15"|| tfs=="15")    tf=PERIOD_M15;
         if (tfs=="M30"|| tfs=="30")    tf=PERIOD_M30;
         if (tfs=="H1" || tfs=="60")    tf=PERIOD_H1;
         if (tfs=="H4" || tfs=="240")   tf=PERIOD_H4;
         if (tfs=="D1" || tfs=="1440")  tf=PERIOD_D1;
         if (tfs=="W1" || tfs=="10080") tf=PERIOD_W1;
         if (tfs=="MN" || tfs=="43200") tf=PERIOD_MN1;
  return(tf);
}

//
//
//
//
//

string StringUpperCase(string str)
{
   string   s = str;
   int      lenght = StringLen(str) - 1;
   int      tchar;
   
   while(lenght >= 0)
      {
         tchar = StringGetChar(s, lenght);
         
         //
         //
         //
         //
         //
         
         if((tchar > 96 && tchar < 123) || (tchar > 223 && tchar < 256))
                  s = StringSetChar(s, lenght, tchar - 32);
         else 
              if(tchar > -33 && tchar < 0)
                  s = StringSetChar(s, lenght, tchar + 224);
         lenght--;
   }
   return(s);
}