//+------------------------------------------------------------------+
//|                                              MarketStructure.mq4 |
//|                     Direct MQL4 Port of MT5 Larry Williams Logic |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Chacha Ian Maroa"
#property link      "https://www.mql5.com/en/users/chachaian"
#property strict

#property indicator_chart_window
#property indicator_buffers 6

#property indicator_color1 clrSpringGreen 
#property indicator_color2 clrHotPink     
#property indicator_color3 clrSpringGreen 
#property indicator_color4 clrHotPink     
#property indicator_color5 clrSpringGreen 
#property indicator_color6 clrHotPink     

#property indicator_width3 2
#property indicator_width4 2
#property indicator_width5 5
#property indicator_width6 5

//--- Inputs
extern int  ShortTermGapPts = 10;            
extern int  IntermediateTermGapPts = 20;    
extern int  LongTermGapPts = 20;            

extern bool DisplayShortTermArrows = false;
extern bool DisplayIntermediateTermArrows = true;
extern bool DisplayLongTermArrows = true;

extern int  ShortTermUpArrowCode = 161;
extern int  ShortTermDownArrowCode = 161;
extern int  IntermediateTermUpArrowCode = 161;
extern int  IntermediateTermDownArrowCode = 161;
extern int  LongTermUpArrowCode = 221;
extern int  LongTermDownArrowCode = 222;

