using BinanceExchange.API.Models.Response;

public static class Indicators
{

    public static decimal getSMA(List<KlineCandleStickResponse> responses, int curIndex, int interval, int startIndex = 0)
    {
        // curIndex = Math.Clamp(curIndex,0, responses.Count);
        // decimal total = 0;
        // for(int i=curIndex-interval; i < curIndex; i++){
        //     total += responses[i].Close;
        // }
        // // decimal length = (curIndex-startIndex); if(length <= 0){length=1;}
        // // decimal N = (length /  (decimal)interval);
        // Console.WriteLine($"SMA Cacl ({interval}) : {total}/{interval} = {total/interval}");

        // return total / interval;

        decimal total = 0;
        for (int x = (curIndex > 1500) ? 1500 : 0; x < interval; x++)
        {
            total += (curIndex - x >= 0) ? responses[curIndex - x].Close : (decimal)0;
        }
        return total / (decimal)interval;
    }

    public static decimal getSMA(List<decimal> responses, int curIndex, int interval, int startIndex = 0)
    {
        decimal total = 0;
        for (int x = (curIndex > 1500) ? 1500 : 0; x < interval; x++)
        {
            total += (curIndex - x >= 0) ? responses[curIndex - x] : (decimal)0;
        }
        return total / (decimal)interval;
    }

    public static decimal getEMA(List<KlineCandleStickResponse> responses, int curIndex, int startIndex, int periods, decimal? prevEma = null)
    {
        if (curIndex < 1) { return 0; }
        if (startIndex - curIndex > 1500) { return 0; }; if (curIndex >= responses.Count) { return 0; };


        //  decimal N = (decimal)curIndex / (decimal)periods;

        decimal multiplier = (decimal)2 / ((decimal)(periods + 1));
        decimal firstHalf = responses[curIndex].Close * multiplier; //First half of the equation
        decimal secondHalf = getEMA(responses, curIndex - 1, startIndex, periods) * (1 - multiplier); //Second half of the equation
        // decimal secondHalf = (prevEma ?? getSMA(responses, curIndex-1, periods)) * (1- multiplier); //Second half of the equation

        return firstHalf + secondHalf;
    }

    public static decimal getEMA(List<decimal> responses, int curIndex, int startIndex, int periods)
    {
        if (curIndex < 1) { return 0; }
        if (startIndex - curIndex > 1500) { return 0; };
        if (curIndex >= responses.Count) { return 0; };

        //  decimal N = (decimal)curIndex / (decimal)periods;

        decimal multiplier = (decimal)2 / ((decimal)(periods + 1));

        decimal firstHalf = responses[curIndex] * multiplier; //First half of the equation
        decimal secondHalf = getEMA(responses, curIndex - 1, startIndex, periods) * (1 - multiplier); //Second half of the equation
        // decimal secondHalf = (prevEma ?? getSMA(responses, curIndex-1, periods)) * (1- multiplier); //Second half of the equation

        return firstHalf + secondHalf;
    }

    public static decimal getMACD(List<KlineCandleStickResponse> responses, int shortPeriod, int longPeriod, int curIndex)
    {
        return getEMA(responses, curIndex, curIndex, shortPeriod) - getEMA(responses, curIndex, curIndex, longPeriod);
    }

    public static decimal getATR(List<KlineCandleStickResponse> responses, int period, int curIndex, decimal[] prevATRs)
    {
        if (curIndex <= 0 || curIndex > responses.Count) { return 0; }

        if (curIndex >= responses.Count) { return 0; };

        decimal TR = responses[curIndex].High - responses[curIndex].Low;
        if (curIndex > 1)
        {
            decimal tr2 = responses[curIndex].High - responses[curIndex - 1].Close;
            decimal tr3 = responses[curIndex].Low - responses[curIndex - 1].Close;
            if (tr2 > TR)
            {
                TR = tr2;
            }
            if (tr3 > TR)
            {
                TR = tr3;
            }
        }

        if (curIndex < period)
        {
            //get just the TR
            return TR;
        }
        decimal prevATR = 0;
        if (prevATRs.Length > 0)
        {
            // int start = curIndex - period;
            // for (int i = start; i < curIndex; i++)
            // {
            //     prevATR += prevATRs[i];
            // }

            // prevATR = (prevATR) / (decimal)(curIndex-start);
            prevATR = prevATRs[curIndex - 1];
        }
        decimal ATR = (decimal)((prevATR * (decimal)(period - 1)) + TR) / (decimal)period;
        return ATR;
    }

    public static bool didMACDLineCrossSignalLine(decimal[] MACDs, decimal[] Signals, int index, int period = 7, decimal threshold = (decimal)0.1)
    {
        int counter = 0;
        if (index >= MACDs.Length || index >= Signals.Length) { return false; }
        if (index - period < 0) { return false; };
        for (int i = index; i > index - period; i--)
        {
            if (MACDs[i] < Signals[i])
            {
                counter++;
            }
        }
        bool wasMACDUnder = counter > ((float)period / 2f);
        return wasMACDUnder && MACDs[index] > Signals[index];
    }

    public static decimal getAvgDiff(List<KlineCandleStickResponse> responses, int i)
    {
        decimal avgDiff = 0;

        if (i > 10)
        {
            for (int k = 1; k < 6; k++)
            {
                avgDiff += responses[i - k].Close;
            }

            avgDiff = avgDiff / (decimal)5;
            avgDiff = responses[i].Close - avgDiff;
        }

        return avgDiff;
    }
}