//------------------------------------------------------------------
#property copyright " "
#property link      " "
//------------------------------------------------------------------

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1  clrMediumSeaGreen
#property indicator_color2  clrMediumSeaGreen
#property indicator_color3  clrMediumSeaGreen

//
//
//
//
//

extern int    TMALength       = 128;
extern int    HalfShift       = 64;
extern int    Price           = PRICE_CLOSE;
extern double Deviation       = 0.15;
extern int    SlopePeriod     = 5;
extern int    Calcbars        = 0;

       
extern string unipueID        ="TMAch2";
extern int    PositionX       = 20;
extern int    PositionY       = 115;
extern int    Corner          = 2;
extern bool   ButtonState     = false; //Default state

//-------------------------------------------------------
string indicatorname ="TMA" +unipueID;
string BTNid         ="TMA" +unipueID;


string prefix        ="TMA" +unipueID;


//-------------------------------------------------------

bool GetButtonState(string whichbutton)
{
      bool selected = ObjectGetInteger(ChartID(),whichbutton,OBJPROP_STATE);
      if (selected)
           { return (true); } 
      else { return (false);}
}

//
//
//
//
//
string pfix = "__" + prefix + "__"; 

double up[],dn[],cent[];
double UpEnv[];
double DnEnv[];
double tmBuffer[];
double arrU[],arrD[];
double arrC[];
double trend[];

//
//
//
//                    
//

string indicatorFileName;
bool   calculateValue;
bool   returnBars;
int    timeFrame;

int w;
int Fvb;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//

int init()
{

   string caption ="MED";
   
   
  if (ObjectFind(BTNid)!=0)
  {
      ObjectCreate(ChartID(),BTNid,OBJ_BUTTON,0,0,0);
         ObjectSetString(ChartID(),BTNid,OBJPROP_TEXT,caption);
         ObjectSetInteger(ChartID(),BTNid,OBJPROP_FONTSIZE,10);
         ObjectSetInteger(ChartID(),BTNid,OBJPROP_CORNER,Corner);
         ObjectSetInteger(ChartID(),BTNid,OBJPROP_COLOR,clrWhite);
         ObjectSetInteger(ChartID(),BTNid,OBJPROP_BGCOLOR,clrDimGray);
         ObjectSetInteger(ChartID(),BTNid,OBJPROP_YDISTANCE,PositionY);
         ObjectSetInteger(ChartID(),BTNid,OBJPROP_XDISTANCE,PositionX);
         ObjectSetInteger(ChartID(),BTNid,OBJPROP_XSIZE,100);
         ObjectSetInteger(ChartID(),BTNid,OBJPROP_YSIZE,20);
         ObjectSetInteger(ChartID(),BTNid,OBJPROP_SELECTABLE,false);
         ObjectSetInteger(ChartID(),BTNid,OBJPROP_HIDDEN,true);
         ObjectSetInteger(ChartID(),BTNid,OBJPROP_STATE,false);
         
  }            
   
   TMALength=MathMax(TMALength,1);


   IndicatorBuffers(7);
   SetIndexBuffer(0,UpEnv);  SetIndexDrawBegin(0,TMALength); //SetIndexShift(0,HalfShift);
   SetIndexBuffer(1,DnEnv);  SetIndexDrawBegin(1,TMALength); //SetIndexShift(1,HalfShift);
   SetIndexBuffer(2,tmBuffer);                               //SetIndexShift(2,HalfShift);
   SetIndexBuffer(3,up);
   SetIndexBuffer(4,dn);
   SetIndexBuffer(5,cent);
   SetIndexBuffer(6,trend);

   
   
      indicatorFileName = WindowExpertName();

      SetIndexShift(0,-1 *HalfShift ); 
      SetIndexShift(1,-1 *HalfShift ); 
      SetIndexShift(2,-1 *HalfShift ); 
      
      
      
      //
      //
      //
      //
      //
        
   
   IndicatorShortName(timeFrameToString(timeFrame)+"  Tma centered env ("+TMALength+") with Channel");
   return(0);
}



int deinit() {

    ObjectsDeleteAll(ChartID(), pfix);
    ObjectsDeleteAll(0,indicatorname);
    ObjectsDeleteAll(0,BTNid);
    
    
    return(0); 
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)
{


   if (id==CHARTEVENT_OBJECT_CLICK && sparam==BTNid)
   {
      bool newState = GetButtonState(BTNid);
            if (newState==true)
              { 
                  SetIndexStyle(0,DRAW_LINE); 
                  SetIndexStyle(1,DRAW_LINE); 
                  SetIndexStyle(2,DRAW_LINE); 
                  Fvb = MathMax(0, WindowFirstVisibleBar() - WindowBarsPerChart());
                  begin();                 
                  
                  
              }
              else
              {  

                  ObjectsDeleteAll(ChartID(), pfix);
                  SetIndexStyle(0,DRAW_NONE); 
                  SetIndexStyle(1,DRAW_NONE); 
                  SetIndexStyle(2,DRAW_NONE); 
                  
              }
         

      
      //ObjectSetInteger(0, BTNid, OBJPROP_STATE, false);
    }


}
    
//+------------------------------------------------------------------
//|                             
//+------------------------------------------------------------------
//
//

