using Knoks.Core.Data.Interfaces;
using Knoks.Core.Entities;
using Knoks.Framework.DataAccess;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Knoks.Core.Data.Dao
{
    public class ExchangeDao : IExchangeDao
    {
        private IProcExecutor executor;
        public ExchangeDao(IProcExecutor executor)
        {
            this.executor = executor;
        }
        public async Task<IEnumerable<Currency>> GetCurrencies(string currency)
        {
            return (await executor.Go("BO_Currencies", new { currency })).Тables[0].ToList<Currency>();
        }
        public async Task<IEnumerable<Currency>> GetFilterCurrencies(long? userId, bool? availableKnoks, bool? activeKnoks, bool? endedKnoks)
        {
            return (await executor.Go("BO_FilterCurrencies", new { availableKnoks, activeKnoks, endedKnoks, userId })).Тables[0].ToList<Currency>();
        }
        public async Task<IEnumerable<Exchange>> GetExchanges(long? userId, bool? availableKnoks, bool? activeKnoks, bool? endedKnoks, int? exchangeId = null )
        {
            var res = await executor.Go("BO_ExchangeCurrencies", new { ExchangeId = exchangeId, AvailableKnoks = availableKnoks ?? false, ActiveKnoks = activeKnoks ?? false, EndedKnoks = endedKnoks ?? false, UserId = userId });
            var r = res.Тables[0].ToList<ExchangeData>().GroupBy(it => new { id = it.ExchangeId, name = it.ExchangeName });
            return r.Select(it => 
                new Exchange()
                {
                    ExchangeId = it.Key.id,
                    ExchangeName = it.Key.name,
                    CurrencyPairs = it
                        .Select(c =>new CurrencyPair() {
                            Currency1 = c.Currency1,
                            Currency2 = c.Currency2,
                            Currency = c.Currency,
                            DisplayName = c.TickerDisplayName
                        }).ToList()
                }
            );
        }

        public async Task<TickerInfo> GetTicker(int tickerId)
        {
            return (await executor.Go("BO_GetTickers", new { TickerId = tickerId })).Тables[0].ToList<TickerInfo>().First();
        }

        public async Task<TickerInfo> GetTicker(int exchangeId, string currency1, string currency2)
        {
            return (await executor.Go("BO_GetTickers", new { TickerId = (int?)null, ExchangeId = exchangeId, Currency1 = currency1, Currency2 = currency2 })).Тables[0].ToList<TickerInfo>().First();
        }
        
        public async Task<IEnumerable<TickerInfo>> GetTickers()
        {
            return (await executor.Go("BO_GetTickers")).Тables[0].ToList<TickerInfo>();
        }

        public async Task<TickerInfo> SaveExchanges(TickerData data)
        {
           
            return (await executor.Go("Agg_1Minute", data)).Тables[0].ToList<TickerInfo>().First();
        }

        public async Task SaveTickers(int exchangeId, IEnumerable<Ticker> data)
        {
            await Task.Run(() =>
            {
                var list = GetExchanges(null, null, null, null, exchangeId).GetAwaiter().GetResult();
                var current = list?.SingleOrDefault();
                if (current != null)
                {
                    var active = data.ToList();
                    var add = active.Where(it => !current.CurrencyPairs.Any(e => e.Currency1 == it.Currency1 && e.Currency2 == it.Currency2)).ToList();
                    var remove = current.CurrencyPairs.Where(it => !active.Any(e => e.Currency1 == it.Currency1 && e.Currency2 == it.Currency2)).ToList();
                    add.ForEach(it => executor.Go("BO_AddTicker", it, new { ExchangeId = exchangeId }));
                    remove.ForEach(it => executor.Go("BO_RemoveTicker", new { ExchangeId = exchangeId, it.Currency1, it.Currency2 }));
                }
            });
        }

        private class ExchangeData
        {
            public short ExchangeId { get; set; }
            public string ExchangeName { get; set; }
            public string Currency1 { get; set; }
            public string Currency2 { get; set; }
            public string Currency { get; set; }
            public string TickerDisplayName { get; set; }
        }
    }
}
