#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;
using NinjaTrader.Gui.PropertiesTest;
#endregion

//This namespace holds Indicators in this folder and is required. Do not change it. 
namespace NinjaTrader.NinjaScript.Indicators
{
    public class DC : Indicator
    {
        private MAX Max;
        private MIN Min;

        protected override void OnStateChange()
        {
            if (State == State.SetDefaults)
            {
                Description = @"Modified Donchian Channel which utilizes closes and displays breakouts";
                Name = "Donchian Channel";
                Calculate = Calculate.OnPriceChange;
                IsOverlay = true;
                DisplayInDataBox = true;
                DrawOnPricePanel = true;
                DrawHorizontalGridLines = true;
                DrawVerticalGridLines = true;
                PaintPriceMarkers = true;
                ScaleJustification = ScaleJustification.Right;
                IsSuspendedWhileInactive = true;
                Period = 72;
                UpperStroke = new Stroke(Brushes.Yellow, DashStyleHelper.Solid, 2);
                LowerStroke = new Stroke(Brushes.Yellow, DashStyleHelper.Solid, 2);
            }
            else if (State == State.Configure)
            {
                AddPlot(UpperStroke, PlotStyle.Line, "Upper");
                AddPlot(LowerStroke, PlotStyle.Line, "Lower");
            }
            else if (State == State.DataLoaded)
            {
                Max = MAX(Close, Period);
                Min = MIN(Close, Period);
            }
            else if (State == State.Historical)
            {
                SetZOrder(-1); // Display behind bars on chart.
            }
        }

        protected override void OnBarUpdate()
        {
            if (CurrentBar < Period)
                return;
            
            Upper[0] = Max[1];
            Lower[0] = Min[1];
        }

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

        [Range(1, int.MaxValue), NinjaScriptProperty]
        [Display(ResourceType = typeof(Custom.Resource), Name = "Period", GroupName = "Donchian Channel", Order = 1)]
        public int Period
        { get; set; }

        [NinjaScriptProperty]
        [Display(Name = "Upper Stroke", GroupName = "Donchian Channel", Order = 2)]
        public Stroke UpperStroke
        { get; set; }

        [NinjaScriptProperty]
        [Display(Name = "Lower Stroke", GroupName = "Donchian Channel", Order = 3)]
        public Stroke LowerStroke
        { get; set; }

        [Browsable(false)]
        [XmlIgnore()]
        public Series<double> Upper
        {
            get { return Values[0]; }
        }

        [Browsable(false)]
        [XmlIgnore()]
        public Series<double> Lower
        {
            get { return Values[1]; }
        }
    }
}

#region NinjaScript generated code. Neither change nor remove.

namespace NinjaTrader.NinjaScript.Indicators
{
    public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
    {
        private DC[] cacheDC;
        public DC DC(int period, Stroke upperStroke, Stroke lowerStroke)
        {
            return DC(Input, period, upperStroke, lowerStroke);
        }

        public DC DC(ISeries<double> input, int period, Stroke upperStroke, Stroke lowerStroke)
        {
            if (cacheDC != null)
                for (int idx = 0; idx < cacheDC.Length; idx++)
                    if (cacheDC[idx] != null && cacheDC[idx].Period == period && cacheDC[idx].UpperStroke == upperStroke && cacheDC[idx].LowerStroke == lowerStroke && cacheDC[idx].EqualsInput(input))
                        return cacheDC[idx];
            return CacheIndicator<DC>(new DC(){ Period = period, UpperStroke = upperStroke, LowerStroke = lowerStroke }, input, ref cacheDC);
        }
    }
}

namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
{
    public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
    {
        public Indicators.DC DC(int period, Stroke upperStroke, Stroke lowerStroke)
        {
            return indicator.DC(Input, period, upperStroke, lowerStroke);
        }

        public Indicators.DC DC(ISeries<double> input , int period, Stroke upperStroke, Stroke lowerStroke)
        {
            return indicator.DC(input, period, upperStroke, lowerStroke);
        }
    }
}

namespace NinjaTrader.NinjaScript.Strategies
{
    public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
    {
        public Indicators.DC DC(int period, Stroke upperStroke, Stroke lowerStroke)
        {
            return indicator.DC(Input, period, upperStroke, lowerStroke);
        }

        public Indicators.DC DC(ISeries<double> input , int period, Stroke upperStroke, Stroke lowerStroke)
        {
            return indicator.DC(input, period, upperStroke, lowerStroke);
        }
    }
}

#endregion