//+------------------------------------------------------------------+
//| Horizontal Candle Histogram MTF (Estilo Linhas)                 |
//| COM TABELA DE 49 CORES - Rafael / Borbel                        |
//| COM FONTE DINÂMICA - NÚMERO GANHADOR MAIOR                       |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property strict

//==============================//
// CONFIGURAÇÕES PRINCIPAIS
//==============================//
extern int X_distance  = 66;   
extern int Y_distance  = 300;  
extern int TotalLinhas = 51;   

//==============================//
// CONFIGURAÇÃO MTF
//==============================//
extern bool Enable_MTF = true;
extern ENUM_TIMEFRAMES MTF_Period = PERIOD_D1;

//==============================//
// CORES BASE
//==============================//
extern color CorBaseBuy   = RoyalBlue;
extern color CorBaseSell  = MediumPurple;
extern color PavioColor = DimGray;
extern color TextColor  = Lavender;

//==============================//
// CORES ESPECIAIS PARA TEXTOS ≥ 10000
//==============================//
extern color Color7500Buy  = Aqua;
extern color Color7500Sell = Red;

//==============================//
// CORES PARA TABELA (ZERO)
//==============================//
extern color ColorZeroBuy  = clrBlue;
extern color ColorZeroSell = clrViolet;

//==============================//
// CONFIGURAÇÕES DE FONTE
//==============================//
extern int BodyFontSize = 12;        // Tamanho da fonte do número do corpo
extern int WickFontSize = 12;        // Tamanho da fonte dos números dos pavios
extern int SignalFontSize = 12;      // Tamanho da fonte dos textos de sinal
extern int WinningFontSize = 16;     // Tamanho da fonte do número vencedor
extern string FontName = "DS-Digital Bold";    // Nome da fonte

// Prefixo
string prefix;

//==============================//
// TABELA DE 49 CORES (igual ao segundo indicador)
//==============================//
color ColorTable[49] = {
   clrBlue, clrOrchid, clrPurple, clrDodgerBlue, clrLavender, clrLime, clrYellow,
   clrOrange, clrMediumBlue, clrGray, clrGold, clrRed, clrAqua, clrIndigo, clrGray,
   clrFireBrick, clrDarkRed, clrMaroon, clrOlive, clrTomato, clrSpringGreen, clrIndigo,
   clrDarkGreen, clrDarkTurquoise, clrPaleGreen, clrPeru, clrSaddleBrown, clrSeashell,
   clrTomato, clrAqua, clrCadetBlue, clrDeepPink, clrHotPink, clrOrangeRed, clrGreenYellow,
   clrTan, clrAquamarine, C'0,155,78', C'94,0,94', C'0,73,147', C'255,255,85',
   C'0,73,147', C'0,64,64', C'128,128,255', C'64,0,128', C'128,128,64', C'128,64,64',
   C'255,255,66', clrLime
};

//==============================//
// VARIÁVEIS PARA DETECTAR MUDANÇA DE ESCALA
//==============================//
static int lastBodyScale = 0;
static int lastUpperWickScale = 0;
static int lastLowerWickScale = 0;
static bool bodyScaleChanged = false;
static bool upperWickScaleChanged = false;
static bool lowerWickScaleChanged = false;
static int lastPtsCorpo = 0;
static int lastPtsUp = 0;
static int lastPtsDown = 0;



//------------------------------------------------------
// FUNÇÕES AUXILIARES RGB
//------------------------------------------------------
int GetRed(color c)   { return c & 0xFF; }
int GetGreen(color c) { return (c >> 8) & 0xFF; }
int GetBlue(color c)  { return (c >> 16) & 0xFF; }

color RGB(int r, int g, int b) {
   return ((b & 0xFF) << 16) | ((g & 0xFF) << 8) | (r & 0xFF);
}

color MixColor(color c1, color c2, double factor) {
   int r = (int)(GetRed(c1)*(1-factor) + GetRed(c2)*factor);
   int g = (int)(GetGreen(c1)*(1-factor) + GetGreen(c2)*factor);
   int b = (int)(GetBlue(c1)*(1-factor) + GetBlue(c2)*factor);
   return RGB(r,g,b);
}

