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

namespace Knoks.Core.Exchanges
{
    public class BinanceExchange : IExchange
    {
        private ExchangeSettings settings;

        public BinanceExchange(ExchangeSettings settings)
        {
            this.settings = settings;
            this.settings.ApiUrl = settings.ApiUrl ?? "https://api.binance.com/api/";
        }
        public async Task<IEnumerable<Ticker>> GetMarkets()
        {
            HttpClient client = new HttpClient();
            HttpResponseMessage response = await client.GetAsync(settings.ApiUrl + "v1/exchangeInfo");//https://api.binance.com/api/v1/exchangeInfo
            if (response.IsSuccessStatusCode)
            {
                var data = await response.Content.ReadAsJsonAsync<Binance.ExchangeInfo>();
                return data.Symbols.Where(s => settings.AllowedCurrencies.Contains(s.QuoteAsset.ToUpper()))
                    .Select(it => new Ticker() { TickerDisplayName = $"{it.BaseAsset}/{it.QuoteAsset}", Currency1 = Replace(it.BaseAsset), Currency2 = Replace(it.QuoteAsset), Currency = Replace(it.BaseAsset), TickerSymbol = it.Symbol });//Status
            }
            throw new NotSupportedException("Binance error");
        }

        public async Task<TickerData> GetTickerData(TickerInfo ticker, DateTime start, DateTime end)
        {
            HttpClient client = new HttpClient();
            var response = await client.GetAsync($"{settings.ApiUrl}v1/klines?symbol={ticker.TickerSymbol}&interval=1m&startTime={ConvertToLong(start)}");
            if (response.IsSuccessStatusCode)
            {
                var data = await response.Content.ReadAsJsonAsync<List<List<JValue>>>();
                var it = data.FirstOrDefault();
                return new TickerData()
                {
                    TickerTime = ConvertFromLong(it[0].ToObject<long>()),
                    TickerId = ticker.TickerId,
                    TickState = 0,
                    Interval ='M',
                    Open = it[1].ToObject<decimal>(),
                    High = it[2].ToObject<decimal>(),
                    Low = it[3].ToObject<decimal>(),
                    Close = it[4].ToObject<decimal>(),
                    Volume = it[5].ToObject<decimal>()
                    //Id = it[0].ToObject<string>()
                };
            }
            throw new NotSupportedException("Binance error");
        }
        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;
        }
    }
}
