using Knoks.Core.Entities;
using Knoks.Core.Logic.Interfaces;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace Knoks.Core.Exchanges
{
    public class BitfinexExchange : IExchange
    {
        #region Members
        internal class TickerType
        {
            public object this[string propertyName]
            {
                get { return this.GetType().GetProperty(propertyName).GetValue(this, null); }
                set { this.GetType().GetProperty(propertyName).SetValue(this, value, null); }
            }
            /*
            0{"mid":"0.069812",
            1"bid":"0.069791",
            2"ask":"0.069833",
            3"last_price":"0.069791",
            4"low":"0.068682",
            5"high":"0.070229",
            6"volume":"7313.0993800100005",
            7"timestamp":"1531400781.645441"}
            */
            public decimal Mid { get; set; }
            [JsonIgnore]
            public decimal Bid { get; set; }
            [JsonIgnore]
            public decimal Ask { get; set; }
            public decimal Last_price { get; set; }
            public decimal Low { get; set; }
            public decimal High { get; set; }
            public decimal Volume { get; set; }
            public decimal Timestamp { get; set; }
        }
        private ExchangeSettings settings;
        #endregion

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="settings"></param>
        public BitfinexExchange(ExchangeSettings settings)
        {
            this.settings = settings;
            this.settings.ApiUrl = settings.ApiUrl ?? "https://api.bitfinex.com/";
        }

        public async Task<IEnumerable<Ticker>> GetMarkets()
        {
            //var handler = new HttpClientHandler();
            //handler.ClientCertificateOptions = ClientCertificateOption.Manual;
            //handler.ServerCertificateCustomValidationCallback =
            //(httpRequestMessage, cert, cetChain, policyErrors) =>
            //{
            //    return true;
            //};
            //ServicePointManager.ServerCertificateValidationCallback =
            //    new RemoteCertificateValidationCallback(
            //        delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
            //        {
            //            return true;
            //        });
            HttpClient client = new HttpClient();
            HttpResponseMessage response = await client.GetAsync(settings.ApiUrl + "v1/symbols");//https://api.bitfinex.com/v1/symbols
            if (response.IsSuccessStatusCode)
            {
                var data = await response.Content.ReadAsJsonAsync<IEnumerable<string>>();
                var parse = data.Select(it => new Tuple<string, string>(it.Substring(0, 3).ToUpper(), it.Substring(3, 3).ToUpper()));
                return parse.Where(s => settings.AllowedCurrencies.Contains(s.Item2.ToUpper()))
                    .Select(it => new Ticker() { TickerDisplayName = $"{it.Item1}/{it.Item2}", Currency1 = Replace(it.Item1), Currency2 = Replace(it.Item2), Currency = Replace(it.Item1), TickerSymbol = it.Item1 + it.Item2 });//Active
            }
            throw new NotSupportedException("Bitfinex error");
        }

        public async Task<TickerData> GetTickerData(TickerInfo ticker, DateTime start, DateTime end)
        {
            HttpClient client = new HttpClient();            
            var response = await client.GetAsync($"{settings.ApiUrl}v1/pubticker/{ticker.TickerSymbol}");
            if (response.IsSuccessStatusCode)
            {
                var data = await response.Content.ReadAsJsonAsync<TickerType>();
                
                return new TickerData() {
                    TickerTime = DateTime.UtcNow, // ConvertFromLong(Decimal.ToInt32(data.Timestamp)),
                    TickerId = ticker.TickerId,
                    Open = data.Low,
                    High = data.High,
                    Low = data.Low,
                    Close = data.Last_price,
                    Volume = data.Volume
                };
            }
            throw new NotSupportedException("Bitfinex error");
        }

        #region Helpers
        private DateTime ConvertFromLong(long ms)
        {
            return new DateTime(DateTime.UtcNow.Date.Millisecond + ms);
        }

        private string Replace(string asset)
        {
            if (settings.ReplaceSymbols != null && settings.ReplaceSymbols.ContainsKey(asset))
            {
                return settings.ReplaceSymbols[asset];
            }
            return asset;
        }
        #endregion
    }
}