//------------------------------------------------------
// FUNÇÕES PARA TABELA DE 49 CORES
//------------------------------------------------------
int GetColorNumberFromValue(double value) {
   int v = (int)value;
   if(v < 6000) return 0;
   else if(v < 8000) return 1;
   else if(v < 10000) return 2;
   else if(v < 12000) return 3;
   else if(v < 14000) return 4;
   else if(v < 16000) return 5;
   else if(v < 18000) return 6;
   else if(v < 20000) return 7;
   else if(v < 22000) return 8;
   else if(v < 24000) return 9;
   else if(v < 26000) return 10;
   else if(v < 28000) return 11;
   else if(v < 30000) return 12;
   else if(v < 32000) return 13;
   else if(v < 34000) return 14;
   else if(v < 36000) return 15;
   else if(v < 38000) return 16;
   else if(v < 40000) return 17;
   else if(v < 50000) return 18;
   else if(v < 60000) return 19;
   else if(v < 70000) return 20;
   else if(v < 80000) return 21;
   else if(v < 90000) return 22;
   else if(v < 100000) return 23;
   else if(v < 110000) return 24;
   else if(v < 120000) return 25;
   else if(v < 130000) return 26;
   else if(v < 140000) return 27;
   else if(v < 150000) return 28;
   else if(v < 160000) return 29;
   else if(v < 170000) return 30;
   else if(v < 180000) return 31;
   else if(v < 190000) return 32;
   else if(v < 200000) return 33;
   else if(v < 210000) return 34;
   else if(v < 220000) return 35;
   else if(v < 230000) return 36;
   else if(v < 240000) return 37;
   else if(v < 250000) return 38;
   else if(v < 260000) return 39;
   else if(v < 270000) return 40;
   else if(v < 280000) return 41;
   else if(v < 290000) return 42;
   else if(v < 300000) return 43;
   else if(v < 310000) return 44;
   else if(v < 320000) return 45;
   else if(v < 330000) return 46;
   else if(v < 340000) return 47;
   else return 48;
}

color GetColorFromTable(int colorNum, bool isBuy) {
   if(colorNum != 0) return ColorTable[colorNum];
   return isBuy ? ColorZeroBuy : ColorZeroSell;
}

//+------------------------------------------------------------------+
// CORES DO HISTOGRAMA - SEM LARANJA (removido scaleChanged)
//+------------------------------------------------------------------+
color GetBuyerGradientColor(int index, int maxHeight, double totalValue, bool scaleChanged) {
   // Removido: if(scaleChanged) return clrOrange;
   int colorNum = GetColorNumberFromValue(totalValue);
   color overlay = GetColorFromTable(colorNum, true);
   double factor = (maxHeight > 0) ? (double)index / (double)(maxHeight - 1) : 0.0;
   if(colorNum == 0) return MixColor(CorBaseBuy, overlay, factor);
   else return MixColor(overlay, CorBaseBuy, factor);
}

color GetSellerGradientColor(int index, int maxHeight, double totalValue, bool scaleChanged) {
   // Removido: if(scaleChanged) return clrOrange;
   int colorNum = GetColorNumberFromValue(totalValue);
   color overlay = GetColorFromTable(colorNum, false);
   double factor = (maxHeight > 0) ? (double)index / (double)(maxHeight - 1) : 0.0;
   return MixColor(overlay, CorBaseSell, factor);
}

color SelectHistoColor(int value, color c1, color c2, color c3, bool scaleChanged, bool isBuy) {
   // Removido: if(scaleChanged) return clrOrange;
   int colorNum = GetColorNumberFromValue(value);
   return GetColorFromTable(colorNum, isBuy);
}

//------------------------------------------------------
// FUNÇÃO PARA VERIFICAR MUDANÇA DE ESCALA (MESMA LÓGICA)
//------------------------------------------------------
int GetScaleValue(int value) {
   if(value >= 100000) return value / 10000;
   if(value >= 10000) return value / 1000;
   if(value >= 1000) return value / 100;
   if(value >= 100) return value / 10;
   return value;
}

bool CheckScaleChanged(int currentValue, int &lastScaleValue, bool &scaleFlag) {
   int currentScale = GetScaleValue(currentValue);
   bool changed = (currentScale != lastScaleValue && lastScaleValue != 0);
   scaleFlag = changed;
   lastScaleValue = currentScale;
   return changed;
}

