using System;
using System.Collections.Generic;
using System.Linq;
using Ecng.Common;
using StockSharp.Algo;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace TestBag02
{
    internal class Strategy03 : Strategy
    {
        private readonly TimeSpan _timeError = TimeSpan.FromSeconds(3); // погрешность синхронизации локального и биржевого времени
        private bool _flagBuy, _flagSell;   // флаги направления входа

        protected override void OnStarted()
        {
            Console.WriteLine(@"{0} Strategy OnStarted: {1} BeginValue={2} CurrentValue={3} Position={4}",
                TimeHelper.Now.TimeOfDay, Name, Portfolio.BeginValue, Portfolio.CurrentValue, Position);
            
            _flagBuy = true;
            _flagSell = true;

            Connector.NewTrades += Connector_NewTrades;
            Connector.ValuesChanged += Connector_ValuesChanged;
            Connector.NewMyTrades += Connector_NewMyTrades;
            base.OnStarted();
        }

        private void Connector_NewMyTrades(IEnumerable<MyTrade> trades)
        {
            foreach (var trade in trades)
            {
                Console.WriteLine(@"{0} Прошла сделка {5} {4} по цене {1}, объём {2}, направление {3}.",
                    TimeHelper.Now.TimeOfDay, trade.Trade.Price, trade.Trade.Volume, trade.Order.Direction,
                    trade.Trade.Security.Code, trade.Trade.Id);
            }
        }

        private void Connector_ValuesChanged(Security security, IEnumerable<KeyValuePair<Level1Fields, object>> values,
            DateTimeOffset serverTime, DateTimeOffset localTime)
        {
            if (TimeHelper.Now - serverTime > _timeError) return;
            
            // получение необходимых данных для анализа
            if (security.Code == "RIM7")
            {
                // Жаль что эти данные получаю не так как при реальном соединении
                var _BidsCount = values.FirstOrDefault(kvp => kvp.Key == Level1Fields.BidsCount).Value;
                var _AsksCount = values.FirstOrDefault(kvp => kvp.Key == Level1Fields.AsksCount).Value;
                var _OpenInterest = values.FirstOrDefault(kvp => kvp.Key == Level1Fields.OpenInterest).Value;
            }
            if (security.Code == "SiM7")
            {
            }
        }

        private void Connector_NewTrades(IEnumerable<Trade> trades)
        {
            foreach (var trade in trades)
            {
                //пропускаем историю
                if (TimeHelper.Now - trade.Time > _timeError) return;
                
                //получение и анализ необходимых данных для входа в позу
                if (trade.Security.Code == "MICEXINDEXCF")
                {
                }
                if (trade.Security.Code == "SiM7")
                {
                }
                if (trade.Security.Code == "RIM7")
                {
                }

                // переворотная система всегда в рынке 1 конём
                // покупка
                if (_flagBuy && NoActiveOredrs && NoChildrenStrategies)
                {
                    _flagBuy = false;
                    _flagSell = false;
                    var volume = (Position < 0 ? (-1)*Position : 0) + 1;
                    var order = this.BuyAtMarket(volume);

                    AnalizOrder(order);
                    RegisterOrder(order);
                }

                // продажа
                if (_flagSell && NoActiveOredrs && NoChildrenStrategies)
                {
                    _flagBuy = false;
                    _flagSell = false;
                    var volume = (Position > 0 ? Position : 0) + 1;
                    var order = this.SellAtMarket(volume);

                    AnalizOrder(order);
                    RegisterOrder(order);
                }
            }
        }

        private void AnalizOrder(Order order)
        {
            order.WhenCanceled(Connector)
                .Do(() =>
                {
                    Console.WriteLine(@"{0} Заявка успешно отменена {1} {2} Volume={3} Price={4}",
                        TimeHelper.Now.TimeOfDay, order.Direction, order.Security.Code, order.Volume, order.Price);

                    if (order.Direction == Sides.Buy)
                        _flagBuy = true;
                    else
                        _flagSell = true;
                })
                .Once()
                .Apply(this);

            order
                .WhenRegistered(Connector)
                .Do(() => { Console.WriteLine(@"{0} Заявка успешно зарегестрирована", TimeHelper.Now.TimeOfDay); })
                .Once()
                .Apply(this);

            order
                .WhenRegisterFailed(Connector)
                .Do(() =>
                {
                    Console.WriteLine(@"{0} Заявка не принята биржей  {1} {2} Volume={3} Price={4}",
                        TimeHelper.Now.TimeOfDay, order.Direction, order.Security.Code, order.Volume, order.Price);

                    if (order.Direction == Sides.Buy)
                        _flagBuy = true;
                    else
                        _flagSell = true;
                })
                .Once()
                .Apply(this);

            order
                .WhenMatched(Connector)
                .Do(() =>
                {
                    Console.WriteLine(
                        @"{0} Заявка {2} {3} полностью исполнена Volume={4}. Позиция {1} AveragePrice={5}",
                        TimeHelper.Now.TimeOfDay, Position, order.Direction, order.Security.Code, order.Volume,
                        order.GetAveragePrice(Connector));

                    if (Position > 0) _flagSell = true;
                    if (Position < 0) _flagBuy = true;
                    if (Position == 0) Console.WriteLine("!!!!!!!!!!");
                })
                .Once()
                .Apply(this);
        }

        //*--------Проверки на вход------*/
        private bool NoActiveOredrs
        {
            get { return Orders.Count(o => o.State == OrderStates.Active) == 0; }
        }

        private bool NoPositions
        {
            get { return PositionManager.Positions.All(p => p.Value == 0); }
        }

        private bool NoChildrenStrategies { get { return !ChildStrategies.Any(s => s is IStrategyChildStrategyList); } }

        protected override void OnStopped()
        {
            CancelActiveOrders(); // Отменить все ордера
            this.ClosePosition(); // закрыть позу по рынку
            base.OnStopped();
        }
    }
}