namespace SampleHistoryTesting
{
	using System;
	using System.Collections.Generic;
    
	using System.Diagnostics;
	using System.IO;
	using System.Windows;
	using System.Windows.Forms;
	using System.Windows.Media;
    using System.Threading;
    using System.Windows.Threading;

	using MessageBox = System.Windows.MessageBox;

	using Ecng.Common;
	using Ecng.Xaml;
	using Ecng.Collections;

	using StockSharp.Algo.Candles;
	using StockSharp.Algo.Reporting;
	using StockSharp.Algo.Storages;
	using StockSharp.Algo.Strategies;
	using StockSharp.Algo.Testing;
    using StockSharp.Algo.Reporting;
    using StockSharp.Logging;
	using StockSharp.Algo.Statistics;
    using StockSharp.Algo.PnL;
	using StockSharp.Algo.Indicators.Trend;
    using StockSharp.Algo.Indicators;
    using StockSharp.Algo.Indicators.Misc;
    using StockSharp.Algo.Indicators.Oscillator;
	using StockSharp.BusinessEntities;
    using StockSharp.Xaml;

    using System.Data.OleDb;
	
	public partial class MainWindow
	{
		private SmaStrategy _strategy;
        public static MainWindow Instance { get; private set; }
		private ICollection<EquityData> _curveItems;
		private EmulationTrader _trader;
        private CandleManager candleManager;
        public ChartArea _area;
        public ChartArea _area_ind;
        private ChartCandleElement _candlesElem;
        private ChartIndicatorElement _longMaElem;

		private readonly LogManager _logManager_test = new LogManager();

		private DateTime _lastUpdateDate;
		private DateTime _startEmulationTime;

        public SimpleMovingAverage Sma24 { get; private set; }
        public SimpleMovingAverage Sma50 { get; private set; }
        

		public MainWindow()
		{
			InitializeComponent();
            MainWindow.Instance = this;

			_logManager_test.Listeners.Add(new FileLogListener("log.txt"));
		}

		private void FindPathClick(object sender, RoutedEventArgs e)
		{
			var dlg = new FolderBrowserDialog();

			if (!HistoryPath.Text.IsEmpty())
				dlg.SelectedPath = HistoryPath.Text;

			if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
			{
				HistoryPath.Text = dlg.SelectedPath;
			}
		}

		private void StartBtnClick(object sender, RoutedEventArgs e)
		{
			// если процесс был запущен, то его останавливаем
			if (_trader != null && _trader.State != EmulationStates.Stopped)
			{
				StartBtn.IsEnabled = false;

				_strategy.Stop();
				_trader.Stop();
				_logManager_test.Sources.Clear();

				return;
			}

			if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text))
			{
				MessageBox.Show(this, "Неправильный путь.");
				return;
			}

			// создаем тестовый инструмент, на котором будет производится тестирование
			var security = new Security
			{
                Id = "SPFB.Si@RTS", // по идентификатору инструмента будет искаться папка с историческими маркет данными
                Code = "Si",
                Name = "Si",
				MinStepSize = 1,
				MinStepPrice = 1,
				Exchange = Exchange.Test,
			};

			// тестовый портфель
			var portfolio = new Portfolio { Name = "test account", BeginValue = 1000000m };

			// хранилище, через которое будет производиться доступ к тиковой и котировочной базе
			var storageRegistry = new StorageRegistry();

			// изменяем путь, используемый по умолчанию
			((LocalMarketDataDrive)storageRegistry.DefaultDrive).Path = HistoryPath.Text;

			var timeFrame = TimeSpan.FromMinutes(15);

			// в реальности период может быть другим, и это зависит от объема данных,
			// хранящихся по пути HistoryPath, 
			var startTime = new DateTime(2012, 01, 01);
			var stopTime = new DateTime(2012, 12, 31);
	
			_trader = new EmulationTrader(
				new[] { security },
				new[] { portfolio })
			{
				
                MarketTimeChangedInterval = timeFrame,
				StorageRegistry = storageRegistry,
				//WorkingTime = Exchange.Rts.WorkingTime,

				// необходимо включать только если есть история стаканов и нужно получить более точное тестирование
				UseMarketDepth = false,
			};
            
            _trader.RegisterMarketDepth(new TrendMarketDepthGenerator(security)
            {
                // стакан для инструмента в истории обновляется раз в секунду
                Interval = TimeSpan.FromSeconds(1),
            });
            //_trader.UseMarketDepth = true;
            //{
            //    // стакан для инструмента в истории обновляется раз в секунду
            //    Interval = TimeSpan.FromSeconds(2),
            //};
			// история по стакана отсутствует, но стаканы необходимы для стратегии,
			// то их можно сгенерировать на основании цен последних сделок
			//_trader.RegisterMarketDepth(new TrendMarketDepthGenerator(security)
			//{
			//    // стакан для инструмента в истории обновляется раз в секунду
			//    Interval = TimeSpan.FromSeconds(1),
			//});

			// соединяемся с трейдером и запускаем экспорт,
			// чтобы инициализировать переданными инструментами и портфелями необходимые свойства EmulationTrader
			_trader.Connect();
			_trader.StartExport();
            