//------------------------------------------------------
// CRIAÇÃO DE OBJETOS
//------------------------------------------------------
void CreateLine(string name, int x, int y, color clr)
{
   if(ObjectFind(0, name) == -1)
      ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);

   ObjectSetText(name, "—", 8, "Arial", clr);
   ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}

void CreateText(string name, int x, int y, string text, color clr, int fontSize = 12)
{
   if(ObjectFind(0, name) == -1)
      ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);

   ObjectSetText(name, text, fontSize, FontName, clr);
   ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}

//------------------------------------------------------
// FUNÇÃO PARA DETERMINAR O NÚMERO VENCEDOR
//------------------------------------------------------
int GetWinningValue(int corpo, int upperWick, int lowerWick) {
   int maxVal = MathMax(corpo, MathMax(upperWick, lowerWick));
   return maxVal;
}

//------------------------------------------------------
// LIMPEZA DE OBJETOS
//------------------------------------------------------
void DeleteHistogramObjects()
{
   for(int i = ObjectsTotal() - 1; i >= 0; i--)
   {
      string name = ObjectName(i);
      if(StringFind(name, prefix) == 0)
         ObjectDelete(name);
   }
}

void DeleteSignalObjects()
{
   string sellSignalName = prefix + "WICK_SELL_SIGNAL";
   string buySignalName = prefix + "WICK_BUY_SIGNAL";
   
   if(ObjectFind(0, sellSignalName) != -1)
      ObjectDelete(sellSignalName);
   
   if(ObjectFind(0, buySignalName) != -1)
      ObjectDelete(buySignalName);
}

//------------------------------------------------------
int OnInit()
{
   if(Enable_MTF)
      prefix = "HISTO_MTF_";
   else
      prefix = "HISTO_CURRENT_";

   DeleteHistogramObjects();
   return(INIT_SUCCEEDED);
}

//------------------------------------------------------
void OnDeinit(const int reason)
{
   DeleteHistogramObjects();
}

