#region Using declarations
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.DrawingTools;
#endregion

//This namespace holds Indicators in this folder and is required. Do not change it. 
namespace NinjaTrader.NinjaScript.Indicators
{
    public class TrafficLight : Indicator
    {
        private MACDHistogram macdHistogram1;
        private MACDHistogram macdHistogram2;
        private MACDHistogram macdHistogram3;
        private RSIHistogram rsiHistogram;
        private TMASlope tmaSlope;
        
        protected override void OnStateChange()
        {
            if (State == State.SetDefaults)
            {
                Description = @"Inspired by @BestForexMethod";
                Name = "Traffic Light";
                Calculate = Calculate.OnPriceChange;
                IsOverlay = false;
                DisplayInDataBox = true;
                ScaleJustification = ScaleJustification.Right;
                IsSuspendedWhileInactive = false;

                PositiveBrush = Brushes.LimeGreen;
                NegativeBrush = Brushes.Red;
                NeutralBrush = Brushes.Yellow;

                ArePlotsConfigurable = false;
                AddPlot(new Stroke(Brushes.Transparent, 0), PlotStyle.Bar, "Traffic Light");
            }
            else if (State == State.DataLoaded)
            {
                macdHistogram1 = MACDHistogram(12, 36);
                macdHistogram2 = MACDHistogram(48, 144);
                macdHistogram3 = MACDHistogram(200, 600);
                rsiHistogram = RSIHistogram(8, 3, 1.5);
                tmaSlope = TMASlope(13, 100);
            }
        }

        protected override void OnBarUpdate()
        {
            if (CurrentBar < 100) // Length of TMA Slope ATR period
                return;

            Value[0] = 1.0;

            if (macdHistogram1[0] > macdHistogram1[1] &&
                macdHistogram2[0] > macdHistogram2[1] &&
                macdHistogram3[0] > macdHistogram3[1] &&
                rsiHistogram[0] > rsiHistogram[1] &&
                tmaSlope[0] > 0.0 &&
                tmaSlope[0] > tmaSlope[1])
                PlotBrushes[0][0] = PositiveBrush;
            else if (macdHistogram1[0] < macdHistogram1[1] &&
                     macdHistogram2[0] < macdHistogram2[1] &&
                     macdHistogram3[0] < macdHistogram3[1] &&
                     rsiHistogram[0] < rsiHistogram[1] &&
                     tmaSlope[0] < 0.0 &&
                     tmaSlope[0] < tmaSlope[1])
                PlotBrushes[0][0] = NegativeBrush;
            else
                PlotBrushes[0][0] = NeutralBrush;
        }

        protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
        {
            base.OnRender(chartControl, chartScale);

            foreach (Plot plot in Plots)
                plot.Width = chartControl.GetBarPaintWidth(ChartBars);
        }

        public override string DisplayName
        {
            get { return Name; }
        }

        [XmlIgnore]
        [Display(Name = "Positive Value", Order = 1, GroupName = "Traffic Light")]
        public Brush PositiveBrush
        { get; set; }

        [Browsable(false)]
        public string PositiveBrushSerializable
        {
            get { return Serialize.BrushToString(PositiveBrush); }
            set { PositiveBrush = Serialize.StringToBrush(value); }
        }

        [XmlIgnore]
        [Display(Name = "Negative Value", Order = 2, GroupName = "Traffic Light")]
        public Brush NegativeBrush
        { get; set; }

        [Browsable(false)]
        public string NegativeBrushSerializable
        {
            get { return Serialize.BrushToString(NegativeBrush); }
            set { NegativeBrush = Serialize.StringToBrush(value); }
        }

        [XmlIgnore]
        [Display(Name = "Neutral Value", Order = 3, GroupName = "Traffic Light")]
        public Brush NeutralBrush
        { get; set; }

        [Browsable(false)]
        public string NeutralBrushSerializable
        {
            get { return Serialize.BrushToString(NeutralBrush); }
            set { NeutralBrush = Serialize.StringToBrush(value); }
        }
    }
}

#region NinjaScript generated code. Neither change nor remove.

namespace NinjaTrader.NinjaScript.Indicators
{
    public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
    {
        private TrafficLight[] cacheTrafficLight;
        public TrafficLight TrafficLight()
        {
            return TrafficLight(Input);
        }

        public TrafficLight TrafficLight(ISeries<double> input)
        {
            if (cacheTrafficLight != null)
                for (int idx = 0; idx < cacheTrafficLight.Length; idx++)
                    if (cacheTrafficLight[idx] != null &&  cacheTrafficLight[idx].EqualsInput(input))
                        return cacheTrafficLight[idx];
            return CacheIndicator<TrafficLight>(new TrafficLight(), input, ref cacheTrafficLight);
        }
    }
}

namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
{
    public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
    {
        public Indicators.TrafficLight TrafficLight()
        {
            return indicator.TrafficLight(Input);
        }

        public Indicators.TrafficLight TrafficLight(ISeries<double> input )
        {
            return indicator.TrafficLight(input);
        }
    }
}

namespace NinjaTrader.NinjaScript.Strategies
{
    public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
    {
        public Indicators.TrafficLight TrafficLight()
        {
            return indicator.TrafficLight(Input);
        }

        public Indicators.TrafficLight TrafficLight(ISeries<double> input )
        {
            return indicator.TrafficLight(input);
        }
    }
}

#endregion