			//var candleManager = new CandleManager(_trader);
            candleManager = new CandleManager(_trader);
			var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame);
           // var series = new CandleSeries(typeof(TickCandle), security,1000);
			candleManager.Start(series);



            Sma24 = new SimpleMovingAverage { Length = 24 };
            Sma50 = new SimpleMovingAverage { Length = 50 };

           

            //// создаем торговую стратегию, скользящие средние на 80 5-минуток и 10 5-минуток
            //_strategy = new SmaStrategy(series, new SimpleMovingAverage { Length = 80 }, new SimpleMovingAverage { Length = 10 })
            _strategy = new SmaStrategy(series, Sma24, Sma50)
			{
				Volume = 1,
				Portfolio = portfolio,
				Security = security,
				Trader = _trader
			};


            //_strategy.vcon.Open();
			// копируем параметры на визуальную панель
			ParametersPanel.Parameters.Clear();
			//ParametersPanel.Parameters.AddRange(_strategy.EquityManager.Parameters);
            ParametersPanel.Parameters.AddRange(_strategy.StatisticManager.Parameters);

			if (_curveItems == null)
				_curveItems = Curve.CreateCurve(_strategy.Name, Colors.DarkGreen);
			else
				_curveItems.Clear();

            _strategy.PnLChanged += () =>
            {
                var data = new EquityData
                {
                    Time = _strategy.GetMarketTime(),
                    Value = _strategy.PnL,
                };

                this.GuiAsync(() =>
                {
                    _curveItems.Add(data);
                   // System.Windows.Forms.Application.DoEvents();
                });
               
            };

            // Создание области графика
            _area = new ChartArea();
            _area_ind = new ChartArea();
            //Chart.Areas.Add(_area);
            //Chart_ind.Areas.Add(_area_ind);

            

			//_strategy.StatisticManager.NewEquityData += data => this.GuiAsync(() => _curveItems.Add(data));
            // Создание элемента графика представляющего индикатор
            

			_logManager_test.Sources.Add(_strategy);
            

            // задаем шаг ProgressBar
            var progressStep = ((stopTime - startTime).Ticks / 100).To<TimeSpan>();
            var nextTime = startTime + progressStep;

            TestingProcess.Maximum = 100;
            TestingProcess.Value = 0;

            // и подписываемся на событие изменения времени, чтобы обновить ProgressBar
            _trader.MarketTimeChanged += diff =>
            {
                if (_trader.CurrentTime >= nextTime || _trader.CurrentTime >= stopTime)
                {
                    nextTime += progressStep;
                    this.GuiAsync(() => TestingProcess.Value++);
                }
            };

            //_trader.StateChanged += () =>
            //{
            //    if (_trader.State == EmulationStates.Stopped)
            //    {
            //        this.GuiAsync(() =>
            //        {
            //            StartBtn.IsEnabled = true;

            //            if (Math.Abs(TestingProcess.Value - TestingProcess.Maximum) < double.Epsilon)
            //                MessageBox.Show("Закончено за " + (DateTime.Now - _startEmulationTime));
            //            else
            //                MessageBox.Show("Отменено");
            //        });
            //    }
            //    else if (_trader.State == EmulationStates.Started)
            //    {
            //        // запускаем стратегию когда эмулятор запустился
            //        _strategy.Start();
            //    }
            //};

            _trader.StateChanged += (oldState, newState) =>
            {
                if (_trader.State == EmulationStates.Stopped)
                {
                    this.GuiAsync(() =>
                    {
                        StartBtn.IsEnabled = true;

                        if (_trader.IsFinished)
                        {
                            TestingProcess.Value = TestingProcess.Maximum;
                            MessageBox.Show(this, "Закончено за " + (DateTime.Now - _startEmulationTime));
                        }
                        else
                            MessageBox.Show(this, "Отменено");
                    });
                }
                else if (_trader.State == EmulationStates.Started)
                {
                    // запускаем стратегию когда эмулятор запустился
                    _strategy.Start();
                }
            };

			// устанавливаем в визуальный элемент ProgressBar максимальное количество итераций)
			//TestingProcess.Maximum = (stopTime - startTime).Ticks;
			//TestingProcess.Value = 0;
			Report.IsEnabled = true;

			_startEmulationTime = DateTime.Now;

			// запускаем эмуляцию, задавая период тестирования (startTime, stopTime).
			_trader.Start(startTime, stopTime);
		}

		private void ReportClick(object sender, RoutedEventArgs e)
		{
			// сгерерировать отчет по прошедшему тестированию
			// Внимание! сделок и заявок может быть большое количество,
			// поэтому Excel отчет может тормозить
			new ExcelStrategyReport(_strategy, "sma.xls").Generate();

			// открыть отчет
			Process.Start("sma.xls");
		}
        
    //    private void DrawCandle(CandleSeries series, Candle candle)
    //    {
    //      //  if (candle.State == CandleStates.Finished) this.GuiAsync(() => Chart.ProcessCandle(_candlesElem, candle));
    //        var longValue = candle.State == CandleStates.Finished ? new ChartIndicatorValue(_longMaElem.Indicator, _longMaElem.Indicator.Process(candle)) : null;

    //        this.GuiAsync(() => Chart.ProcessValues(candle.OpenTime, new Dictionary<IChartElement, object>
    //{
    //    { _candlesElem, candle },
    //    { _longMaElem, longValue}
    //}));
    //    }

        private void ParametersPanel_Loaded(object sender, RoutedEventArgs e)
        {

        }
	}
}