using Binance.TradeRobot.Common.DI;
using Binance.TradeRobot.Model.Dto;
using Microsoft.Extensions.DependencyInjection;
using SDKAdapter.Model;
using SDKAdapter.WebSockets.Market;
using SDKAdapter.WebSockets.Order.Spot;
using System.Collections.Generic;
using System.Linq;

namespace Binance.TradeRobot.Business
{
    [BatchRegistration(ServiceLifetime.Singleton, RegistrationType.Self)]
    public class GlobalContext
    {
        private NLogManager logManager;
        private IDictionary<string, SpotMarketWebSocketClient> spotMarketWebSocketClientDictionary;
        private IDictionary<string, SpotOrderWebSocketClient> spotOrderWebSocketClientDictionary;
        private IEnumerable<ISpotOrderPublishBusiness> spotOrderPublishBusinessList;

        public GlobalContext(NLogManager logManager, IEnumerable<ISpotOrderPublishBusiness> spotOrderPublishBusinessList)
        {
            this.logManager = logManager;
            spotMarketWebSocketClientDictionary = new Dictionary<string, SpotMarketWebSocketClient>();
            spotOrderWebSocketClientDictionary = new Dictionary<string, SpotOrderWebSocketClient>();
            this.spotOrderPublishBusinessList = spotOrderPublishBusinessList;
        }

        /// <summary>
        /// 订阅K线
        /// </summary>
        /// <param name="robot"></param>
        public void SubscribeKLine(RobotResponse robot)
        {
            if (!spotMarketWebSocketClientDictionary.TryGetValue(robot.KLineKey, out SpotMarketWebSocketClient spotMarketWebSocketClient))
            {
                spotMarketWebSocketClient = SpotMarketWebSocketClient.Create(robot.ExchangeId, robot.Symbol, logManager.GetLogger(robot.KLineKey));
                spotMarketWebSocketClientDictionary.TryAdd(robot.KLineKey, spotMarketWebSocketClient);
            }
            spotMarketWebSocketClient.Start();
        }

        /// <summary>
        /// 取消订阅K线
        /// </summary>
        /// <param name="robot"></param>
        public void UnSubscribeKLine(RobotResponse robot)
        {
            //停止订阅k线
            if (spotMarketWebSocketClientDictionary.TryGetValue(robot.KLineKey, out SpotMarketWebSocketClient spotMarketWebSocketClient))
                spotMarketWebSocketClient.Stop();
        }

        /// <summary>
        /// 订阅订单推送
        /// </summary>
        /// <param name="robot"></param>
        public void SubscribeOrderPublish(RobotResponse robot)
        {
            if (!spotOrderWebSocketClientDictionary.TryGetValue(robot.OrderPublishKey, out SpotOrderWebSocketClient spotOrderWebSocketClient))
            {
                spotOrderWebSocketClient = SpotOrderWebSocketClient.Create(robot.BusinessType,
                                                                           robot.ExchangeId,
                                                                           robot.ExchangeAPIKey.AccountId,
                                                                           robot.ExchangeAPIKey.APIKey,
                                                                           robot.ExchangeAPIKey.SecretKey,
                                                                           logManager.GetLogger(robot.OrderPublishKey),
                                                                           OnSpotOrderPublish);
            }
            spotOrderWebSocketClient.Start(robot.Symbol);
        }



        /// <summary>
        /// 取消订阅订单推送
        /// </summary>
        /// <param name="robot"></param>
        public void UnSubscribeOrderPublish(RobotResponse robot)
        {
            if (spotOrderWebSocketClientDictionary.TryGetValue(robot.OrderPublishKey, out SpotOrderWebSocketClient spotOrderWebSocketClient))
                spotOrderWebSocketClient.Stop(robot.Symbol);
        }

        /// <summary>
        /// 获取指定交易对现货最新成交价
        /// </summary>
        /// <param name="kLineKey"></param>
        /// <returns></returns>
        public decimal? GetSpotNewestPrice(string kLineKey)
        {
            if (spotMarketWebSocketClientDictionary.TryGetValue(kLineKey, out SpotMarketWebSocketClient spotMarketWebSocketClient))
                return spotMarketWebSocketClient.NewestPrice;
            return null;
        }

        public void OnSpotOrderPublish(SpotOrderPublishInfo spotOrderPublishInfo)
        {
            var orderPublishBusiness = spotOrderPublishBusinessList.FirstOrDefault(p => p.TradePolicy == spotOrderPublishInfo.TradePolicy);
            orderPublishBusiness.OnSpotOrderPublish(spotOrderPublishInfo);
        }
    }
}