using eSuite.WorkBench.Models;
using eSuite.WorkBench.Services;
using eSuite.WorkBench.WpfHelper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace eSuite.WorkBench.Commands
{
    public class GetTagListCommand : AsyncCommandBase
    {
        private readonly IContainerRegistryClient _containerRegistryClient;
        private readonly MainWindowViewModel _mainWindowViewModel;

        public GetTagListCommand(MainWindowViewModel mainWindowViewModel, IContainerRegistryClient containerRegistryClient, Action<Exception> onException, EventHandler<FeedbackEventArgs> addFeedbackMessage) : base(onException)
        {
            FeedbackMessage += addFeedbackMessage;
            _containerRegistryClient = containerRegistryClient;
            _mainWindowViewModel = mainWindowViewModel;
        }

        protected override async Task ExecuteAsync(object parameter)
        {
            DoFeedbackMessage("Refreshing list...");

            _mainWindowViewModel.CombinedBranches.Clear();
            _mainWindowViewModel.Branches.Clear();

            var proxyTags = _containerRegistryClient.GetTagsListAsync("e-suite.proxy");
            var apiTags = _containerRegistryClient.GetTagsListAsync("e-suite.api");
            var uiTags = _containerRegistryClient.GetTagsListAsync("e-suite.webui");
            var dbMigratorTags = _containerRegistryClient.GetTagsListAsync("e-suite.database.migrator");
            var schedulerTags = _containerRegistryClient.GetTagsListAsync("e-suite.scheduler");
            var messageProcessorTags = _containerRegistryClient.GetTagsListAsync("e-suite.messageprocessor");

            var tasks = new List<Task<IEnumerable<string>>>
            {
                apiTags,
                uiTags,
                dbMigratorTags,
                schedulerTags,
                messageProcessorTags
            };

            await Task.WhenAll(tasks);

            foreach (var task in tasks)
                GetAllBranches(task.Result);

            foreach (var kv in _mainWindowViewModel.CombinedBranches)
            {
                var branch = new Branch(kv.Key, default, default);
                branch.BranchVersions = kv.Value.GroupBy(x => x)
                    .Select(g => g.First())
                    .Select(x => new Branch(x, null, branch))
                    .ToList();

                _mainWindowViewModel.Branches.Add(branch);
            }

            
            PopulateTags(proxyTags.Result, _mainWindowViewModel.AvailableProxyTags, _mainWindowViewModel.ProxyBranchesVersions);
            PopulateTags(apiTags.Result, _mainWindowViewModel.AvailableApiTags, _mainWindowViewModel.ApiBranchesVersions);
            PopulateTags(uiTags.Result, _mainWindowViewModel.AvailableWebUiTags, _mainWindowViewModel.WebUiBranchesVersions);
            PopulateTags(dbMigratorTags.Result, _mainWindowViewModel.AvailableDbMigratorTags,
                _mainWindowViewModel.DbMigratorBranchesVersions);
            PopulateTags(schedulerTags.Result, _mainWindowViewModel.AvailableSchedulerTags,
                _mainWindowViewModel.SchedulerBranchesVersions);
            PopulateTags(messageProcessorTags.Result, _mainWindowViewModel.AvailableMessageProcessorTags,
                _mainWindowViewModel.MessageProcessorBranchesVersions);
            DoFeedbackMessage("...finished refreshing list");
        }

        private void PopulateTags(IEnumerable<string> tags, SelectableObservableCollection<string> selectableCollection, Dictionary<string, List<string>> dictionary)
        {
            foreach (var apiTag in tags)
            {
                selectableCollection.Add(apiTag);

                var tagsList = new List<string>();

                var branchName = "master";
                var version = apiTag;
                var lastSeperator = apiTag.LastIndexOf('-');
                if (lastSeperator != -1)
                {
                    branchName = apiTag.Substring(lastSeperator + 1);
                    version = apiTag.Substring(0, lastSeperator);
                }
                
                if (dictionary.TryGetValue(branchName, out tagsList))
                {
                    tagsList.Add(version);
                }
                else
                {
                    var newTagsList = new List<string> { version };
                    dictionary.Add(branchName, newTagsList);
                }
            }
        }

        private void GetAllBranches(IEnumerable<string> tags)
        {
            foreach (var tag in tags)
            {
                var branch = tag.Substring(tag.IndexOf('-') + 1);

                if (branch.IndexOf('-') != -1)
                {
                    var feature = branch.Substring(branch.IndexOf('-') + 1);
                    List<string> featureList;
                    if (_mainWindowViewModel.CombinedBranches.TryGetValue(branch.Substring(0, branch.IndexOf('-')), out featureList))
                    {
                        if (featureList == null)
                        {
                            featureList = new List<string>();
                        }

                        featureList.Add(feature);
                    }
                    else
                    {
                        featureList = new List<string>();
                        featureList.Add(feature);

                        _mainWindowViewModel.CombinedBranches.Add(branch.Substring(0, branch.IndexOf('-')), featureList);
                    }
                }
                else
                {
                    if (!_mainWindowViewModel.CombinedBranches.ContainsKey(branch))
                    {
                        _mainWindowViewModel.CombinedBranches.Add(branch, new List<string>());
                    }
                }
            }
        }
    }
}
