using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo
{

    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class ParabolicStop : Indicator
    {

        [Parameter("Start", DefaultValue = 0.02)]
        public double Start { get; set; }

        [Parameter("Maximum", DefaultValue = 0.2)]
        public double Maximum { get; set; }

        [Parameter("Length", DefaultValue = 20)]
        public int Length { get; set; }

        [Parameter("Multiplier", DefaultValue = 4)]
        public int Multiplier { get; set; }

        private ParabolicSAR _sar;
        private SimpleMovingAverage _smaClose;
        private AverageTrueRange _atr;

        private double _max;
        private double _min;
        private bool _isUptrend;
        private double _vstop;
        bool isUptrendPrev;
        double vstopPrev;

        // Erstelle die IndicatorDataSeries mit Output-Attribut und LineColor
        [Output("Stop Line", LineColor = "Aqua", PlotType = PlotType.Line)]
        public IndicatorDataSeries _stopLine { get; set; }

        [Output("SMA Line", LineColor = "White", PlotType = PlotType.Line)]
        public IndicatorDataSeries _smaLine { get; set; }

        protected override void Initialize()
        {
            _sar = Indicators.ParabolicSAR(Bars, Start, Maximum);
            _smaClose = Indicators.SimpleMovingAverage(Bars.ClosePrices, 3 * Length);
            _atr = Indicators.AverageTrueRange(Bars, Length, MovingAverageType.Exponential);

        }

        public override void Calculate(int index)
        {
            double smaClose = _smaClose.Result[index];

            double max1 = System.Math.Max(_max, Bars.ClosePrices[index]); 
            double min1 = System.Math.Min(_min, Bars.ClosePrices[index]); 

            double stop = isUptrendPrev ? max1 - Multiplier * _atr.Result[index] : min1 + Multiplier * _atr.Result[index];

            double vstop1 = isUptrendPrev ? System.Math.Min(System.Math.Max(vstopPrev, stop), _sar.Result[index]) : System.Math.Max(System.Math.Min(vstopPrev, stop), _sar.Result[index]); 

            isUptrendPrev = _isUptrend;
            _isUptrend = Bars.ClosePrices[index] - vstop1 >= 0;
            bool isTrendChanged = _isUptrend != isUptrendPrev;

            _max = isTrendChanged ? Bars.ClosePrices[index] : max1;
            _min = isTrendChanged ? Bars.ClosePrices[index] : min1;

            vstopPrev = _vstop;
            _vstop = isTrendChanged ? (_isUptrend ? System.Math.Max(_max - Multiplier * _atr.Result[index], _sar.Result[index]) : System.Math.Min(_min + Multiplier * _atr.Result[index], _sar.Result[index])) : vstop1; 

            _stopLine[index] = _vstop;  
            _smaLine[index] = smaClose;  
        }
    }
}