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 HUOBIExchange : IExchange
    {
        #region Members
        internal class TickerType
        {
            /* GET /market/detail?symbol=ethusdt */
            /*             
                {
                  "status": "ok",
                  "ch": "market.btcusdt.detail",
                  "ts": 1489473538996,
                  "tick": {
                    "amount": 4316.4346,
                    "open": 8090.54,
                    "close": 7962.62,
                    "high": 8119.00,
                    "ts": 1489464451000,
                    "id": 1489464451,
                    "count": 9595,
                    "low": 7875.00,
                    "vol": 34497276.905760
                  }
                }
            */
            public object this[string propertyName]
            {
                get { return this.GetType().GetProperty(propertyName).GetValue(this, null); }
                set { this.GetType().GetProperty(propertyName).SetValue(this, value, null); }
            }
            public TickerItemType Tick { get; set; }
            [JsonProperty(PropertyName = "ts")]
            public long Timestamp { get; set; }
        }

        internal class TickerItemType
        {
            public object this[string propertyName]
            {
                get { return this.GetType().GetProperty(propertyName).GetValue(this, null); }
                set { this.GetType().GetProperty(propertyName).SetValue(this, value, null); }
            }
            public decimal Low { get; set; }
            public decimal High { get; set; }
            [JsonProperty(PropertyName = "close")]
            public decimal Last { get; set; }
            [JsonProperty(PropertyName = "vol")]
            public decimal Volume { get; set; }
        }

        private ExchangeSettings settings;
        #endregion

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

        public async Task<IEnumerable<Ticker>> GetMarkets()
        {
            HttpClient client = new HttpClient();
            ///v1/common/symbols
            HttpResponseMessage response = await client.GetAsync(settings.ApiUrl + "v1/common/symbols");
            if (response.IsSuccessStatusCode)
            {
                var data = await response.Content.ReadAsJsonAsync<HUOBIResponse>();

                return data.Data.Where(s => settings.AllowedCurrencies.Contains(s.QuoteCurrency.ToUpper())).
                    Select(it => new Ticker() { TickerDisplayName = $"{it.BaseCurrency.ToUpper()}/{it.QuoteCurrency.ToUpper()}", Currency1 = Replace(it.BaseCurrency.ToUpper()), Currency2 = Replace(it.QuoteCurrency.ToUpper()), Currency = Replace(it.BaseCurrency.ToUpper()), TickerSymbol = $"{it.BaseCurrency.ToUpper()}{it.QuoteCurrency.ToUpper()}" });
            }
            throw new NotSupportedException("HUOBI error");
        }

        public async Task<TickerData> GetTickerData(TickerInfo ticker, DateTime start, DateTime end)
        {
            ///market/detail?symbol=ethusdt
            HttpClient client = new HttpClient();
            var response = await client.GetAsync($"{settings.ApiUrl}market/detail?symbol={ticker.Currency1.ToLower()}{ticker.Currency2.ToLower()}");
            if (response.IsSuccessStatusCode)
            {
                var data = await response.Content.ReadAsJsonAsync<TickerType>();

                return new TickerData()
                {
                    TickerTime = ConvertFromLong(data.Timestamp),
                    TickerId = ticker.TickerId,
                    Open = data.Tick.Low,
                    High = data.Tick.High,
                    Low = data.Tick.Low,
                    Close = data.Tick.Last,
                    Volume = data.Tick.Volume
                };
            }
            throw new NotSupportedException("HUOBI error");
        }

        #region Helpers        
        private long ConvertToLong(DateTime time)
        {
            return (long)(time - Constants._1970Time).TotalMilliseconds;
        }

        private DateTime ConvertFromLong(long ms)
        {
            return Constants._1970Time.AddMilliseconds(ms);
        }

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