int start()
{
   return(0);
}


void begin(){

   //uint timeb = GetTickCount();


   ArrayInitialize(UpEnv,EMPTY_VALUE);
   ArrayInitialize(DnEnv,EMPTY_VALUE);
   ArrayInitialize(tmBuffer,EMPTY_VALUE);
   
   int i,limit;
   
   

   int calcbar = Calcbars;
   
   limit = Fvb+calcbar;
   if(Calcbars ==0) limit =Bars-1;
   //
   //
   //
   //
   //
   
      //Print("Fvb : "+Fvb);
      for (i=limit; i>=Fvb; i--)
      {
         int tmalength; 
         
         if(MathMod(TMALength,2.0) !=0) tmalength = (TMALength+1.0)*0.5;
         else                           tmalength = TMALength *0.5;
         
         
         cent[i] = iMA(NULL,0,tmalength,0,MODE_SMA,Price,i);

//       //TMA and SMA of sma are identical
//  
//         double sum  = iMA(NULL,0,TMALength,0,MODE_SMA,Price,i);
//         double sumw = 1;
//         double half = (TMALength+1.0)/2.0;
//
//         for( k=1; k<TMALength && (i+k)<=Bars-1; k++)
//         {
//             double weight = k+1; if (weight > half) weight = TMALength-k;
//                    sumw  += weight;
//                    sum   += weight*iMA(NULL,0,1,0,MODE_SMA,Price,i+k);  
//         }             

         double ssum=0;
         
         for(int q=0; q<tmalength; q++) ssum +=cent[i+q];
             
         tmBuffer[i] = ssum/tmalength;
         UpEnv[i] = (1.0+Deviation/100)*tmBuffer[i];
         DnEnv[i] = (1.0-Deviation/100)*tmBuffer[i];
         
         up[i] = UpEnv[i];  //
         dn[i] = DnEnv[i];
         
            
            double slope,interC,interU,interD;
            w =SlopePeriod;
            
            slope  = (tmBuffer[i] - tmBuffer[i+w])/w;
            interC = tmBuffer[i+w];
            interU = UpEnv[i+w];
            interD = DnEnv[i+w];
            
            
        
      }


      
            datetime timeA,timeB;
            double   valA,valB;
            
            timeA = Time[Fvb+HalfShift+w];       timeB = Time[Fvb+HalfShift];
            valA  = tmBuffer[Fvb+5];   valB  = tmBuffer[Fvb];
    
        i =Fvb;
        
        ObjectsDeleteAll(ChartID(), pfix);
   
        ObjectCreate(pfix+"up", OBJ_TREND, 0, timeA, up[i+w], timeB, up[i]);
            ObjectSet(pfix+"up", OBJPROP_WIDTH, 1);
            ObjectSet(pfix+"up", OBJPROP_STYLE, 2);
            ObjectSet(pfix+"up", OBJPROP_COLOR, clrMediumSeaGreen);
            ObjectSet(pfix+"up", OBJPROP_RAY, true);

        ObjectCreate(pfix+"dn", OBJ_TREND, 0, timeA, dn[i+w], timeB, dn[i]);
            ObjectSet(pfix+"dn", OBJPROP_WIDTH, 1);
            ObjectSet(pfix+"dn", OBJPROP_STYLE, 2);
            ObjectSet(pfix+"dn", OBJPROP_COLOR, clrMediumSeaGreen);
            ObjectSet(pfix+"dn", OBJPROP_RAY, true);

         ObjectCreate(pfix+"center", OBJ_TREND, 0, timeA, valA, timeB, valB);
            ObjectSet(pfix+"center", OBJPROP_WIDTH, 1);
            ObjectSet(pfix+"center", OBJPROP_STYLE, 2);
            ObjectSet(pfix+"center", OBJPROP_COLOR, clrMediumSeaGreen);
            ObjectSet(pfix+"center", OBJPROP_RAY, true);
         
         ObjectCreate(pfix+"vv", OBJ_VLINE, 0, Time[Fvb], 0, 0, 0);
            ObjectSet(pfix+"vv", OBJPROP_STYLE, STYLE_DOT);
            ObjectSet(pfix+"vv", OBJPROP_COLOR, clrSlateGray);
    
    

         
     
     //uint result = GetTickCount() - timeb; 
     //Comment("TMA calc : "+result);
     
     return;
     


     
}

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

//
//
//
//
//

int stringToTimeFrame(string tfs)
{
   tfs = StringUpperCase(tfs);
   for (int i=ArraySize(iTfTable)-1; i>=0; i--)
         if (tfs==sTfTable[i] || tfs==""+iTfTable[i]) return(MathMax(iTfTable[i],Period()));
                                                      return(Period());
}
string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

//
//
//
//
//

string StringUpperCase(string str)
{
   string   s = str;

   for (int length=StringLen(str)-1; length>=0; length--)
   {
      int tchar = StringGetChar(s, length);
         if((tchar > 96 && tchar < 123) || (tchar > 223 && tchar < 256))
                     s = StringSetChar(s, length, tchar - 32);
         else if(tchar > -33 && tchar < 0)
                     s = StringSetChar(s, length, tchar + 224);
   }
   return(s);
}

//
//
//
//
//