//--- Chart Appearance Inputs
extern bool EnableTrendCandleColoring    = false; 
extern color new_CHART_COLOR_BACKGROUND  = clrWhite;
extern color new_CHART_COLOR_FOREGROUND  = clrBlack;
extern bool  new_CHART_SHOW_GRID         = false;
extern color new_CHART_COLOR_CANDLE_BULL = clrSeaGreen;
extern color new_CHART_COLOR_CANDLE_BEAR = clrBlack;
extern color new_CHART_COLOR_CHART_UP    = clrSeaGreen;
extern color new_CHART_COLOR_CHART_DOWN  = clrBlack;
//--- Buffers
double shortTermLows[], shortTermHighs[], intermediateTermLows[], intermediateTermHighs[], longTermLows[], longTermHighs[];
int currentTrend = 0; 
//--- Global Variables to store original user colors
long old_bg, old_fg, old_grid, old_up, old_down, old_bull, old_bear;
//+------------------------------------------------------------------------------------------------------------------+
int OnInit()
{
   //--- Save user's current colors
   old_bg   = ChartGetInteger(0, CHART_COLOR_BACKGROUND);
   old_fg   = ChartGetInteger(0, CHART_COLOR_FOREGROUND);
   old_grid = ChartGetInteger(0, CHART_COLOR_GRID);
   old_up   = ChartGetInteger(0, CHART_COLOR_CHART_UP);
   old_down = ChartGetInteger(0, CHART_COLOR_CHART_DOWN);
   old_bull = ChartGetInteger(0, CHART_COLOR_CANDLE_BULL);
   old_bear = ChartGetInteger(0, CHART_COLOR_CANDLE_BEAR);

   //--- Bind arrays to buffers
   SetIndexBuffer(0, shortTermLows);
   SetIndexBuffer(1, shortTermHighs);
   SetIndexBuffer(2, intermediateTermLows);
   SetIndexBuffer(3, intermediateTermHighs);
   SetIndexBuffer(4, longTermLows);
   SetIndexBuffer(5, longTermHighs);

   //--- Configure Plots (MQL4 Equivalent of PlotIndexSetInteger)
   for(int Banzai=0; Banzai<indicator_buffers; Banzai++) {
      SetIndexStyle(Banzai, DRAW_ARROW);
      SetIndexEmptyValue(Banzai, EMPTY_VALUE);
   }

   // Set specific arrows for Long Term (MT5 codes 233/234)
   SetIndexArrow(0, ShortTermUpArrowCode);
   SetIndexArrow(1, ShortTermDownArrowCode);
   SetIndexArrow(2, IntermediateTermUpArrowCode);
   SetIndexArrow(3, IntermediateTermDownArrowCode);
   SetIndexArrow(4, LongTermUpArrowCode);
   SetIndexArrow(5, LongTermDownArrowCode);

   ConfigureChartAppearance();
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------------------------------------------------------+
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[])
{
   //--- Recalculate on new bar or first run
   if(prev_calculated < rates_total)
   {
      ArrayInitialize(shortTermLows,  EMPTY_VALUE);
      ArrayInitialize(shortTermHighs, EMPTY_VALUE);
      ArrayInitialize(intermediateTermLows,  EMPTY_VALUE);
      ArrayInitialize(intermediateTermHighs, EMPTY_VALUE);
      ArrayInitialize(longTermLows,  EMPTY_VALUE);
      ArrayInitialize(longTermHighs, EMPTY_VALUE);

      //--- Step 1: Identify Short-Term (MT5 logic: Loop 1 to total-2)
      for(int i = 1; i < rates_total - 1; i++)
      {
         if(Low[i] < Low[i-1] && Low[i] < Low[i+1])
            shortTermLows[i] = Low[i];
         
         if(High[i] > High[i-1] && High[i] > High[i+1])
            shortTermHighs[i] = High[i];
      }

      //--- Step 2: Build Hierarchies (Direct clones of your MT5 Utility Functions)
      BuildIntermediateLows(shortTermLows, rates_total, intermediateTermLows);
      BuildIntermediateHighs(shortTermHighs, rates_total, intermediateTermHighs);
      
      //--- Step 3: Build Long-Term from Intermediate
      BuildIntermediateLows(intermediateTermLows, rates_total, longTermLows);
      BuildIntermediateHighs(intermediateTermHighs, rates_total, longTermHighs);

      // 4. Trend Logic
      if(EnableTrendCandleColoring) {
         UpdateTrend(rates_total);
      }

      // 5. Visibility Toggle
      ApplyVisibility(rates_total);
   }

   return(rates_total);
}
//+------------------------------------------------------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   //--- Restore the user's original chart colors captured in OnInit
   ChartSetInteger(0, CHART_COLOR_BACKGROUND,  (color)old_bg);
   ChartSetInteger(0, CHART_COLOR_FOREGROUND,  (color)old_fg);
   ChartSetInteger(0, CHART_COLOR_GRID,        (color)old_grid);
   
   //--- Restore the bar and wick colors
   ChartSetInteger(0, CHART_COLOR_CHART_UP,    (color)old_up);
   ChartSetInteger(0, CHART_COLOR_CHART_DOWN,  (color)old_down);
   
   //--- Restore the candle body fill colors
   ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, (color)old_bull);
   ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, (color)old_bear);
   
   //--- Force the chart to refresh visually
   ChartRedraw();
   
   //--- Optional: Print to terminal for confirmation
   Print("Larry Williams Indicator removed: Original chart colors restored.");
}
//+------------------------------------------------------------------------------------------------------------------+
void UpdateTrend(int total) 
{
      ChartSetInteger(0, CHART_COLOR_BACKGROUND, (color)old_bg);
      ChartSetInteger(0, CHART_COLOR_FOREGROUND, (color)old_fg);
      ChartSetInteger(0, CHART_COLOR_GRID,       (color)old_grid);
      ChartSetInteger(0, CHART_COLOR_CHART_UP,   (color)old_up);
      ChartSetInteger(0, CHART_COLOR_CHART_DOWN, (color)old_down);
      ChartSetInteger(0, CHART_COLOR_CANDLE_BULL,(color)old_bull);
      ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR,(color)old_bear);
      ChartRedraw();
}
//+------------------------------------------------------------------------------------------------------------------+
void ApplyVisibility(int total) {
   if(!DisplayShortTermArrows) { for(int i=0; i<total; i++) { shortTermLows[i]=EMPTY_VALUE; shortTermHighs[i]=EMPTY_VALUE; } }
   if(!DisplayIntermediateTermArrows) { for(int i=0; i<total; i++) { intermediateTermLows[i]=EMPTY_VALUE; intermediateTermHighs[i]=EMPTY_VALUE; } }
   if(!DisplayLongTermArrows) { for(int i=0; i<total; i++) { longTermLows[i]=EMPTY_VALUE; longTermHighs[i]=EMPTY_VALUE; } }
}
//+------------------------------------------------------------------------------------------------------------------+
void BuildIntermediateHighs(const double &src[], int total, double &dst[])
{
   int idx[]; ArrayResize(idx, 0);
   for(int i=0; i<total; i++) {
      if(src[i] != EMPTY_VALUE) {
         int len = ArraySize(idx);
         ArrayResize(idx, len+1);
         idx[len] = i;
      }
   }
   if(ArraySize(idx) < 3) return;
   for(int k=1; k<ArraySize(idx)-1; k++) {
      int prev = idx[k-1], cur = idx[k], next = idx[k+1];
      if(src[cur] > src[prev] && src[cur] > src[next]) dst[cur] = src[cur];
   }
}
//+------------------------------------------------------------------------------------------------------------------+
void BuildIntermediateLows(const double &src[], int total, double &dst[])
{
   int idx[]; ArrayResize(idx, 0);
   for(int i=0; i<total; i++) {
      if(src[i] != EMPTY_VALUE) {
         int len = ArraySize(idx);
         ArrayResize(idx, len+1);
         idx[len] = i;
      }
   }
   if(ArraySize(idx) < 3) return;
   for(int k=1; k<ArraySize(idx)-1; k++) {
      int prev = idx[k-1], cur = idx[k], next = idx[k+1];
      if(src[cur] < src[prev] && src[cur] < src[next]) dst[cur] = src[cur];
   }
}
//+------------------------------------------------------------------------------------------------------------------+
void ConfigureChartAppearance()
{
   //--- Apply General Chart Settings
   ChartSetInteger(0, CHART_MODE, CHART_CANDLES);
   ChartSetInteger(0, CHART_SHOW_GRID, new_CHART_SHOW_GRID);
   
   //--- Apply Colors from User Inputs
   ChartSetInteger(0, CHART_COLOR_BACKGROUND,  new_CHART_COLOR_BACKGROUND);
   ChartSetInteger(0, CHART_COLOR_FOREGROUND,  new_CHART_COLOR_FOREGROUND);
   
   //--- Apply Candle Body Colors
   ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, new_CHART_COLOR_CANDLE_BULL);
   ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, new_CHART_COLOR_CANDLE_BEAR);
   
   //--- Apply Wick and Outline Colors
   ChartSetInteger(0, CHART_COLOR_CHART_UP,    new_CHART_COLOR_CHART_UP);
   ChartSetInteger(0, CHART_COLOR_CHART_DOWN,  new_CHART_COLOR_CHART_DOWN);
   
   //--- Refresh the chart to show changes immediately
   ChartRedraw();
}
//+------------------------------------------------------------------------------------------------------------------+