//------------------------------------------------------
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[])
{
   double O, C, H, L;

   if(Enable_MTF)
   {
      O = iOpen(Symbol(), MTF_Period, 0);
      C = iClose(Symbol(), MTF_Period, 0);
      H = iHigh(Symbol(), MTF_Period, 0);
      L = iLow(Symbol(), MTF_Period, 0);
   }
   else
   {
      O = open[0];
      C = close[0];
      H = high[0];
      L = low[0];
   }

   bool isBuy = (C > O);

   double bodySize  = MathAbs(C - O);
   double upperWick = H - MathMax(O, C);
   double lowerWick = MathMin(O, C) - L;

   double totalRange = H - L;
   if(totalRange <= 0) totalRange = Point;

   double pctPorLinha = totalRange / TotalLinhas;

   int y = Y_distance;

   // Pontos (sem multiplicador, valores brutos)
   int ptsCorpo = (int)MathRound(bodySize / Point);
   int ptsUp   = (int)MathRound(upperWick / Point);
   int ptsDown = (int)MathRound(lowerWick / Point);
   
   // Detecta quem está se movendo
bool corpoMovendo = (ptsCorpo != lastPtsCorpo);
bool upMovendo    = (ptsUp != lastPtsUp);
bool downMovendo  = (ptsDown != lastPtsDown);

   // Detectar mudança de escala (apenas para os números)
   CheckScaleChanged(ptsCorpo, lastBodyScale, bodyScaleChanged);
   CheckScaleChanged(ptsUp, lastUpperWickScale, upperWickScaleChanged);
   CheckScaleChanged(ptsDown, lastLowerWickScale, lowerWickScaleChanged);

//=========================================
// DETERMINAR O NÚMERO VENCEDOR (MAIOR VALOR)
//=========================================
int winningValue = GetWinningValue(ptsCorpo, ptsUp, ptsDown);

// Fonte padrão
int finalBodyFontSize  = BodyFontSize;
int finalUpFontSize    = WickFontSize;
int finalDownFontSize  = WickFontSize;

// Só participa da disputa quem está se movendo
int corpoAtivo = corpoMovendo ? ptsCorpo : -1;
int upAtivo    = upMovendo    ? ptsUp    : -1;
int downAtivo  = downMovendo  ? ptsDown  : -1;

// Descobre vencedor ENTRE OS ATIVOS
if(corpoAtivo > upAtivo && corpoAtivo > downAtivo)
{
   finalBodyFontSize = WinningFontSize;
}
else if(upAtivo > corpoAtivo && upAtivo > downAtivo)
{
   finalUpFontSize = WinningFontSize;
}
else if(downAtivo > corpoAtivo && downAtivo > upAtivo)
{
   finalDownFontSize = WinningFontSize;
}

//===============================
// DESENHO DAS LINHAS (histograma vertical) – sem cor laranja
//===============================
for(int i = 0; i < TotalLinhas; i++)
{
   string name = prefix + "LINE_" + IntegerToString(i+1);
   double priceLevel = H - pctPorLinha * i;

   color corLinha = PavioColor;

   bool insideBody = (priceLevel <= MathMax(O, C) && priceLevel >= MathMin(O, C));

   if(insideBody)
   {
      if(isBuy)
         corLinha = GetBuyerGradientColor(i, TotalLinhas, ptsCorpo, bodyScaleChanged);
      else
         corLinha = GetSellerGradientColor(i, TotalLinhas, ptsCorpo, bodyScaleChanged);
   }

   CreateLine(name, X_distance, y, corLinha);
   y -= 2;
}

//===============================
// TEXTOS DOS NÚMEROS
//===============================
int yHigh = Y_distance;
int yLow  = Y_distance - (TotalLinhas-1)*2;
int yMid  = (yHigh + yLow) / 2;

// Corpo
color corpoTxtColor;

if(bodyScaleChanged)
   corpoTxtColor = clrOrange;
else if(ptsCorpo >= 10000)
   corpoTxtColor = (isBuy ? Color7500Buy : Color7500Sell);
else
   corpoTxtColor = TextColor;

CreateText(prefix + "BODY",
           X_distance - 13,
           yMid,
           IntegerToString(ptsCorpo),
           corpoTxtColor,
           finalBodyFontSize);

// Caveira (mantida original)
string skull = "i";
string skullFont = "SKULLX";
int skullSize = 25;

//===============================
// PAVIO SUPERIOR
//===============================
color clrUp;

if(upperWickScaleChanged)
   clrUp = clrOrange;
else if(ptsUp >= 10000)
   clrUp = (isBuy ? Color7500Buy : Color7500Sell);
else
   clrUp = TextColor;

if(ptsUp == 0)
{
   CreateText(prefix + "UPPER_WICK",
              X_distance - 16,
              yHigh,
              skull,
              Aqua,
              finalUpFontSize);

   ObjectSetText(prefix + "UPPER_WICK",
                 skull,
                 skullSize,
                 skullFont,
                 Aqua);
}
else
{
   CreateText(prefix + "UPPER_WICK",
              X_distance - 16,
              yHigh,
              IntegerToString(ptsUp),
              clrUp,
              finalUpFontSize);
}

//===============================
// PAVIO INFERIOR
//===============================
color clrDown;

if(lowerWickScaleChanged)
   clrDown = clrOrange;
else if(ptsDown >= 10000)
   clrDown = (isBuy ? Color7500Buy : Color7500Sell);
else
   clrDown = TextColor;

if(ptsDown == 0)
{
   CreateText(prefix + "LOWER_WICK",
              X_distance - 13,
              yLow,
              skull,
              Aqua,
              finalDownFontSize);

   ObjectSetText(prefix + "LOWER_WICK",
                 skull,
                 skullSize,
                 skullFont,
                 Aqua);
}
else
{
   CreateText(prefix + "LOWER_WICK",
              X_distance - 13,
              yLow,
              IntegerToString(ptsDown),
              clrDown,
              finalDownFontSize);
}

   //===============================
   // TEXTOS DE SINAL ("venda" / "comp") – NUNCA laranjas
   //===============================
   DeleteSignalObjects();

   if(isBuy && (ptsUp > ptsCorpo))
   {
      CreateText(prefix + "WICK_SELL_SIGNAL", X_distance + 46, yMid+1, "venda", TextColor, SignalFontSize);
   }

   if(!isBuy && (ptsDown > ptsCorpo))
   {
      CreateText(prefix + "WICK_BUY_SIGNAL", X_distance + 43, yMid+1 , "comp ", TextColor, SignalFontSize);
   }
// Salva valores anteriores
lastPtsCorpo = ptsCorpo;
lastPtsUp = ptsUp;
lastPtsDown = ptsDown;
   WindowRedraw();
   return(rates_total);
}
//+------------------------------------------------------------------+