using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebSocket.Clients;
using WebSocket.Interfaces;

namespace Knoks.CryptoExchanges.ExchangeClients
{
    class OKExExchange : IExchangeContainer
    {
        #region Members
        internal class PairSocket
        {
            public WebSocket4NetSocket socket { get; set; }
            public OKExClient client { get; set; }
            public Tuple<string, string> pair { get; set; }
        }
        private List<PairSocket> socketsPool;
        private int exchangeId;
        public UpdateData updateData { get; set; }
        public IDictionary<string, string> ReplaceSymbols { get; set; }
        #endregion

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="exchangeId"></param>
        public OKExExchange(int initExchangeId)
        {
            this.exchangeId = initExchangeId;
            socketsPool = new List<PairSocket>();
        }

        /// <summary>
        /// Init connection to exchange 
        /// </summary>
        /// <param name="saveDataEvent"></param>
        /// <returns></returns>
        public async Task InitClient(UpdateData saveDataEvent)
        {
            this.updateData = saveDataEvent;
            await Task.CompletedTask;
        }

        /// <summary>
        /// Start pairs requesting
        /// </summary>
        /// <param name="pairs"></param>
        /// <returns></returns>
        public async Task RequestPairsData(List<Tuple<string, string>> pairs)
        {
            foreach (var pair in pairs)
            {
                var poolItem = socketsPool.FirstOrDefault(x => x.pair == pair);
                if (poolItem == null)
                {

                    var socket = new OKExWebsocket4Net();
                    socket.Create("wss://real.okex.com:10441/websocket");
                    socket.Sign((s) => new ConsoleWebClient(
                        this.updateData,
                        this.exchangeId,
                        (ss) =>
                        {
                            var client = new OKExClient(ss);
                            poolItem = new PairSocket()
                            {
                                socket = socket,
                                client = client,
                                pair = pair
                            };
                            socketsPool.Add(poolItem);
                            return client;
                        }, s));

                    await poolItem.socket.Connect();
                    poolItem.client.StartRequest(new string[] { $"{pair.Item1}_{pair.Item2}" });
                }
            }

            var socketsToStop = socketsPool.Where(socket => !pairs.Contains(socket.pair));
            await Task.WhenAll(socketsToStop.Select(x => x.socket.Close()));

            socketsPool.RemoveAll(socket => !pairs.Contains(socket.pair));
        }

        /// <summary>
        /// Close connection for all pool items
        /// </summary>
        /// <returns></returns>
        public async Task CloseConnection()
        {
            await Task.WhenAll(this.socketsPool.Select(x => x.socket.Close()));
        }

        /// <summary>
        /// Force to reconnect
        /// </summary>
        /// <returns></returns>
        public async Task Reconnect()
        {
            await Task.CompletedTask;
        }
    }
}
