using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using WebSocket.Interfaces;
using System.Linq;
using Bitfinex.Client.Websocket.Responses.Candles;

namespace WebSocket.Clients
{
    public class BitfinexClient : IWebClient
    {
        #region Members
        private Dictionary<string, Action<Command, string>> CommandAnswers = new Dictionary<string, Action<Command, string>>();
        private IWebSocketForClient server;
        #endregion

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="server"></param>
        public BitfinexClient(IWebSocketForClient server)
        {
            this.server = server;
            //Register();
        }

        public void Connected()
        {
            //SendAuth();
            //wait connected message?
        }
        
        //private void Register()
        //{
        //}

        public void Message(string message)
        {
            var parse = JsonConvert.DeserializeObject<BinanceModel>(message, GetSettings());
            if (parse.data != null && CommandAnswers.ContainsKey(parse.data.e))
            {
                CommandAnswers[parse.data.e](parse, message);
            }
        }

        public void Tick()
        {
            //'ticker' or 'get-balance'
        }

        public void Data(byte[] data)
        {
        }

        public void Data(Dictionary<string, object> data)
        {
            this.server.DataChanged("Bitfinex", GetMarketOHLCVData(data));
        }

        public void Closed(bool byUser, string reason)
        {
            //subscribed = false;
        }

        public void Error(Exception ex)
        {
        }

        public void Error(string reason)
        {
        }

        public void SendFailed(string data, Exception ex)
        {
        }

        private void Send(object obj)
        {
            server.Send(JsonConvert.SerializeObject(obj, GetSettings()));
        }

        private void SendPong()
        {
            Send(new Command() { E = "pong" });
        }

        private void On(string name, Action<Command, string> command)
        {
            CommandAnswers[name] = command;
        }

        private void Off(string name)
        {
            if (CommandAnswers.ContainsKey(name))
            {
                CommandAnswers.Remove(name);
            }
        }

        public Dictionary<string, IMarketOHLCVData> GetMarketOHLCVData(Dictionary<string, object> data)
        {
            return data.Where(x => x.Value != null).Select(x =>
            {
                var item = ((Candle)x.Value);
                return new MarketOHLCVData()
                {
                    PairSymbol = x.Key,
                    HighPrice = (decimal)item.High,
                    LowPrice = (decimal)item.Low,
                    OpenPrice = (decimal)item.Open,
                    ClosePrice = (decimal)item.Close,
                    Volume = (decimal)item.Volume,
                    TimeStamp = item.Mts
                } as IMarketOHLCVData;
            }
            ).ToDictionary(x => x.PairSymbol);

            //return data.Select(x => new MarketOHLCVData()
            //{
            //    PairSymbol = x.Key,
            //    HighPrice = (decimal)x.Value.High,
            //    LowPrice = (decimal)x.Value.Low,
            //    OpenPrice = (decimal)x.Value.Open,
            //    ClosePrice = (decimal)x.Value.Close,
            //    Volume = (decimal)x.Value.Volume,
            //    TimeStamp = x.Value.Mts
            //} as IMarketOHLCVData).ToDictionary(x => x.PairSymbol);
        }

        private JsonSerializerSettings GetSettings()
        {
            var settings = new JsonSerializerSettings()
            {
                ContractResolver = new LowerCaseUnderscoreContractResolver()
                //Formatting = Formatting.Indented
            };
            //settings.Converters.Add(new MicrosoftSecondsDateTimeConverter()); 
            return settings;
        }
    }
}
